[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\n\n# A special property that should be specified at the top of the file outside of\n# any sections. Set to true to stop .editor config file search on current file\nroot = true\n\n[*]\n# Indentation style\n# Possible values - tab, space\nindent_style = space\n\n# Indentation size in single-spaced characters\n# Possible values - an integer, tab\nindent_size = 2\n\n# Line ending file format\n# Possible values - lf, crlf, cr\nend_of_line = lf\n\n# File character encoding\n# Possible values - latin1, utf-8, utf-16be, utf-16le\ncharset = utf-8\n\n# Denotes whether to trim whitespace at the end of lines\n# Possible values - true, false\ntrim_trailing_whitespace = true\n\n# Denotes whether file should end with a newline\n# Possible values - true, false\ninsert_final_newline = true"
  },
  {
    "path": ".eslintignore",
    "content": "/node_modules/\ndist/\n/website/schema2Markdown.js"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "# fdc3-maintainers will be default reviewers for everything in the repo unless a later match takes precedence\n* @finos/fdc3-maintainers\n\n# Any changes to this CODEOWNERS file should be reviewed by finos-admins\n/.github/CODEOWNERS @finos/finos-admins\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---context_or_intent_proposal.md",
    "content": "---\nname: \"✉️ Context or Intent proposal\"\nabout: Propose new contexts and intents to help implement a particular use-case!\ntitle: ''\nlabels: enhancement, Context Data & Intents\nassignees: ''\n---\n\n## Enhancement Request\n\n### Use Case\n\n<!--- \nPlease specify at least one use case that the proposed additions would support\n\nFor example:\n> User may want to view current positions for a list of securities\n--->\n\n### Intents\n\n#### \\<intent name goes here\\>\n\n<!---\nBrief description of purpose\nInclude indication of input and output context types (if any)\n--->\n\n### Contexts\n\n#### \\<context name goes here\\>\n\n<!--- Brief description of purpose\n--->\n\n##### Details\n\n| Property    | Type    | Required | Example Value       |\n|-------------|---------|----------|---------------------|\n| `type`      | string  | Yes      | `'fdc3.instrument'` |\n| `name`      | string  | No       | `'Microsoft'`       |\n| `id.ticker` | string  | No       | `'MSFT'`            |\n| `id.BBG`    | string  | No       | `'MSFT:US'`         |\n\n##### Example\n\n<!---\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n```\n--->\n\n### Additional Information\n<!---\nPlease add any other information that can provide additional detail for this enhancement request\n--->"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---enhancement-request.md",
    "content": "---\nname: \"\\U0001F680 Enhancement Request\"\nabout: Propose an addition or change to the FDC3 standard!\ntitle: ''\nlabels: enhancement\nassignees: ''\n---\n\n## Enhancement Request\n\n### Use Case\n\n<!--- Please specify at least one use case that this enhancement would support\n\nA use case should not be a solution, but a description of a problem from an end user point of view.  \n\nFor example: \n> Often, end users want to link from one app to another to dynamically create a workflow without prior knowledge of the app they want to connect to.  For example, using the 'share' feature allows an end user to dynamically discover what apps they have that support social sharing and no advanced knowledge is required by the end user. --->\n\n### Workflow Description\n\n<!--- clearly and concisely describe the target workflow for the proposed enhancement --->\n\n### Workflow Examples\n\n<!--- provide one or more concrete examples of the proposed workflow --->\n\n### Additional Information\n\n<!--- please add any other information that can provide additional detail for this enhancement request --->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---minor-issue.md",
    "content": "---\nname: \"\\U0001F41B Minor Issue\"\nabout: \"If something isn't as expected \\U0001F914.\"\ntitle: ''\nlabels: bug\nassignees: ''\n---\n\n## Minor Issue\n\n<!-- Please use minor issues for discrepancies or errors found in the spec or supporting documentation, examples, and other materials.  If you wish to propose a new feature or a revision to an existing feature, please use the *Enhancement Request* template. -->\n\n### Area of Issue\n\n- [ ] App Directory\n- [ ] API\n- [ ] Context Data\n- [ ] Intents\n- [ ] Desktop Agent Bridging\n- [ ] Use Cases\n- [ ] Other\n\n### Issue Description\n\n<!--- please provide a detailed description of the issue  --->\n\n### Additional Context\n\n<!--- Add any other context about the problem here. If applicable, add screenshots to help explain...  --->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---question.md",
    "content": "---\nname: \"\\U0001F917 Question\"\nabout: \"If you have a questions about FDC3. \\U0001F4AC\"\ntitle: 'Question: '\nlabels: 'question'\nassignees: ''\n---\n\n### Question Area\n\n- [ ] App Directory\n- [ ] API\n- [ ] Context Data\n- [ ] Intents\n- [ ] Use Cases\n- [ ] Other\n\n### Question\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/general-meeting.md",
    "content": "---\nname: General Meeting\nabout: minutes for an FDC3 General Meeting\ntitle: 'General Meeting - mmm dd, yyyy'\nlabels: General meeting, meeting\nassignees: ''\n---\n\n## Date\n\nDD MMM yyyy - 10am EST / 3pm GMT\n\n### Zoom info\n\n- **[Join Zoom Meeting](https://zoom.us/j/96940294948?pwd=SjFibVdiN25QSWxva3FqRHY2RUFCdz09)**\n- **Meeting ID:** 969 4029 4948\n- **Passcode:** 636931\n- **Dial-in:**\n    | Country      | International Dial-in | Toll-free Dial-in |\n    | :---        | :---        | :---        |\n    | **US** | [+1 929 205 6099 (New York)](tel:+19292056099) | [877 853 5247](tel:8778535247) |\n    | **UK** | [+44 330 088 5830](tel:+443300885830) | [0800 031 5717](tel:08000315717) |\n    | **France** | [+33 1 8699 5831](tel:+33186995831) | [0 800 940 415](tel:0800940415) \n    | Find your local number | <https://zoom.us/u/ad2WVnBzb8> | |\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact <legal@finos.org> with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n\n## Participation Requirements\n\n**Note:** Meeting participants are expected to accept the terms of the FDC3 license (Community Specification License), understand the governance process and have a CLA in place.  \n\nPlease click the following links at the start of the meeting if you have not done so previously.\n\n- [View the CSL](https://github.com/finos/FDC3/blob/main/LICENSE.md)\n- [View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n- [Click here to start a PR](https://github.com/finos/FDC3/edit/main/NOTICES.md). \n  - Edit the page to add your details.\n  - Hit the save button.\n  - Click \"Create Pull Request\".\n  - Click \"Accept\" on the EasyCLA dialog in the PR's discussion section.\n- [Click here to send email to become a voting participant on the FDC3 Project](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&amp;body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!\")\n\n## Tracking Attendance\n\n**Note:** Meeting participants are expected to _add a comment to this GitHub issue_ in order that we can track attendance of FDC3 project meetings.  Please do this at the start of the meeting.\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (10mins)\n\n## Decisions Made\n\n- ...\n\n## Action Items\n\n- [ ] ...\n\n## Untracked attendees\n\n| Full name | Affiliation | GitHub username |\n|-----------|-------------|-----------------|\n|           |             |                 |\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/identity-and-security-meeting.md",
    "content": "---\nname: Identity and Security group meeting\nabout: Overview and notes for a discussion group\ntitle: 'Identity and Security group meeting - mmm dd, yyyy'\nlabels: identity-security, meeting\nassignees: ''\n---\n\n## Meeting Date\n\nThursday DD MMM yyyy - 10am (US eastern timezone EST/EDT) / 3pm (London, GMT/BST)\n\n### Zoom info\n\nRegister to the meeting series and receive and invitation:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/92600977319?password=17e9e8f8-7d4e-47b4-b8f0-8c68b02005de&invite=true\n\nJoin Zoom Meeting:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/92600977319?password=17e9e8f8-7d4e-47b4-b8f0-8c68b02005de\n\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact <legal@finos.org> with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n  \n- A Discussion Group has no direct decision-making power regarding the FDC3 standard - rather it is intended that anything they propose or work on will result in proposals (via Github issues and PRs) for the Standards Working Group participants to consider and vote on for inclusion in the standard.\n\n## Participation Requirements\n\n**Note:** Meeting participants are expected to accept the terms of the FDC3 license (Community Specification License), understand the governance process and have a CLA in place.  \n\nPlease click the following links at the start of the meeting if you have not done so previously.\n\n- [View the CSL](https://github.com/finos/FDC3/blob/main/LICENSE.md)\n- [View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n- [Click here to start a PR](https://github.com/finos/FDC3/edit/main/NOTICES.md).\n  - Edit the page to add your details.\n  - Hit the save button.\n  - Click \"Create Pull Request\".\n  - Click \"Accept\" on the EasyCLA dialog in the PR's discussion section.\n- [Click here to send email to become a voting participant on the FDC3 Project](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&amp;body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!\")\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (5mins)\n\n## Minutes\n\n- ...\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/maintainers-meeting.md",
    "content": "---\nname: FDC3 Maintainers Meeting\nabout: minutes for an FDC3 Maintainers Meeting\ntitle: 'FDC3 Maintainers Meeting - mmm dd, yyyy'\nlabels: project governance, meeting\nassignees: ''\n---\n\n## Date\n\nWednesday DD MMM yyyy - 9am (US eastern timezone EST/EDT) / 2pm (London, GMT/BST)\n\n### Zoom info\n\nSee calendar invite\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact legal@finos.org with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n\n## Participation Requirements\n\nBy invitation of the FDC3 maintainers\n\n[View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (5mins)\n\n## Minutes\n\n- ...\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/standard-wg-meeting.md",
    "content": "---\nname: Standard WG Meeting\nabout: minutes for an FDC3 Standard Working Group Meeting\ntitle: 'Standard WG Meeting - mmm dd, yyyy'\nlabels: Standard WG Meeting, meeting\nassignees: ''\n---\n\n## Date\n\nThursday DD MMM yyyy - 10am (US eastern timezone EST/EDT) / 3pm (London, GMT/BST)\n\n### Zoom info\n\nRegister to the meeting series to receive an invitation:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/96839365264?password=b5c2bc6a-bc47-43a5-bc49-7be3e0b422c3&invite=true\n\nJoin Zoom Meeting:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/96839365264?password=b5c2bc6a-bc47-43a5-bc49-7be3e0b422c3\n\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact legal@finos.org with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n\n## Participation Requirements\n\n **Note:** Meeting participants are expected to accept the terms of the FDC3 license (Community Specification License), understand the governance process and have a CLA in place.  \n\n Please click the following links at the start of the meeting if you have not done so previously.\n\n- [View the CSL](https://github.com/finos/FDC3/blob/main/LICENSE.md)\n- [View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n- [Click here to start a PR](https://github.com/finos/FDC3/edit/main/NOTICES.md).\n  - Edit the page to add your details.\n  - Hit the save button.\n  - Click \"Create Pull Request\".\n  - Click \"Accept\" on the EasyCLA dialog in the PR's discussion section.\n- [Click here to send email to become a voting participant on the FDC3 Project](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&amp;body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!\")\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (5mins)\n\n## Minutes\n\n- ...\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/use-cases-and-workflows-meeting.md",
    "content": "---\nname: Use Cases and Workflows group meeting\nabout: Overview and notes for a discussion group\ntitle: 'Use Cases and Workflows group meeting - mmm dd, yyyy'\nlabels: Use cases, meeting\nassignees: ''\n---\n\n## Meeting Date\n\nThursday DD MMM yyyy - 10am (US eastern timezone EST/EDT) / 3pm (London, GMT/BST)\n\n### Zoom info\n\n\nRegister to the meeting series and receive an invitation:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/91001005768?password=0c878e0c-b8a4-42d3-9786-e8c1524d6d1c&invite=true\n\nJoin Zoom Meeting:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/91001005768?password=0c878e0c-b8a4-42d3-9786-e8c1524d6d1c\n\n\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact <legal@finos.org> with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n  \n- A Discussion Group has no direct decision-making power regarding the FDC3 standard - rather it is intended that anything they propose or work on will result in proposals (via Github issues and PRs) for the Standards Working Group participants to consider and vote on for inclusion in the standard.\n\n## Participation Requirements\n\n**Note:** Meeting participants are expected to accept the terms of the FDC3 license (Community Specification License), understand the governance process and have a CLA in place.  \n\nPlease click the following links at the start of the meeting if you have not done so previously.\n\n- [View the CSL](https://github.com/finos/FDC3/blob/main/LICENSE.md)\n- [View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n- [Click here to start a PR](https://github.com/finos/FDC3/edit/main/NOTICES.md).\n  - Edit the page to add your details.\n  - Hit the save button.\n  - Click \"Create Pull Request\".\n  - Click \"Accept\" on the EasyCLA dialog in the PR's discussion section.\n- [Click here to send email to become a voting participant on the FDC3 Project](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&amp;body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!\")\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (5mins)\n\n## Minutes\n\n- ..."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/web-browsers-meeting.md",
    "content": "---\nname: Web Browsers group meeting\nabout: Overview and notes for a discussion group\ntitle: 'Web Browsers group meeting - mmm dd, yyyy'\nlabels: FDC3 for Web Browsers, meeting\nassignees: ''\n---\n\n## Meeting Date\n\nThursday DD MMM yyyy - 10am (US eastern timezone EST/EDT) / 3pm (London, GMT/BST)\n\n### Zoom info\n\n\nRegister to the meeting series to receive an invitation:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/96615992377?password=88ed4841-afa2-41a6-8de3-e246967e5566&invite=true\n\nJoin Zoom Meeting:\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/96615992377?password=88ed4841-afa2-41a6-8de3-e246967e5566\n\n## Meeting notices\n\n- FINOS **Project leads** are responsible for observing the FINOS guidelines for [running project meetings](https://community.finos.org/docs/governance/meeting-procedures/). Project maintainers can find additional resources in the [FINOS Maintainers Cheatsheet](https://community.finos.org/docs/finos-maintainers-cheatsheet).\n\n- **All participants** in FINOS project meetings are subject to the [LF Antitrust Policy](https://www.linuxfoundation.org/antitrust-policy/), the [FINOS Community Code of Conduct](https://community.finos.org/docs/governance/code-of-conduct) and all other [FINOS policies](https://community.finos.org/docs/governance/#policies).\n\n- FINOS meetings involve participation by industry competitors, and it is the intention of FINOS and the Linux Foundation to conduct all of its activities in accordance with applicable antitrust and competition laws. It is therefore extremely important that attendees adhere to meeting agendas, and be aware of, and not participate in, any activities that are prohibited under applicable US state, federal or foreign antitrust and competition laws. Please contact <legal@finos.org> with any questions.\n\n- FINOS project meetings may be recorded for use solely by the FINOS team for administration purposes. In very limited instances, and with explicit approval, recordings may be made more widely available.\n  \n- A Discussion Group has no direct decision-making power regarding the FDC3 standard - rather it is intended that anything they propose or work on will result in proposals (via Github issues and PRs) for the Standards Working Group participants to consider and vote on for inclusion in the standard.\n\n## Participation Requirements\n\n**Note:** Meeting participants are expected to accept the terms of the FDC3 license (Community Specification License), understand the governance process and have a CLA in place.  \n\nPlease click the following links at the start of the meeting if you have not done so previously.\n\n- [View the CSL](https://github.com/finos/FDC3/blob/main/LICENSE.md)\n- [View the GOVERNANCE of the Project](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md)\n- [Click here to start a PR](https://github.com/finos/FDC3/edit/main/NOTICES.md).\n  - Edit the page to add your details.\n  - Hit the save button.\n  - Click \"Create Pull Request\".\n  - Click \"Accept\" on the EasyCLA dialog in the PR's discussion section.\n- [Click here to send email to become a voting participant on the FDC3 Project](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&amp;body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!\")\n\n## Agenda\n\n- [ ] Convene & roll call, review meeting notices (5mins)\n- [ ] Review action items from previous meeting (5mins)\n- [ ] Agenda item 1\n- [ ] Agenda item 2\n- [ ] ...\n- [ ] AOB & Adjourn (5mins)\n\n## Minutes\n\n- ...\n\n## Action Items\n\n- [ ] ...\n\n## Untracked attendees\n\n| Full name | Affiliation | GitHub username |\n|-----------|-------------|-----------------|\n|           |             |                 |\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "## Describe your change\n\n<!--- Describe your change here-->\n\n### Related Issue\n<!--- This project prefers to accept pull requests related to open issues -->\n<!--- If suggesting a new feature or change, please discuss it in an issue first -->\n<!--- Please [link to the issue here](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue) by writing \"resolves #123456\" here: -->\n\n## Contributor License Agreement\n\n<!--- All contributions to FDC3 must be made under an active contributor license agreement and the [Community Specification License](https://github.com/finos/FDC3/blob/main/LICENSE.md). This will be checked by the EasyCLA tool (https://easycla.lfx.linuxfoundation.org/) that runs automatically on every PR. If you've not contributed to FDC3 before, look for a comment on your PR shortly after it is raised and follow the instructions to establish a CLA or have it acknowledged by the EasyCLA tool. -->\n\n- [ ] I acknowledge that a contributor license agreement is required and that I have one in place or will seek to put one in place ASAP.\n\n## Review Checklist\n\n<!--- \nIf you've changed docs or schemas make sure you run code and documentation tasks before raising your PR.\nTo do so, run: \n    - Code generation and build: `npm run build`\n    - Docs generation and preview `cd website; npm run start`\nOnce run, any modified files can be committed and added to your PR for review.\n--->\n<!--- Checklist to be completed by reviewers, and pre-checked by the authors of a PR -->\n\n- [ ] **Issue**: If a change was made to the FDC3 Standard, was an issue linked above?\n- [ ] **CHANGELOG**: Is a *CHANGELOG.md* entry included?\n- [ ] **API changes**: Does this PR include changes to any of the FDC3 APIs (`DesktopAgent`, `Channel`, `PrivateChannel`, `Listener`, `Bridging`)?\n  - [ ] **Docs & Sources**: If yes, were both documentation (/docs) and sources updated?<br/>\n        *JSDoc comments on interfaces and types should be matched to the main documentation in /docs*\n  - [ ] **Conformance tests**: If yes, are conformance test definitions (/toolbox/fdc3-conformance) still correct and complete?<br/>\n        *Conformance test definitions should cover all **required** aspects of an FDC3 Desktop Agent implementation, which are usually marked with a **MUST** keyword, and  optional features (**SHOULD** or **MAY**) where the format of those features is defined*\n  - [ ] **Schemas**: If yes, were changes applied to the Bridging and FDC3 for Web protocol schemas?<br/>\n        *The Web Connection protocol and Desktop Agent Communication Protocol schemas must be able to support all necessary aspects of the Desktop Agent API, while Bridging must support those aspects necessary for Desktop Agents to communicate with each other*\n    - [ ] If yes, was code generation (`npm run build`) run and the results checked in?<br/>\n        *Generated code will be found at `/src/api/BrowserTypes.ts` and/or `/src/bridging/BridgingTypes.ts`*\n- [ ] **Context types**: Were new Context type schemas created or modified in this PR?\n  - [ ] Were the [field type conventions](https://fdc3.finos.org/docs/context/spec#field-type-conventions) adhered to?\n  - [ ] Was the `BaseContext` schema applied via `allOf` (as it is in existing types)?\n  - [ ] Was a `title` and `description` provided for all properties defined in the schema?\n  - [ ] Was at least one example provided?\n  - [ ] Was code generation (`npm run build`) run and the results checked in?<br/>\n        *Generated code will be found at `/src/context/ContextTypes.ts`*\n- [ ] **Intents**: Were new Intents created in this PR?\n  - [ ] Were the [intent name prefixes](https://fdc3.finos.org/docs/intents/spec#intent-name-prefixes) and other [naming conventions & characteristics](https://fdc3.finos.org/docs/intents/spec#naming-conventions) adhered to?\n  - [ ] Was the new intent added to the list in the [Intents Overview](https://fdc3.finos.org/docs/intents/spec#standard-intents)?\n"
  },
  {
    "path": ".github/workflows/coverage.yml",
    "content": "name: Node.js CI Tests and Coverage\n\n# Controls when the workflow will run on any branch\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\n# Allows Coverage to be written back as a PR comment\npermissions: \n  pull-requests: write\n\n# Define the jobs for this workflow\njobs:\n  test:\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: read\n      id-token: write\n      pull-requests: write\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v6\n\n    - name: Set up Node.js\n      uses: actions/setup-node@v6\n      with:\n        node-version: 20.x\n\n    - name: Install dependencies\n      run: npm ci\n\n    - name: Lint\n      run: npm run lint\n\n    - name: Run tests\n      run: npm run test\n\n    - name: Codecov\n      uses: codecov/codecov-action@v6\n      with:\n        use_oidc: true\n"
  },
  {
    "path": ".github/workflows/cve-scanning.yml",
    "content": "name: Node.js CVE Scanning\n\non:\n  pull_request:\n    types: [opened, reopened, synchronize, ready_for_review]\n    paths:\n      - 'allow-list.json'\n      - 'package.json'\n      - 'toolbox/fdc3-workbench/package.json'\n      - '.github/workflows/cve-scanning.yml'\n      - 'website/package.json'\n  # push:\n  #   paths:\n  #     - 'package.json'\n  #     - 'toolbox/fdc3-workbench/package.json'\n  #     - '.github/workflows/cve-scanning.yml'\n  #     - 'website/package.json'\n  schedule:\n    # Run every day at 5am and 5pm\n    - cron: '0 5,17 * * *'\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [20]\n    steps:\n      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2\n        with:\n          node-version: ${{ matrix.node-version }}\n          \n      - run: npm install\n      \n      - run: npm install\n        working-directory: toolbox/fdc3-workbench\n\n      - run: npm install\n        working-directory: website\n\n      - run: npx --yes auditjs ossi --whitelist allow-list.json -u ${{ secrets.OSS_INDEX_USERNAME }} -p ${{ secrets.OSS_INDEX_TOKEN }}\n        if: success() || failure()\n        \n      - run: npx --yes auditjs ossi --whitelist ../allow-list.json -u ${{ secrets.OSS_INDEX_USERNAME }} -p ${{ secrets.OSS_INDEX_TOKEN }}\n        working-directory: website\n        if: success() || failure()\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "\nname: Publish To NPM\n\non:\n  release:\n    types: [published]\n\npermissions:\n  contents: read\n  id-token: write     # required for npm provenance\n  packages: write     # required for GitHub Packages publish\n\njobs:\n  build_and_pack:\n    name: Build and pack workspaces (once)\n    runs-on: ubuntu-latest\n    outputs:\n      is_prerelease: ${{ steps.version.outputs.is_prerelease }}\n      publish_tag: ${{ steps.version.outputs.publish_tag }}\n    steps:\n      - name: Checkout repo\n        uses: actions/checkout@v4\n\n      - name: Configure Node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Lint\n        run: npm run lint\n\n      - name: Run tests\n        run: npm run test\n\n      - name: Build\n        run: npm run build\n\n      - name: Verify version consistency across workspaces\n        run: npm run version-check\n\n      # Compute prerelease flag & desired dist-tag from top-level package.json version\n      - name: Determine prerelease tag\n        id: version\n        run: |\n          set -euo pipefail\n          VERSION=\"$(node -p 'JSON.parse(require(\"fs\").readFileSync(\"./package.json\",\"utf8\")).version')\"\n          echo \"Detected version: $VERSION\"\n\n          # If version contains a hyphen, it's a prerelease (e.g., 1.2.3-alpha.1)\n          if [[ \"$VERSION\" == *-* ]]; then\n            echo \"is_prerelease=true\"  >> \"$GITHUB_OUTPUT\"\n            echo \"publish_tag=prerelease\" >> \"$GITHUB_OUTPUT\"\n            echo \"This is a prerelease. Will use tag 'prerelease'.\"\n          else\n            echo \"is_prerelease=false\" >> \"$GITHUB_OUTPUT\"\n            echo \"publish_tag=latest\"  >> \"$GITHUB_OUTPUT\"\n            echo \"This is a stable release. Will use tag 'latest'.\"\n          fi\n\n      # Create tarballs for each public workspace so we can publish the exact same artifacts twice\n      - name: Pack workspaces (skip private)\n        run: |\n          set -euo pipefail\n          for ws in $(node -e '\n            const fs = require(\"fs\");\n            const read = (p) => JSON.parse(fs.readFileSync(p, \"utf8\"));\n            const root = read(\"./package.json\");\n            for (const dir of root.workspaces || []) {\n              const pkg = read(\"./\" + dir + \"/package.json\");\n              if (!pkg.private) console.log(dir);\n            }\n          '); do\n            echo \"Packing $ws ...\"\n            npm pack --workspace \"$ws\"\n          done\n          echo \"Packed tarballs:\"\n          ls -1 *.tgz\n\n      - name: Upload packed artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: npm-tarballs\n          path: |\n            ./*.tgz\n          if-no-files-found: error\n          retention-days: 7\n\n  publish_npm:\n    name: Publish to npmjs.org\n    runs-on: ubuntu-latest\n    needs: build_and_pack\n    steps:\n      - name: Checkout repo (required for npm provenance)\n        uses: actions/checkout@v4\n\n      - name: Download packed artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: npm-tarballs\n          path: ./dist-tarballs\n\n      - name: Configure Node for npmjs.org\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          registry-url: https://registry.npmjs.org\n          always-auth: true\n\n      - name: Publish tarballs to npmjs.org (with provenance and dist-tag)\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}   # npm automation token\n          PUBLISH_TAG: ${{ needs.build_and_pack.outputs.publish_tag }}\n        run: |\n          set -euo pipefail\n          shopt -s nullglob\n          for tgz in ./dist-tarballs/*.tgz; do\n            echo \"Publishing $tgz to npmjs.org with tag '${PUBLISH_TAG}' ...\"\n            # --access public needed for first publish of public packages\n            npm publish \"$tgz\" --provenance --access public --tag \"${PUBLISH_TAG}\"\n          done\n\n  publish_github:\n    name: Publish to GitHub Packages\n    runs-on: ubuntu-latest\n    needs: build_and_pack\n    steps:\n      - name: Download packed artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: npm-tarballs\n          path: ./dist-tarballs\n\n      - name: Configure Node for GitHub Packages\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          registry-url: https://npm.pkg.github.com\n          scope: '@finos'\n          always-auth: true\n\n      - name: Publish tarballs to GitHub Packages (with dist-tag)\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # has packages: write via permissions\n          PUBLISH_TAG: ${{ needs.build_and_pack.outputs.publish_tag }}\n        run: |\n          set -euo pipefail\n          shopt -s nullglob\n          for tgz in ./dist-tarballs/*.tgz; do\n            echo \"Publishing $tgz to GitHub Packages with tag '${PUBLISH_TAG}' ...\"\n            # GitHub Packages does not support npm provenance; omit --provenance and --access\n            npm publish \"$tgz\" --tag \"${PUBLISH_TAG}\"\n          done\n"
  },
  {
    "path": ".github/workflows/scorecard.yml",
    "content": "# This workflow uses actions that are not certified by GitHub. They are provided\n# by a third-party and are governed by separate terms of service, privacy\n# policy, and support documentation.\n\nname: Scorecard supply-chain security\non:\n  # For Branch-Protection check. Only the default branch is supported. See\n  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection\n  branch_protection_rule:\n  # To guarantee Maintained check is occasionally updated. See\n  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained\n  schedule:\n    # “At 17:05 on Friday”\n    - cron: '5 17 * * 5'\n  push:\n    branches: [ \"main\" ]\n\n# Declare default permissions as read only.\npermissions: read-all\n\njobs:\n  analysis:\n    name: Scorecard analysis\n    runs-on: ubuntu-latest\n    permissions:\n      # Needed to upload the results to code-scanning dashboard.\n      security-events: write\n      # Needed to publish results and get a badge (see publish_results below).\n      id-token: write\n      # Uncomment the permissions below if installing in a private repository.\n      # contents: read\n      # actions: read\n\n    steps:\n      - name: \"Checkout code\"\n        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n        with:\n          persist-credentials: false\n\n      - name: \"Run analysis\"\n        uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0\n        with:\n          results_file: results.sarif\n          results_format: sarif\n          # (Optional) \"write\" PAT token. Uncomment the `repo_token` line below if:\n          # - you want to enable the Branch-Protection check on a *public* repository, or\n          # - you are installing Scorecard on a *private* repository\n          # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.\n          repo_token: ${{ secrets.SCORECARD_TOKEN }}\n\n          # Public repositories:\n          #   - Publish results to OpenSSF REST API for easy access by consumers\n          #   - Allows the repository to include the Scorecard badge.\n          #   - See https://github.com/ossf/scorecard-action#publishing-results.\n          # For private repositories:\n          #   - `publish_results` will always be set to `false`, regardless\n          #     of the value entered here.\n          publish_results: false\n\n      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF\n      # format to the repository Actions tab.\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0\n        with:\n          name: SARIF file\n          path: results.sarif\n          retention-days: 5\n\n      # Upload the results to GitHub's code scanning dashboard (optional).\n      # Commenting out will disable upload of results to your repo's Code Scanning dashboard\n      - name: \"Upload to code-scanning\"\n        uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8\n        with:\n          sarif_file: results.sarif\n"
  },
  {
    "path": ".github/workflows/semgrep.yml",
    "content": "name: Static code analysis\n\non:\n  pull_request:\n    types: [opened, reopened, synchronize, ready_for_review]\n  schedule:\n    # Run every day at 5am and 5pm\n    - cron: '0 5,17 * * *'\n\npermissions:\n  contents: read\n\njobs:\n  semgrep:\n    name: run-semgrep\n    runs-on: ubuntu-latest\n    container:\n      image: returntocorp/semgrep\n    steps:\n    - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7\n    - run: semgrep scan --error --config auto\n      env:\n        SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.log\n.DS_Store\nnode_modules\ndist\ncoverage\n.project\n\nlib/core/metadata.js\nlib/core/MetadataBlog.js\n\nwebsite/translated_docs\nwebsite/build/\nwebsite/static/toolbox\nwebsite/node_modules\nwebsite/i18n/*\nwebsite/.docusaurus/\nwebsite/static/schemas/next/*\nwebsite/static/ui\ntest-results.xml\n\n\n.idea/\n*.iml\nwebsite/.yarn\n.nyc_output\ntoolbox/fdc3-for-web/fdc3-web-impl/generated/\ncucumber-report.html\nnyc-coverage-report/\n.history/\n.rollup.cache\ntsconfig.tsbuildinfo\n.vscode/launch.json"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\nnpx lint-staged \n"
  },
  {
    "path": ".node-version",
    "content": "22\n"
  },
  {
    "path": ".npmrc",
    "content": "# Omit the registry url which can be an organization's internal npm mirror when generating package-lock.json file\n# see: https://github.com/npm/cli/pull/4874\n# and https://docs.npmjs.com/cli/v8/using-npm/config#omit-lockfile-registry-resolved\nomit-lockfile-registry-resolved = true"
  },
  {
    "path": ".nvmrc",
    "content": "22\n"
  },
  {
    "path": ".prettierignore",
    "content": "# ignore files\n*.md\n*.html\n*.yml\n*.yaml\n*.json\n\n# ignore folders\nwebsite\ndist\nsrc/app-directory/*/target\nnode_modules\ncoverage\n.nyc_output\nbuild"
  },
  {
    "path": ".semgrepignore",
    "content": "website/**\n\n# Just used for build so ignoring\ns2tQuicktypeUtil.cjs\nt2sQuicktypeUtil.js\n\n# API schema set for localhost gets picked up by semgrep rule\nschemas/bridgingAsyncAPI/bridgingAsyncAPI.json\n\n# demo apps get picked up for not having integrity headers\ntoolbox/fdc3-for-web/demo/src/client/apps/**\n\n# Test utilities using controlled paths (false positive for path traversal)\npackages/testing/src/steps/generic.impl.ts\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"typescript.tsdk\": \"node_modules/typescript/lib\",\n    \"editor.tabSize\": 2,\n    \"editor.insertSpaces\": true\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).\n\n## [Unreleased]\n\n### Added\n\n* Added Go language binding. ([#1483](https://github.com/finos/FDC3/pull/1483))\n* Added details of and procedures for resolving fully-qualified appIds and unqualified appIds in the API and Bridging Parts of the Standard. ([#1523](https://github.com/finos/FDC3/pull/1523))\n* Added clarification regarding expected behavior upon repeated calls to `addContextListener` on same or overlapping types (allowed) and `addIntentListener` on same intent (rejected; new error type added). ([#1394](https://github.com/finos/FDC3/pull/1394))\n* Added `clearContext` function and associated `contextClearedEvent` to the `Channel` API, to be able to clear specific or all context types from the channel. ([#1379](https://github.com/finos/FDC3/pull/1379))\n* Added `version-check` script and integrated it into the `syncpack` script and Publish To NPM workflow to prevent version mismatches causing incorrect npm dist-tags. ([#1864](https://github.com/finos/FDC3/pull/1864))\n\n### Changed\n\n* Updated \"Releasing FDC3 to NPM\" instructions in README to reflect the current GitHub Actions release workflow. ([#1864](https://github.com/finos/FDC3/pull/1864))\n\n### Deprecated\n\n### Fixed\n\n## [npm v2.2.2] - 2026-04-13\n\n### Added\n\n* Added a notes field to Trade type ([#1563](https://github.com/finos/FDC3/pull/1563))\n* Added a notes field to Order and Product types ([#1597](https://github.com/finos/FDC3/pull/1597))\n* Added dynamic intent listener support to the reference Desktop Agent implementation ([#1613](https://github.com/finos/FDC3/pull/1613))\n* Ported FDC3 Conformance Project as-is into the FDC3 Monorepo, just including minimal fixes for typescript compilation. ([#1576](https://github.com/finos/FDC3/pull/1576))\n* Added Conformance tests for FDC3 2.2 ([#1586](https://github.com/finos/FDC3/pull/1586))\n* Added custom mocha test runner for conformance tests to better display test progress. ([#1769](https://github.com/finos/FDC3/pull/1769))\n\n### Changed\n\n* Converted the standalone app-directory specification test from `src/app-directory/specification/test/` into a test that runs as part of CI. ([#1720](https://github.com/finos/FDC3/pull/1720))\n* Fix for channel change listeners not sending addEventListenerRequests ([#1606](https://github.com/finos/FDC3/pull/1606))\n* When adding a listener on the current channel, the payload.channelId should be null ([#1611](https://github.com/finos/FDC3/pull/1611))\n* Increased FDC3 Conformance Test WindowCloseWaitTime to 2000 (from 1000). ([#1586](https://github.com/finos/FDC3/issues/1586))\n* Enhanced method binding for FDC3 API objects to support destructuring. All public methods of `Channel`, `PrivateChannel`, and `IntentResolution` objects are now properly bound to their instances using `.bind(this)` in their constructors. ([#1645](https://github.com/finos/FDC3/issues/1645))\n* Changed fdc3-web-impl to not deliver broadcast messages back to the sending application, as recommended (SHOULD) in the Standard. [#1749](https://github.com/finos/FDC3/pull/1749)\n* Removed version number prefix from conformance test names and implementation to simplify future maintenance. ([#1726](https://github.com/finos/FDC3/pull/1726))\n* Updated workbench from MUI 4 to MUI 5 ([#1714](https://github.com/finos/FDC3/pull/1714))\n* Modernized and standardised eslint configuration in all packages. ([#1823](https://github.com/finos/FDC3/pull/1823))\n* Reduced log messages in fdc3-web-impl to the debug level and removed logging of all messages recevied in the BroadcastHandler. ([#1851](https://github.com/finos/FDC3/pull/1851))\n\n### Fixed\n\n* Added support for passing `originatingApp` metadata to context listeners in `fdc3-agent-proxy` and `fdc3-web-impl`, matching the `ContextMetadata` spec for `addContextListener` callbacks. ([#1819](https://github.com/finos/FDC3/pull/1819))\n* Corrected /toolbox/fdc3-for-web/demo to only use MessagePort communication when 'Parent Post-Message' selected in the demo. ([#1695](https://github.com/finos/FDC3/pull/1695))\n* Corrected the property set in WCP1Hello by getAgent that indicates whether an intent resolver is needed. ([#1684](https://github.com/finos/FDC3/issues/1684))\n* Added unit tests to the fdc3-context package for validating context examples are valid schema.\n* Reverted schema of `fdc3.timeRange` context type back to use anyOf in place of oneOf for the `startTime` and `endTime` property combinations.  This will allow existence of one of either, or both, and pass schema validation.  When defined with oneOf, validation would fail due to multiple entries being valid and it could not identify which to apply. ([#1592](https://github.com/finos/FDC3/issues/1592))\n* Reverted schema of `fdc3.interaction` context type back to use anyOf in place of oneOf for the `interactionType` property.  Since it could be a string enum or a string, validation could not differentiate. ([#1598](https://github.com/finos/FDC3/issues/1598))\n* Fixed `fdc3.timeRange` context example to use correctly formatted dateTime. ([#1599](https://github.com/finos/FDC3/issues/1599))\n* Removed broken sourcemaps from npm package output ([#1589](https://github.com/finos/FDC3/issues/1589))\n* Fixed the `fdc3-commonjs` build to include `d.ts` files and corrects the config for easier consumption in different environments. ([#1694](https://github.com/finos/FDC3/issues/1694))\n* Updated .NET API documentation for IListener.Unsubscribe to be async for 2.2 and current. ([#1690](https://github.com/finos/FDC3/pull/1690))\n* Fix for channel change listeners not sending addEventListenerRequests ([#1606](https://github.com/finos/FDC3/pull/1606))\n* Fix to ensure that Adding A Channel Change Event Listener Doesn't Send addEventListenerRequest - Conformance 2.2 ([#1606](https://github.com/finos/FDC3/pull/1606))\n* Updated Conformance tests to allow agents that fully qualify app Ids (as recommended in the Standard) to pass the conformance tests ([#1767](https://github.com/finos/FDC3/pull/1767))\n* Fixed import file extensions and module type to be esm module compliant ([#1677](https://github.com/finos/FDC3/pull/1677))\n* Added mising context types to types and enums in. ContextTypes.ts and implemented tests to ensure they stay in sync with the fdc3-context package ([#1796](https://github.com/finos/FDC3/pull/1796))\n* Allowed retrieval of User channels as App channels via getOrCreateChannel and getCurrentChannel in fdc3-web-impl. ([#1835](https://github.com/finos/FDC3/pull/1835))\n* Corrected description of UCBasic3 in the fdc-conformance framework implementation. ([#1823](https://github.com/finos/FDC3/pull/1823))\n* Fixed a race condition in fdc3-workbench's context store which caused the context listeners on user channels to miss replay of current context in some cases. ([#1823](https://github.com/finos/FDC3/pull/1823))\n* Fixed lint in the fdc3-workbench implementation. ([#1823](https://github.com/finos/FDC3/pull/1823))\n* Stopped fdc3-workbench flagging FDC3 version 2.2 as unsupported. ([#1841](https://github.com/finos/FDC3/pull/1841))\n* Resolved vulnerable dependencies (esbuild, serialize-javascript, elliptic) and consolidated shared devDependencies to simplify future maintenance. ([#1841](https://github.com/finos/FDC3/pull/1841))\n* Fixed the lack of handling of WCP6Disconnect messages in MessagePort example in the FDC3 Web reference implementation. ([#1854](https://github.com/finos/FDC3/pull/1854))\n* Fixed handling of DesktopAgents that start apps joined to a user channel by the agent-proxy by retrieving the current user channel on start-up. ([#1858](https://github.com/finos/FDC3/pull/1858))\n* Fixed a race condition in `DefaultChannelSupport` initialization where the current user channel was retrieved asynchronously without being awaited, which could cause apps started on a user channel by the Desktop Agent to miss their initial channel assignment. ([#1858](https://github.com/finos/FDC3/pull/1858))\n\n## [FDC3 Standard 2.2](https://github.com/finos/FDC3/compare/v2.1..v2.2) - 2025-03-12\n\n### Added\n\n* Added clarification that `id` field values SHOULD always be strings to context schema definition (a restriction that can't easily be represented in the generated types). ([#1149](https://github.com/finos/FDC3/pull/1149))\n* Added requirement that Standard versions SHOULD avoid the use unions in context and API definitions wherever possible as these can be hard to replicate and MUST avoid unions of primitive types as these can be impossible to replicate in other languages. ([#120](https://github.com/finos/FDC3/pull/1200))\n* Added `addEventListener` to the `DesktopAgent` API to provide support for event listener for non-context and non-intent events, including a `userChannelChanged` event ([#1207](https://github.com/finos/FDC3/pull/1207))\n* Added an `async` `addEventListener` function to the `PrivateChannel` API to replace the deprecated, synchronous `onAddContextListener`, `onUnsubscribe` and `onDisconnect` functions and to keep consistency with the DesktopAgent API. ([#1305](https://github.com/finos/FDC3/pull/1305))\n* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108))\n* Specifications for getAgent() and Browser-Resident Desktop Agents. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* Specification for Preload Desktop Agents. This content was previously in the supported platforms section. It had been revised and amended to include recommended behavior related to the new validateAppIdentity() function. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* Typescript definitions for getAgent() and related types. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* Typescript definitions for Desktop Agent Communication Protocol (DACP). These constitute the internal \"wire protocol\" that the \"@finos/fdc3\" library uses to communicate with Browser-Resident DAs. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* Typescript definitions for Web Connection Protocol (WCP). These constitute the messages used to establish connectivity between \"@finos/fdc3\" and a Browser-Resident DA. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* Added support for broadcast actions to the `fdc3.action` context type, allowing an Action to represent the broadcast of a specified context to an app or user channel. ([#1368](https://github.com/finos/FDC3/pull/1368))\n* Added utility functions `isStandardContextType(contextType: string)`, `isStandardIntent(intent: string)`,`getPossibleContextsForIntent(intent: StandardIntent)`. ([#1139](https://github.com/finos/FDC3/pull/1139))\n* Added support for event listening outside of intent or context listnener. Added new function `addEventListener`, type `EventHandler`,  enum `FDC3EventType` and interfaces `FDC3Event` and `FDC3ChannelChangedEvent`. ([#1207](https://github.com/finos/FDC3/pull/1207))\n* Added new `CreateOrUpdateProfile` intent. ([#1359](https://github.com/finos/FDC3/pull/1359))\n* Added conformance tests into the FDC3 API documentation in the current version and back-ported into 2.0 and 2.1. Removed outdated 1.2 conformance tests (which are preserved in the older 2.0 and 2.1 versions). ([#1417](https://github.com/finos/FDC3/pull/1417)).\n* Added conformance tests to documentation for features introduced in FDC3 2.2 (`fdc3.addEventListener`, `PrivateChannel.addEventListener` and `getAgent`). ([#1425](https://github.com/finos/FDC3/pull/1425))\n* Added separate `fdc3-commonjs` module for compatibility with older projects that use CommonJS. ([#1452](https://github.com/finos/FDC3/pull/1452))\n* Added testing policy to [Contributing](CONTRIBUTING) page to address ([810](https://github.com/finos/FDC3/issues/810))\n* Added the ability to control logging to the JS console from getAgent() and the DesktopAgentProxy via arguments to getAgent(). ([#1495](https://github.com/finos/FDC3/pull/1495))\n* Added the ability for a browser-based DesktopAgent to control the timeouts used in the DesktopAgentProxy when making calls to it, via properties in WCP3Handshake message. ([#1497](https://github.com/finos/FDC3/pull/1497))\n* Added .NET docs for Events to API reference. ([#1441](https://github.com/finos/FDC3/pull/1441))\n* Setup package publishing for mono-repo packages. ([#1520](https://github.com/finos/FDC3/pull/1520))\n* Implementation PR for FDC3 for the Web ([#896](https://github.com/finos/FDC3/pull/896))\n  * resolves ([#1209](https://github.com/finos/FDC3/issues/1209))\n  * resolves ([#1297](https://github.com/finos/FDC3/issues/1297))\n  * resolves ([#1429](https://github.com/finos/FDC3/issues/1429))\n  * resolves ([#1430](https://github.com/finos/FDC3/issues/1430))\n  * resolves ([#1431](https://github.com/finos/FDC3/issues/1431))\n  * resolves ([#1432](https://github.com/finos/FDC3/issues/1432))\n  * resolves ([#1433](https://github.com/finos/FDC3/issues/1433))\n  * resolves ([#1468](https://github.com/finos/FDC3/issues/1468))\n  * resolves ([#810](https://github.com/finos/FDC3/issues/810))\n  * resolves ([#832](https://github.com/finos/FDC3/issues/832))\n  * resolves ([#1487](https://github.com/finos/FDC3/issues/1487))\n  * resolves ([#1488](https://github.com/finos/FDC3/issues/1488))\n* Adjusted reference Desktop Agent implementation for FDC3 for Web to open a new app instance when raiseIntent is called with an appId but no instanceId ([#1556](https://github.com/finos/FDC3/pull/1556))\n\n### Changed\n\n* `window.fdc3` is now an optional property and may or may not be defined. Applications should now use `getAgent()` as the recommended way of retrieving a reference to the FDC3 API. ([#1386](https://github.com/finos/FDC3/pull/1386))\n* `Listener.unsubscribe()` was made async (the return type was changed from `void` to `Promise<void>`) for consistency with the rest of the API. ([#1305](https://github.com/finos/FDC3/pull/1305))\n* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108))\n* The supported platforms page in the FDC3 documentation was moved into the API section as the information it provides all relates to FDC3 Desktop Agent API implementations. ([#1108](https://github.com/finos/FDC3/pull/1108))\n* FDC3 apps are now encouraged to instantiate their FDC3 interface (DesktopAgent) using the `getAgent()` function provided by the `@finos/fdc3` module. This will allow apps to interoperate in either traditional Preload DAs (i.e. Electron) as well as the new Browser-Resident DAs. ([#1191](https://github.com/finos/FDC3/pull/1191))\n* `ContextType` and `Intent` (`string`) types were created for use in DesktopAgent API signatures - they are unions of standardized values and `string`, enabling autocomplete/IntelliSense in IDEs when working with the FDC3 API. ([#1139](https://github.com/finos/FDC3/pull/1139))\n* SessionStorage use by `getAgent` was updated to scope the stored data by `window.name` and the app's `identityUrl`. ([#1442](https://github.com/finos/FDC3/pull/1442))\n* FDC3 Workbench updated to use `getAgent()` rather than `fdc3Ready()`\n\n### Deprecated\n\n* Made `IntentMetadata.displayName` optional as it is deprecated. ([#1280](https://github.com/finos/FDC3/pull/1280))\n* Deprecated `PrivateChannel`'s synchronous `onAddContextListener`, `onUnsubscribe` and `onDisconnect` functions in favour of an `async` `addEventListener` function consistent with the one added to `DesktopAgent` in #1207. ([#1305](https://github.com/finos/FDC3/pull/1305))\n* The `ContextTypes` and `Intents` enums were deprecated in favour of the new ContextType and Intent unions. ([#1139](https://github.com/finos/FDC3/pull/1139))\n\n### Fixed\n\n* Spin off fileAttachment into its own schema, and correct related examples ([1255](https://github.com/finos/FDC3/issues/1255))\n* Added missing `desktopAgent` field to ImplementationMetadata objects returned for all agents connect to a DesktopAgent bridge in Connection Step 6 connectAgentsUpdate messages and refined the schema used to collect this info in step 3 handshake. ([#1177](https://github.com/finos/FDC3/pull/1177))\n* Removed the `version` field from `IntentResolution` as there are no version fields for intents in the FDC3 API definitions and hence the field has no purpose. ([#1170](https://github.com/finos/FDC3/pull/1170))\n* Fixed error in the Client-side example from `PrivateChannel` and `addIntentListener` by correcting `id.symbol` to `id.ticker` to align with the `fdc3.instrument` context. ([#1314](https://github.com/finos/FDC3/pull/1314))\n* Added missing `resultType` argument to `findIntent` agent request in the Bridging Schema. ([#1154](https://github.com/finos/FDC3/pull/1154))\n* Added missing `resultType` argument to `findIntentByContext` agent request in the Bridging Schema. ([#1212](https://github.com/finos/FDC3/pull/1212))\n* Added missing id and name fields from the context base schema to respective context schemas (`Contact`, `ContactList`, `Country`, `InstrumentList`, `OrderList`, `Organization`, `Portfolio`, `Position`, `TradeList`). ([#1360](https://github.com/finos/FDC3/pull/1360))\n* Revised FDC3 charter to include well-known language from the FDC3 introduction, better describe FDC3's scope, focus on financial applications, update application types, etc. ([#1079](https://github.com/finos/FDC3/pull/1079))\n* Ensured that `PrivateChannelEvent` extends `ApiEvent` in both sourcecode and documentation. ([#1474](https://github.com/finos/FDC3/pull/1474))\n* Standardized prettier config for fdc3-workbench with other packages. ([#1520](https://github.com/finos/FDC3/pull/1520))\n* Ensured that user channel changes made by the DA without a call to joinUserChannel (i.e. those driven by an external channel selector) are applied by the Desktop Agent Proxy. ([#1541](https://github.com/finos/FDC3/pull/1541))\n* Ensured that the FDC3 Workbench and apps like it that are migrated to getAgent will still work with FDC3 1.2 Preload-based DAs by not requiring appMetadata properties to be present in getInfo() responses. ([#1550](https://github.com/finos/FDC3/pull/1550))\n* Bound all DesktopAgentProxy functions to enable destructuring. ([#1550](https://github.com/finos/FDC3/pull/1550))\n* Fixed polyfill of node.js JS modules in fdc3-workbench. ([#1550](https://github.com/finos/FDC3/pull/1550))\n\n## [npm v2.1.1] - 2024-06-28\n\n### Fixed\n\n* Corrected inconsistent camel-casing of the `fdc3.timeRange` context type which appeared as `fdc3.timerange` in a number of places. ([#1240](https://github.com/finos/FDC3/pull/1240))\n* Corrected an error in the `fdc3.TransactionResult` schema which resulted in the `message` property being omitted from the generated TypeScript types for it. ([#1251](https://github.com/finos/FDC3/pull/1251))\n\n## [FDC3 Standard 2.1](https://github.com/finos/FDC3/compare/v2.0..v2.1) - 2023-09-13\n\n### Added\n\n* Added `CreateInteraction` intent. To be used when a user wants to record an interaction into a system.  New context `Interaction` also introduced. An interaction might be a call, IM, email, a meeting (physical or virtual) or the preparation of some specialist data. ([#747](https://github.com/finos/FDC3/pull/747))\n* Added `TransactionResult` context. A context type representing the result of a transaction initiated via FDC3. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object. ([#761](https://github.com/finos/FDC3/pull/761))\n* Added a `MalformedContext` error to the `OpenError`, `ChannelError` and `ResolveError` enumerations, to be used when `broadcast`, `open`, `findIntents`, `raiseIntents`, and other related functions are passed an invalid context Object. ([#972](https://github.com/finos/FDC3/pull/972))\n* Added error examples to the /v2 App Directory API routes ([#973](https://github.com/finos/FDC3/pull/973))\n* Added a `SendChatMessage` intent to be used when a user wants to send a message to an existing chat room. ([#794](https://github.com/finos/FDC3/pull/794))\n* Added a context type representing a chat message (`fdc3.chat.message`). ([#794](https://github.com/finos/FDC3/pull/794))\n* Added a context type representing a chat room (`fdc3.chat.room`). ([#794](https://github.com/finos/FDC3/pull/794))\n* Added a chat `Message` type in order to describe messages with rich content and attachments. ([#779](https://github.com/finos/FDC3/pull/779))\n* Added an `Action` type, encapsulating either a `Context` or the association of a `Context` with an `Intent` inside another object.  ([#779](https://github.com/finos/FDC3/pull/779))\n* Added a `ViewChat` Intent to be used when a user wants to open an existing chat room. ([#796](https://github.com/finos/FDC3/pull/796))\n* Added a `ViewMessages` intent to be used when a user wants to search and see a list of messages. ([#797](https://github.com/finos/FDC3/pull/797))\n* Added a context type representing a ChatSearchCriteria (`fdc3.chat.searchCriteria`). ([#797](https://github.com/finos/FDC3/pull/797))\n* Added an indication that applications, that can be launched to receive intents or context via a raised intent or open with context, SHOULD add their context or intent listeners via the API within 15 seconds, and that Desktop Agents MUST allow at least a 15 second timeout for them to do so, and MAY set a longer timeout  ([#987](https://github.com/finos/FDC3/pull/987))\n* Added [@experimental](https://fdc3.finos.org/docs/fdc3-compliance#experimental-features) `Order`, `OrderList`, `Product`, `Trade` & `TradeList` context types. ([#1021](https://github.com/finos/FDC3/pull/1021))\n* Added Agent Bridging as an [@experimental](https://fdc3.finos.org/docs/fdc3-compliance#experimental-features) 5th part of the FDC3 Standard. ([#968](https://github.com/finos/FDC3/pull/968))\n* Added a description of the standards use of JSON Schema to define context types and Bridging messages. ([#1020](https://github.com/finos/FDC3/pull/1020))\n* Documentation for standardized Context types was added to their JSON Schema files and TypeScript interfaces generated from them, so that they may act as a 'single source of truth' for Context definitions. ([#1020](https://github.com/finos/FDC3/pull/1020))\n\n### Changed\n\n* Updated definition of the `ChatInitSettings` context type to use the new `Message` type.  ([#779](https://github.com/finos/FDC3/pull/779))\n* Updated the `StartChat` intent to return a reference to the room. ([#794](https://github.com/finos/FDC3/pull/794))\n* Updated definition of the `Instrument` context type to include optional market identifiers ([#819](https://github.com/finos/FDC3/pull/819))\n* Corrected API functions and object types to always use `string` instead of `String` ([#924](https://github.com/finos/FDC3/pull/924))\n* Updated definition of the `otherConfig` element of the `Chart` context type from an Object to an array of Contexts as this allows the `type` of each additional item of config to be examined before it is used ([#985](https://github.com/finos/FDC3/pull/985))\n* Corrected the appD `interop.appChannels` metadata to use an `id` field to identify channels, rather than `name` ([#981](https://github.com/finos/FDC3/pull/981))\n* The App Directory OpenAPI schema was converted from YAML to JSON Schema, containing the same definitions. ([#1035](https://github.com/finos/FDC3/pull/1035))\n* Switched to union types (from enums) for constrained string values in generated source files as they provide better type checking and cross-compatibility of types. ([#1093](https://github.com/finos/FDC3/pull/1093))\n\n### Deprecated\n\n* Deprecated the `name` field in AppD records, to match the deprecation of API signatures and metadata objects using `name` (see [#722](https://github.com/finos/FDC3/pull/722)) in 2.0. ([#928](https://github.com/finos/FDC3/pull/928))\n* Deprecated `IntentMetadata.displayName` and the appD record's `interop.intents.listensFor[].displayName` field in favor of using intent names for display (which are required to be recognizable) as it can be set differently for each application in the appD ([#926](https://github.com/finos/FDC3/pull/926))\n* Deprecated the `customConfig` field in an AppD record due to the lack of a standard API to retrieve it. To be replaced with an `applicationConfig` element with a Desktop Agent API call to retrieve it in a future version (see [#1006](https://github.com/finos/FDC3/issues/1006) for more details). Also deprecates the `customCOnfig` element of an Intent configuration due to a lack of documented use cases. ([#982](https://github.com/finos/FDC3/pull/982))\n\n### Fixed\n\n* Removed the union type for the `ChatMessage` context, which caused issues for languages not having union types. This is a breaking change (made before the final version of 2.1 is released).\n* Corrected chatInitSettings context schema to incorporate the Context schema. ([#869](https://github.com/finos/FDC3/pull/869))\n* Corrected schema syntax in chatInitSettings and renamed the `public` property to `isPublic` (as `public` is a reserved keyword in javascript). ([#875](https://github.com/finos/FDC3/pull/875))\n* Further clarified the difference between the behavior of User channels and other channel types on joinUserChannel/addContextListener. ([#971](https://github.com/finos/FDC3/pull/971))\n* Clarified description of the behavior of `IntentResolution.getResult()` when the intent handler returned void (which is not an error). ([#1004](https://github.com/finos/FDC3/pull/1004))\n* An error was fixed in the appD schema where launch details sub-schemas were combined with `oneOf`, rather than `anyOf`. This causes validation errors for web or online native apps as their details elements overlap on a `url` field. ([#1034](https://github.com/finos/FDC3/pull/1034))\n* The appD `icon` and `screenshot` sub-schemas were updated to require the `src` value is set and restrict additional values, ensuring that common mistakes (such as using a `url` rather than `src` field are caught by the schemas when used to validate). ([#1037](https://github.com/finos/FDC3/pull/1037))\n* Linting, spell checking other corrections were applied to markdown syntax throughout the FDC3 documentation ([#1032](https://github.com/finos/FDC3/pull/1032))\n* Corrected bad example URLs in the App Directory overview/discovery page in the current and past versions as they did not agree with the paths provided in the API specification and OpenAPI schema.  ([#1060](https://github.com/finos/FDC3/pull/1060))\n\n## [npm v2.0.3] - 2023-05-31\n\n### Changed\n\n* Applied missing `readonly` tags to `ImplementationMetadata.optionalFeatures` sub-properties. ([#1008](https://github.com/finos/FDC3/pull/1008))\n\n## [npm v2.0.2] - 2023-05-24\n\n### Changed\n\n* Removed source files from the NPM module as they are not necessary, increase the bundle size and include POM files that lack license info, causing issues for enterprise onboarding. ([#999](https://github.com/finos/FDC3/pull/999))\n\n## [FDC3 Standard 2.0](https://github.com/finos/FDC3/compare/v1.2..v2.0) - 2022-07-01\n\n### Added\n\n* Definition of the `icons` property of `AppMetadata`, based on PWA icon spec ([#319](https://github.com/finos/FDC3/pull/319))\n* Added support for raiseIntent without a context via the addition of the `fdc3.nothing` context type ([#375](https://github.com/finos/FDC3/pull/375))\n* Added [**FDC3 Workbench**](https://fdc3.finos.org/toolbox/fdc3-workbench/), an FDC3 API developer application ([#457](https://github.com/finos/FDC3/pull/457))\n* Added advice on how to `broadcast` complex context types, composed of other types, so that other apps can listen for both the complex type and simpler constituent types ([#464](https://github.com/finos/FDC3/pull/464))\n* 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))\n* 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))\n* 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))\n* 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))\n* Added `IntentDeliveryFailed` to the `ResolveError` enumeration to be used when delivery of an intent and context to a targeted app or instance fails. ([#601](https://github.com/finos/FDC3/pull/601))\n* Added an `instanceId` (and optional `instanceMetadata`) field to `AppMetadata` allowing it to refer to specific app instances and thereby supporting targeting of intents to specific app instances. Also added a `findInstances()` function to the desktop agent and `TargetAppUnavailable` and `TargetInstanceUnavailable` Errors to the `ResolveError` enumeration. ([#509](https://github.com/finos/FDC3/pull/509))\n* 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))\n* Added a Trademarks page to website to acknowledge trademarks used within the Standard not owned by FINOS or the Linux Foundation ([#534](https://github.com/finos/FDC3/pull/534))\n* Added details of FDC3's existing versioning and deprecation policies to the FDC3 compliance page ([#539](https://github.com/finos/FDC3/pull/539))\n* Added a new experimental features policy, which exempts features designated as experimental from the versioning and deprecation policies, to the FDC3 compliance page ([#549](https://github.com/finos/FDC3/pull/549))\n* Added a recommended set of user channel definitions to the API docs and typescript sources ([#727](https://github.com/finos/FDC3/pull/727))\n* Added the optional exposure of originating app metadata to messages received via `addContextListener` and `addIntentListener` via the new `ContextMetadata` type. ([#725](https://github.com/finos/FDC3/pull/725))\n* Added the current app's `AppMetadata` to the `ImplementationMetadata` returned by `fdc3.getInfo()` allowing an app to retrieve its own metadata, according to the Desktop Agent ([#726](https://github.com/finos/FDC3/pull/726))\n* Added a context type representing a range of time (`fdc3.timeRange`). ([#706](https://github.com/finos/FDC3/pull/706))\n* Added a context type representing a Currency (`fdc3.currency`). ([#708](https://github.com/finos/FDC3/pull/708))\n* Added a context type representing the price and value of a holding (`fdc3.valuation`). ([#709](https://github.com/finos/FDC3/pull/709))\n* Added a context type representing a Chart (`fdc3.chart`). ([#715](https://github.com/finos/FDC3/pull/715))\n* Added a context type `ChatInitSettings` to initialize a chat creation with new optional parameters ([#620](https://github.com/finos/FDC3/pull/620))\n* Added guide on how to submit a new Intent. ([#624](https://github.com/finos/FDC3/pull/624))\n* Added a `ViewResearch` Intent to be used when a user wants to see the latest research on a particular stock ([#623](https://github.com/finos/FDC3/pull/623))\n* Added a `ViewProfile` intent, which supersedes the `ViewContact` intent which is deprecated. ([#619](https://github.com/finos/FDC3/pull/619))\n* Added a `ViewInteractions` intent to be used when a user wants to see the latest interactions (calls, meetings, conferences, roadshows) on a particular stock or with an individual or organization. ([#625](https://github.com/finos/FDC3/pull/625))\n* Added a `ViewOrders` intent to be used when a user wants to see the order history of an individual, an institution or of a particular instrument. ([#672](https://github.com/finos/FDC3/pull/672))\n* Added a `StartEmail` intent and `fdc3.email` context type to be used to initiate an email with a contact or list of contacts provided as part of the context. ([#632](https://github.com/finos/FDC3/pull/632))\n* Added a definition for \"app directory record\" to the FDC3 glossary to be used to refer to a single appD record ([#658](https://github.com/finos/FDC3/pull/658))\n* Added `/v2/` paths to the AppD's specification, allowing a single implementation to support serving both FDC3 v1.2 and v2.0 application records, enabling simpler migration ([#666](https://github.com/finos/FDC3/pull/666))\n* Added a `moreInfo` URL field to AppD application records to enable linking to a web page with more information on an app ([#669](https://github.com/finos/FDC3/pull/669))\n* Added `lang` field to AppD application records to specify the primary language of an app and its appD record. ([#670](https://github.com/finos/FDC3/pull/670))\n* Added `localizedVersions` field to AppD application records to support localized versions of descriptive fields in the app records and alternative launch details for localized versions of the applications themselves. ([#670](https://github.com/finos/FDC3/pull/670))\n* Added `type` and `details` elements to AppD application records to support vendor-agnostic launch details for both web and native apps ([#671](https://github.com/finos/FDC3/pull/671))\n* Added `categories` field and recommended categories list to AppD application records to enable category based browsing of AppDs ([#673](https://github.com/finos/FDC3/pull/673))\n* Added an `interop` field to AppD application records, replacing the `intents` field, to more fully describe an app's use of FDC3 and enable search for apps that 'interoperate' with a selected app ([#697](https://github.com/finos/FDC3/pull/697))\n* Added `AppIdentifier` type, which is a new parent of `AppMetadata` and clarifies required fields for API call parameters which now prefer `appId` and `instanceId` over `name` ([#722](https://github.com/finos/FDC3/pull/722))\n* Added a `getAppMetadata()` function to the desktop agent that can be used to retrieve the full `AppMetadata` for an `AppIdentifier` and reduced types such as `IntentResolution.source` and `ContextMetadata.source` from `AppMetadata` to `AppIdentifier` to clarify what fields a developer can rely on and that they should manually retrieve the full `AppMetadata` when they need it for display purposes. ([#751](https://github.com/finos/FDC3/pull/751))\n\n### Changed\n\n* Consolidated `Listener` documentation with other types ([#404](https://github.com/finos/FDC3/pull/404))\n* Updated definition of the `Position` context type to support negative (short) positions ([#419](https://github.com/finos/FDC3/pull/419))\n* Upgraded web access statements from SHOULD to MUST in the API specification ([#440](https://github.com/finos/FDC3/pull/440))\n* Updated copyright notices ([#467](https://github.com/finos/FDC3/pull/467))\n* Adjusted wording in API spec and documentation to acknowledge the possibility of methods of intent resolution other than a resolver UI ([#461](https://github.com/finos/FDC3/pull/461))\n* Replaced 'System channels' with 'User channels' throughout the spec, documentation, API and methods.ts. Clarified spec and documentation where it is referring to User channels vs. App channels. Added support to methods.ts for automatic fallback to `getSystemChannels` if `getUserChannels` doesn't exist. ([#470](https://github.com/finos/FDC3/pull/479))\n* Moved the Icon type definition into the Types documentation page for consistency with other types. ([#493](https://github.com/finos/FDC3/pull/493)\n* The `fdc3.joinChannel()`, `fdc3.getCurrentChannel()` and `fdc3.leaveCurrentChannel()` functions have been made optional for FDC3 API compliance, but are recommended through the application of the SHOULD keyword. ([#512](https://github.com/finos/FDC3/pull/512))\n* All DesktopAgent and Channel API functions are now async for consistency, changing the return type of the `broadcast`, `addIntentListener`, `addContextListener` and `getInfo` functions ([#516](https://github.com/finos/FDC3/pull/516))\n* `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))\n* The App Directory record schema (Application) has had the `manifestType` and `manifest` properties removed and replaced with the new `type` (required), `details` and `hostManifests` properties ([#437](https://github.com/finos/FDC3/pull/437))\n* App Directory `images` field was replaced with `screenshots` to better align the application record with web application manifest and match its format to that used by `icons` ([#675](https://github.com/finos/FDC3/pull/675))\n* API `AppMetadata` type was updated to replace the `images` field with a `screenshots` field (an array of `Image` objects) matching the spec of the App Directory's `screenshots` field entries ([#736](https://github.com/finos/FDC3/pull/736))\n* App Directory endpoint for creating applications was removed as these will often be implementation dependent and should not be required for compliance ([#695](https://github.com/finos/FDC3/pull/695))\n* App Directory endpoint for searching applications was removed as searches over multiple app directories are better implemented by retrieving all the records and searching over the resulting combined dataset ([#696](https://github.com/finos/FDC3/pull/696))\n* Extended Intent Naming conventions and added hyperlinks for existing Intent spec definitions ([#701](https://github.com/finos/FDC3/pull/701))\n* Extended recommended field type conventions for contexts to include types for ids, times, dates, currency codes and country codes. The `fdc3.country` context type was updated to comply with the recommended field name for country codes (`COUNTRY_ISOALPHA2`). ([#704](https://github.com/finos/FDC3/pull/704))\n* The `intents` field of an AppD application records has been replaced with the `interop` field, to more fully describe an app's use of FDC3 and enable search for apps that 'interoperate' with a selected app ([#697](https://github.com/finos/FDC3/pull/697))\n\n### Deprecated\n\n* Deprecated the `ViewContact` intent, which is superseded by `ViewProfile` ([#619](https://github.com/finos/FDC3/pull/619))\n* Removed details of the 'global' channel that was deprecated in FDC3 1.2. ([#496](https://github.com/finos/FDC3/pull/496))\n* `open`, `raiseIntent` and `raiseIntentForContext` function signatures that make use of the app `name` have been deprecated in favour of using `AppIdentifier` (which is a new parent of `AppMetadata` that clarifies required fields for API call parameters) ([#722](https://github.com/finos/FDC3/pull/722))\n\n### Fixed\n\n* Removed trailing slashes from schema references (which break refs for schema parsers) ([#374](https://github.com/finos/FDC3/pull/374))\n* Corrected the definition of the `Context` type in documentation ([#406](https://github.com/finos/FDC3/pull/406)])\n* Corrected syntax errors in context schema examples ([#424](https://github.com/finos/FDC3/pull/424))\n* Corrected a minor error in the ViewQuote Intent example ([#439](https://github.com/finos/FDC3/pull/439))\n* Clarified behavior of `fdc3.addContextListener` when not joined to a channel ([#449](https://github.com/finos/FDC3/pull/449))\n* Clarified existing behavior of `joinChannel` and `addContextListener` when joining a channel ([#454](https://github.com/finos/FDC3/pull/454))\n* Clarified numerous aspects of the existing `raiseIntent` behavior in the spec and documentation ([#461](https://github.com/finos/FDC3/pull/461))\n* Updated Methods.ts to support the updated signature for `addContextListener` introduced in FDC3 1.2 ([#462](https://github.com/finos/FDC3/pull/462))\n* Clarified the description of the addContextListener functions from the Desktop Agent and Channel APIs in spec and docs. ([#492](https://github.com/finos/FDC3/pull/492))\n* Clarified that implementing `fdc3.getInfo()` is required for compliance with the FDC3 standard ([#515](https://github.com/finos/FDC3/pull/515))\n* Corrected syntax errors in valuation schema ([#834](https://github.com/finos/FDC3/pull/834))\n* Clarified that API errors are promises rejected with a JavaScript (or language appropriate) Error Object with a message chosen from the error enumerations. ([#843](https://github.com/finos/FDC3/pull/843))\n* Clarified that `findIntent` functions should return the `ResolveError.NoAppsFound` error, rather than an `AppIntent` with an empty `apps` array when no apps are fund during intent resolution. ([#843](https://github.com/finos/FDC3/pull/843))\n* Clarified spec requirements for registration of intent handlers (SHOULD support `interop.intents.listensFor` in an appD record, may support other routes including dynamic registration at runtime) ([#844](https://github.com/finos/FDC3/pull/844))\n* Corrected schema definition for appD `interop.intents.listensFor` element ([#847](https://github.com/finos/FDC3/pull/847))\n\n## [npm v1.2.0] - 2021-04-19\n\n### Added\n\n* ES6 functions for `getInfo()` and `raiseIntentForContext()` ([#268](https://github.com/finos/FDC3/pull/268), [#324](https://github.com/finos/FDC3/pull/324))\n* `fdc3Ready()` utility function that wraps checks for the window.fdc3 global object and new `fdc3Ready` event ([#360](https://github.com/finos/FDC3/pull/360))\n* `compareVersionNumbers()` and `versionIsAtLeast()` utility functions to complement `getInfo()` ([#324](https://github.com/finos/FDC3/pull/324))\n* An example application definition ([#437](https://github.com/finos/FDC3/pull/437)\n* A test environment for the app directory specification and the example application definition ([#437](https://github.com/finos/FDC3/pull/437)\n\n### Changed\n\n* `addContextListener(contextType, handler)` now supports passing `null` as the context type ([#329](https://github.com/finos/FDC3/pull/329))\n* All other API type changes and additions from the [FDC3 Standard 1.2](https://github.com/finos/FDC3/releases/tag/v1.2) release\n\n### Deprecated\n\n* `addContextListener(handler)` ([#329](https://github.com/finos/FDC3/pull/329))\n* `IntentResolution.data` ([#341](https://github.com/finos/FDC3/pull/341))\n\n## [FDC3 Standard 1.2] - 2021-04-19\n\n### Added\n\n* New `raiseIntentForContext()` method ([#268](https://github.com/finos/FDC3/pull/268))\n* New `fdc3Ready` event ([#269](https://github.com/finos/FDC3/pull/269))\n* New `getInfo()` method that returns implementation metadata ([#324](https://github.com/finos/FDC3/pull/324))\n\n### Changed\n\n* `fdc3.open()` and `fdc3.raiseIntent()` now takes `TargetApp`, which resolves to `string | AppMetadata` ([#272](https://github.com/finos/FDC3/pull/272))\n* `AppMetadata` return type can now optionally include `appId` and `version` ([#273](https://github.com/finos/FDC3/pull/273))\n* `addContextListener(contextType, handler)` now supports passing `null` as the context type ([#329](https://github.com/finos/FDC3/pull/329))\n* Simplify API reference documentation and add info about supported platforms, including npm package ([#349](https://github.com/finos/FDC3/pull/349))\n\n### Deprecated\n\n* `addContextListener(handler)` ([#329](https://github.com/finos/FDC3/pull/329))\n* `IntentResolution.data` and `'global'` channel concept ([#341](https://github.com/finos/FDC3/pull/341))\n\n### Fixed\n\n* Return type of `getCurrentChannel()` should be `Promise<Channel | null>` ([#282](https://github.com/finos/FDC3/pull/282))\n* `leaveCurrentChannel()` is missing from `DesktopAgent` interface ([#283](https://github.com/finos/FDC3/pull/283))\n\n## [npm v1.1.1] - 2021-04-15\n\n### Fixed\n\n* `Intents` enum should contain `StartChat` not `StartChart` ([#364](https://github.com/finos/FDC3/pull/364))\n* Return type of `getCurrentChannel()` should be `Promise<Channel | null>` ([#282](https://github.com/finos/FDC3/pull/282))\n* Missing `leaveCurrentChannel()` export ([#283](https://github.com/finos/FDC3/pull/283))\n\n## [npm v1.1.0] - 2021-04-14\n\n### Added\n\n* Build an npm package with exported TypeScript typings for API, Context Data and `window.fdc3` global ([#252](https://github.com/finos/FDC3/pull/252))\n* Export helper enums for names of standardized `Intents` and `ContextTypes` ([#264](https://github.com/finos/FDC3/pull/264))\n* Export API operations as ES6 functions that can be directly imported ([#266](https://github.com/finos/FDC3/pull/266))\n* Check for the existence of `window.fdc3` in ES6 functions, and reject or throw if not defined ([#356](https://github.com/finos/FDC3/pull/356))\n\n### Fixed\n\n* Return type of `getCurrentChannel()` should be `Promise<Channel>` ([#222](https://github.com/finos/FDC3/pull/222))\n\n## [FDC3 Standard 1.1] - 2020-04-09\n\n### Added\n\n* JSON Schema definitions for agreed context types ([#119](https://github.com/finos/FDC3/pull/119)):\n  * `fdc3.context`\n  * `fdc3.instrument`\n  * `fdc3.instrumentList`\n  * `fdc3.contact`\n  * `fdc3.contactList`\n  * `fdc3.organization`\n  * `fdc3.country`\n  * `fdc3.position`\n  * `fdc3.portfolio`\n* API entry point for web - `window.fdc3` ([#139](https://github.com/finos/FDC3/pull/139))\n* Use Case 17 ([#153](https://github.com/finos/FDC3/pull/153))\n* Channels API ([#154](https://github.com/finos/FDC3/pull/154)):\n  * `fdc3.getSystemChannels`\n  * `fdc3.getOrCreateChannel`\n  * `fdc3.joinChannel`\n  * `fdc3.leaveCurrentChannel`\n  * `fdc3.getCurrentChannel`\n  * `Channel` interface\n  * `DisplayMetadata` interface\n  * `ChannelError` type\n* Type filtering support for `getCurrentContext` ([#161](https://github.com/finos/FDC3/pull/161))\n* Publish versioned JSON schemas to FDC3 website ([#170](https://github.com/finos/FDC3/pull/170))\n* Intent Reference and Context Data Reference documentation ([#172](https://github.com/finos/FDC3/pull/172))\n\n### Changed\n\n* Remove FactSet-specific examples from docs ([#88](https://github.com/finos/FDC3/pull/88))\n* Apply FINOS branding, styles and logos to the website ([#96](https://github.com/finos/FDC3/pull/96))\n* Include ChartIQ in \"Who is using FDC3?\" section on website ([#100](https://github.com/finos/FDC3/pull/100))\n* Expand `AppMetadata` interface with more application properties ([#157](https://github.com/finos/FDC3/pull/157))\n* Restructure some docs ([#190](https://github.com/finos/FDC3/pull/190))\n\n### Fixed\n\n* Several typos and broken links in docs\n* Various security vulnerabilities\n\n## [FDC3 Standard 1.0] - 2019-03-28\n\n### Added\n\n* Documentation website (generated with [Docusaurus]) and content from old separate FDC3 repos ([#5](https://github.com/finos/FDC3/pull/5)):\n  * [FDC3/API](https://github.com/FDC3/API)\n  * [FDC3/ContextData](https://github.com/FDC3/ContextData)\n  * [FDC3/Intents](https://github.com/FDC3/Intents)\n  * [FDC3/appd-api](https://github.com/FDC3/appd-api)\n  * [FDC3/use-cases](https://github.com/FDC3/use-cases)\n* Use Case 15 ([#49](https://github.com/finos/FDC3/pull/49))\n* FDC3 Roadmap ([#55](https://github.com/finos/FDC3/pull/55))\n* FDC3 feature icons on website landing page ([#57](https://github.com/finos/FDC3/pull/57))\n* Participant showcase on website landing page ([#67](https://github.com/finos/FDC3/pull/67))\n\n[Docusaurus]: https://docusaurus.io\n\n### Changed\n\n* General cleanup of spelling, grammar and punctuation ([#34](https://github.com/finos/FDC3/pull/34))\n* Use cases call-out on website landing page ([#54](https://github.com/finos/FDC3/pull/54))\n* Proofreading of docs ([#62](https://github.com/finos/FDC3/pull/62))\n\n### Fixed\n\n* Remove unnecessary dates from use case file names ([#41](https://github.com/finos/FDC3/pull/41))\n* Header coloring on responsive website ([#56](https://github.com/finos/FDC3/pull/56))\n* Workflow numbers in Use Case 1 ([#60](https://github.com/finos/FDC3/pull/60))\n* Examples in Intent Overview ([#65](https://github.com/finos/FDC3/pull/65))\n* Errors in DesktopAgent API Reference ([#66](https://github.com/finos/FDC3/pull/66))\n\n[Unreleased]: https://github.com/finos/FDC3/compare/v1.2..HEAD\n[npm v1.2.0]: https://github.com/finos/FDC3/compare/v1.1.0..v1.2.0\n[FDC3 Standard 1.2]: https://github.com/finos/FDC3/compare/v1.2..v1.1\n[npm v1.1.1]: https://github.com/finos/FDC3/compare/v1.1.0..v1.1.1\n[npm v1.1.0]: https://github.com/finos/FDC3/compare/v1.1..v1.1.0\n[FDC3 Standard 1.1]: https://github.com/finos/FDC3/compare/v1.1..v1.0\n[FDC3 Standard 1.0]: https://github.com/finos/FDC3/v1.0\n"
  },
  {
    "path": "CNAME",
    "content": "fdc3.finos.org"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct for FDC3\n\nPlease see the [Community Code of Conduct](https://www.finos.org/code-of-conduct).\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to FDC3\n\nThis document provides the contribution policy for the FDC3 Standard (the [Working Group](GOVERNANCE.md)) and is based on the [Community Specification Contribution Policy 1.0](https://spdx.org/licenses/Community-Spec-1.0.html).\n\n_NOTE:_ Commits and pull requests to FINOS repositories will only be accepted from those participants with an active, executed Individual Contributor License Agreement (ICLA) with FINOS, _OR_ who are covered under an existing and active Corporate Contribution License Agreement (CCLA) executed with FINOS. Commits from individuals not covered under an ICLA or CCLA will be flagged and blocked by the [Linux Foundation `EasyCLA` tool](https://easycla.lfx.linuxfoundation.org/#/). Please note that some CCLAs require individuals/employees to be explicitly named on the CCLA.\n\n*Need an ICLA? Unsure if you are covered under an existing CCLA? Email [help@finos.org](mailto:help@finos.org).*\n\n## 1.\tContribution Guidelines.\n\nThis Working Group accepts contributions via pull requests. The following section outlines the process for merging contributions to the specification\n\n**1.1.\tIssues.**  Issues are used as the primary method for tracking anything to do with this specification Working Group.\n\n**1.1.1.\tIssue Types.**  A number of issue templates are available in the FDC3 respository:\n\n**1.1.1.1.\tMeetings.** Templates for issues that represent meetings and include agendas, teleconference details and minutes.\n\n**1.1.1.2.\tProposals and Enhancement Requests.** Used for items that propose a new ideas or functionality that require a larger discussion. This allows for feedback from others before a specification change is actually written.\n\n**1.1.1.3.\tMinor Issue:** These track minor changes or corrections that don't alter the Standard significantly but rather correct minor errors or ommisions.\n\n**1.1.1.4.\tQuestion:** May be used to ask questions about FDC3, requests support etc..\n\n## 2.\tIssue Lifecycle.\n\nThe issue lifecycle is mainly driven by the Maintainer.  All issue types follow the same general lifecycle. Differences are noted below.\n\n**Prerequisites**\n\n * Have you [searched for duplicates](https://github.com/finos/FDC3/issues?utf8=%E2%9C%93&q=)?  A simple search for exception error messages or a summary of the unexpected behaviour should suffice.\n * Are you using the latest version of the Standard?\n   * Changes that have been merged but not yet released can be found in the [next](https://fdc3.finos.org/docs/next/fdc3-standard) version of the website and details found in the [CHANGELOG](https://github.com/finos/FDC3/blob/main/CHANGELOG.md)\n * Are you sure this is a bug or missing capability?\n\n**2.1.\tIssue Creation.**\n\n * Create your issue [here](https://github.com/finos/FDC3/issues/new).\n * New issues contain two templates in the description: bug report and enhancement request. Please pick the most appropriate for your issue, **then delete the other**.\n\n * Please also tag the new issue with either \"Bug\" or \"Enhancement\".\n\n * Please use [Markdown formatting](https://help.github.com/categories/writing-on-github/)\nliberally to assist in readability.\n \n * [Code fences](https://help.github.com/articles/creating-and-highlighting-code-blocks/) for exception stack traces and log entries, for example, massively improve readability.\n\n**2.2.\tTriage.**\n\n- The FDC3 Maintainers will apply the proper labels for the issue. This may include labels for priority, type, and metadata.\n\n- (If needed) Clean up the title to succinctly and clearly state the issue.\n\n**2.3.\tDiscussion.**\n\n- Issues that change the Standard usually need discussion. You can post comments directly on the issue or can ask for it to be added to a Standards Working Group meeting agenda by emailing [fdc3@finos.org](mailto:fdc3@finos.org), sending a message to the [#fdc3 channel on the FINOS slack](https://finos-lf.slack.com/messages/fdc3/) or tag the FDC3 maintainers (`@finos/fdc3-maintainers`) in your issue.\n\n- Issues that enhance or otherwise change the Standard should be connected to the pull request that resolves it. That can be achieved by prefixing your pull request's description with a keyword and issue number, e.g. `resolves #123`. For more details on linking issues and PRs see [Github's documentation](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).\n\n**2.4.\tIssue Closure.**\n\n## 3.\tHow to Contribute a Patch.\n\nThe Working Group uses pull requests to track changes. To submit a change to the Standard:\n\n**3.1.\tFork the Repo**\n- (<https://github.com/finos/FDC3/fork>)\n\n**3.2.\tCreate your feature branch**\n- `git checkout -b feature/fooBar`\n\n**3.3.\tCommit your changes**\n- `git commit -am 'Describe what you changed'`\n\n**3.4.\tPush to the branch**\n- `git push origin feature/fooBar`\n\n**3.5.\tCreate a Pull Request**\n- For help creating a pull request from your fork, [see Github's documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)\n\nTo contribute a patch for a New Intent, see the [Submit New Intent](docs/guides/submit-new-intent) guide.\n\n**3.6. Test Policy**\n\n- The FDC3 project takes very seriously code quality, especially with respect to production-grade sub-modules.  This includes:\n\n|Module | Test Policy |\n|---|---|\n|`packages/fdc3` | Code should not be added here - just `import` / `export` in `index.ts` |\n|`packages/fdc3-agent-proxy` | Contributions must improve or maintain coverage at the current level |\n|`packages/fdc3-commonjs` | Code should not be added here |\n|`packages/fdc3-context` | Must contain only JSON Schemas and source code generated from them |\n|`packages/fdc3-get-agent` |Contributions must improve or maintain coverage at the current level \n|`packages/fdc3-schema` | Must contain only JSON Schemas and source code generated from them |\n|`packages/fdc3-standard` | Contributions must improve or maintain coverage at the current level |\n|`toolbox/fdc3-for-web/fdc3-web-impl` | Contributions must improve or maintain coverage at the current level |\n\nPlease note that the FDC3 project uses the following test policy:\n\n  * Code should have tests (coverage is reported in the PR comments)\n  * All tests must pass. (checked automatically by the PR comments)\n  * All tests must be meaningful.\n  * All tests must be kept up-to-date.\n  * All tests must be run locally before submitting a PR.\n  * Finally, the `toolbox/fdc3-for-web/demo` project is expected to pass the FDC3 conformance framework prior to new FDC3 releases (not currently automated).\n\n## 4.\tPull Request Workflow.\n\nThe next section contains more information on the workflow followed for Pull Requests.\n\n**4.1.\tPull Request Creation.**\n\n- We welcome pull requests that are currently in progress. They are a great way to keep track of important work that is in-flight, but useful for others to see. If a pull request is a work in progress, it should be prefaced with \"WIP: [title]\". Once the pull request is ready for review, remove \"WIP\" from the title and label.\n\n- It is preferred, but not required, to have a pull request tied to a specific issue. Prefix your PR's description with `resolves #<issue number>` to link it to your issue.\n\n- There can be circumstances where if it is a quick fix then an issue might be overkill. The details provided in the pull request description would suffice in this case.\n\n- Ensure that pull requests include a proposed update to the [FDC3 Changelog (CHANGELOG.md)](CHANGELOG.md)\n\nTo make review of PRs easier, please:\n\n * Please make sure your PRs will merge cleanly - PRs that don't are unlikely to be accepted.\n \n * For code contributions, follow the existing code layout.\n \n * For documentation contributions, follow the general structure, language, and tone of the [existing docs](https://fdc3.finos.org).\n \n * Keep commits small and cohesive - if you have multiple contributions, please submit them as independent commits (and ideally as independent PRs too).\n \n * Reference issue #s if your PR has anything to do with an issue (even if it doesn't address it).\n \n * Minimise non-functional changes (e.g. whitespace shenanigans).\n \n * Ensure all new source files include a header comment block containing the [Apache License v2.0 and your copyright information](http://www.apache.org/licenses/LICENSE-2.0#apply).\n \n * If necessary (e.g. due to 3rd party dependency licensing requirements), update the [NOTICES.md file](https://github.com/finos/FDC3/blob/main/NOTICES.md) with any new attribution or other notices\n\n**4.2.\tTriage**\n\n- The Maintainers will apply the proper labels for the issue. This may include an indication of the subject area or type (e.g. `deprecation`).\n\n**4.3.\tReviewing/Discussion.**\n\n- All PRs will be reviewed by at least one of the FDC3 Maintainers and any appointed Editors. PRs are also open to review by FDC3 Participants.\n\n- The FDC3 Maintainers are responsible for ensuring that the Standard Working Group has been consulted on either an issue (that provides a high-level of detail on the proposed changes) or on the PR itself, a decision has been reached that the change should be made and that that decision has been documented.\n\n- All reviews will be completed using the Github review tool.\n\n- A \"Comment\" review should be used when there are questions about the spec that should be answered, but that don't involve spec changes. This type of review does not count as approval.\n\n- A \"Changes Requested\" review indicates that changes to the spec need to be made before they will be merged.\n\n- Reviewers should update labels as needed (such as needs rebase).\n\n- When a review is approved, the reviewer should add LGTM as a comment.\n\n**4.4.\tResponsive.** Pull request owner should try to be responsive to comments by answering questions or changing text. Once all comments have been addressed, the pull request is ready to be merged.\n\n**4.5.\tMerge or Close.**\n\n- A pull request should stay open until a Maintainer has marked the pull request as approved.\n\n- Pull requests can be closed by the author without merging.\n\n- Pull requests may be closed by a Maintainer if the decision is made that it is not going to be merged.\n\n## 5. Adoption of Contributions.\nContributions merged into the main branch of the FDC3 repository will form part of the next pre-draft of the FDC3 Standard (as defined by the [FDC3 Governance document](./GOVERNANCE.md)), which must be approved by the Standard Working Group voting participants before it is accepted as a draft and subsequently released as the next version of the Standard.\n\n\n"
  },
  {
    "path": "GOVERNANCE.md",
    "content": "# FDC3 Governance Policy\n\nThis document provides the governance policy for the development of the FDC3 specification and related materials in the FDC3 Standard (the “Working Group”).\n\n## 1.\tRoles.\n\nThe Working Group includes the following roles:\n\n### 1.1. Participants\n\n“Participants” are those that have made Contributions to the Working Group subject to the [Community Specification Contribution Policy 1.0](https://spdx.org/licenses/Community-Spec-1.0.html).  The [FDC3 Standard Working Group](https://github.com/finos/FDC3/issues?q=label%3A%22Standard+WG+Meeting%22) has the specific purpose of defining and releasing subsequent updates to the Standard. In practice, that means people that attend and contribute to meetings, raise issues, pull requests (to submit patches to the Standard) and reviews.\n\n#### How do you become a Participant?\n\nBecoming an FDC3 Participant is as easy as attending a meeting and/or raising issues for changes you'd like see in the Standard, commenting on issues others have raised or even asking questions (which can often result in the clarification of the Standard's documentation to help others with the same questions in future).\n\n#### Register to vote\nParticipants may register to vote on changes to the FDC3 Standard (see [Section 2](#2decision-making) below). To do so use this link: [fdc3-participants+subscribe@finos.org](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!) to send a templated email email to join the enrolled voting participants group.\n\nUpon enrollment as an [FDC3 voting participant](https://github.com/orgs/finos/teams/fdc3-participants), you will be invited to join the [FINOS GitHub organization](https://github.com/orgs/finos/people) and the [fdc3-participants](https://github.com/orgs/finos/teams/fdc3-participants) GitHub team.\n\n- [View the FDC3 Participants GitHub Team](https://github.com/orgs/finos/teams/fdc3-participants)\n\n### 1.2. Discussion Groups\n\nThe Working Group may form one or more \"Discussion Groups\" to organize collaboration around a particular aspect of a specification. Discussion Groups are for discussion only.  Approval of all portions of a specification is subject to the consensus-based decision-making process of the FDC3 Standard Working Group.\n\n### 1.3. Maintainers & Editors\n\n“Maintainers” are responsible for organizing activities around developing, maintaining, and updating the specification(s) developed by the Working Group.  Maintainers are also responsible for determining consensus and coordinating appeals.  The Working Group will designate one or more Maintainer(s). The Working Group may select a new or additional Maintainer(s) upon Approval of the Working Group Participants.  \n\n- [View the FDC3 Maintainers GitHub Team](https://github.com/orgs/finos/teams/fdc3-maintainers)\n\n“Editors” are responsible for ensuring that the contents of the document accurately reflect the decisions that have been made by the group, and that the specification adheres to formatting and content guidelines. The Working Group will designate one or more Editor(s). The Working Group may select a new Editor upon Approval of the Working Group Participants.\n\n- [View the FDC3 Editors GitHub Team](https://github.com/orgs/finos/teams/fdc3-editors)\n\n#### How do you become an Editor or Maintainer?\n\nOnce you are an enrolled participant in FDC3, you can apply to become an **editor** or **maintainer** by contacting the existing FDC3 maintainers at [fdc3-maintainers@finos.org](mailto:fdc3-maintainers@finos.org) and then seeking the approval of the FDC3 Standards Working Group. Generally, the maintainers will look for both a history of contribution to FDC3 and a commitment to investing sufficient time in the role from any prospective candidates before proposing them to the Standards Working Group for approval. \n\nIf you are new to FDC3, but willing to make the investment of time, the maintainers can work with you to build up a history of contribution.\n\n## 2.\tDecision Making.\n\n**2.1.\tConsensus-Based Decision Making.**  The Working Group makes decisions through a consensus process (“Approval” or “Approved”).  While the agreement of all Participants is preferred, it is not required for consensus.  Rather, the Maintainer(s) will determine consensus based on their good faith consideration of a number of factors, including the dominant view of the Working Group Participants and nature of support and objections.  The Maintainer(s) will document evidence of consensus in accordance with these requirements. \n\n**2.2.\tAppeal Process.**  Decisions may be appealed be via a pull request or an issue. The Maintainer(s) will consider each appeal in good faith and will respond in writing within a reasonable time.\n\n## 3.\tWays of Working.\n\nInspired by [ANSI’s Essential Requirements for Due Process](https://share.ansi.org/Shared%20Documents/Standards%20Activities/American%20National%20Standards/Procedures,%20Guides,%20and%20Forms/2020_ANSI_Essential_Requirements.pdf), the Working Group adheres to consensus-based due process requirements.  These requirements apply to activities related to the development of consensus for approval, revision, reaffirmation, and withdrawal of specifications.  Due process means that any person (organization, company, government agency, individual, etc.) with a direct and material interest has a right to participate by: a) expressing a position and its basis, b) having that position considered, and c) having the right to appeal. Due process allows for equity and fair play. The following constitute the minimum acceptable due process requirements for the development of consensus.\n\n**3.1.\tOpenness.**  Participation shall be open to all persons who are directly and materially affected by the activity in question. There shall be no undue financial barriers to participation. Voting membership on the consensus body shall not be conditional upon membership in any organization, nor unreasonably restricted on the basis of technical qualifications or other such requirements.  Membership in a Working Group’s parent organization, if any, may be required.\n\n**3.2.\tLack of Dominance.**  The development process shall not be dominated by any single interest category, individual or organization. Dominance means a position or exercise of dominant authority, leadership, or influence by reason of superior leverage, strength, or representation to the exclusion of fair and equitable consideration of other viewpoints.\n\n**3.3.\tBalance.**  The development process should have a balance of interests. Participants from diverse interest categories shall be sought with the objective of achieving balance.\n\n**3.4.\tCoordination and Harmonization.**  Good faith efforts shall be made to resolve potential conflicts between and among deliverables developed under this Working Group and existing industry standards.\n\n**3.5.\tConsideration of Views and Objections.**  Prompt consideration shall be given to the written views and objections of all Participants.\n\n**3.6.\tWritten procedures.**  This governance document and other materials documenting the specification development process shall be available to any interested person.\n\n## 4.\tStandard Development Process.  \n\n**4.1.\tPre-Draft.**  Any Participant may submit a proposed initial draft document as a candidate Draft Specification of the Working Group.  The Maintainer(s) will designate each submission as a “Pre-Draft” document.\n\n**4.2.\tDraft.**  Each Pre-Draft document of the Working Group must first be Approved to become a “Draft Specification”.  Once the Working Group approves a document as a Draft Specification, the Draft Specification becomes the basis for all going forward work on that specification.\n\n**4.3.\tWorking Group Approval.**  Once the Working Group believes it has achieved the objectives for its specification as described in the [Scope](./SCOPE), it will Approve that Draft Specification and progress it to “Approved Specification” status. \n\n**4.4.\tPublication and Submission.**  Upon the designation of a Draft Specification as an Approved Specification, the Maintainer(s) will publish the Approved Specification in a manner agreed upon by the Working Group Participants (i.e., Working Group Participant only location, publicly available location, Working Group maintained website, Working Group member website, etc.).  The publication of an Approved Specification in a publicly accessible manner must include the terms under which the Approved Specification is being made available under.\n\n**4.5.\tSubmissions to Standards Bodies.**  No Draft Specification or Approved Specification may be submitted to another standards development organization without Working Group Approval. Upon reaching Approval, the Maintainer(s) will coordinate the submission of the applicable Draft Specification or Approved Specification to another standards development organization. Working Group Participants that developed that Draft Specification or Approved Specification agree to grant the copyright rights necessary to make those submissions.\n\n## 5. Non-Confidential, Restricted Disclosure.\n\nInformation disclosed in connection with any Working Group activity, including but not limited to meetings, Contributions, and submissions, is not confidential, regardless of any markings or statements to the contrary.  Notwithstanding the foregoing, if the Working Group is collaborating via a private repository, the Participants will not make any public disclosures of that information contained in that private repository without the Approval of the Working Group.  \n"
  },
  {
    "path": "LICENSE.md",
    "content": "# Community Specification License 1.0\n\n**The Purpose of this License.**  This License sets forth the terms under which 1) Contributor will participate in and contribute to the development of specifications, standards, best practices, guidelines, and other similar materials under this Working Group, and 2) how the materials developed under this License may be used.  It is not intended for source code.  Capitalized terms are defined in the License’s last section.\n\n**1.\tCopyright.**\n\n**1.1.\tCopyright License.**  Contributor grants everyone a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) copyright license, without any obligation for accounting, to reproduce, prepare derivative works of, publicly display, publicly perform, and distribute any materials it submits to the full extent of its copyright interest in those materials. Contributor also acknowledges that the Working Group may exercise copyright rights in the Specification, including the rights to submit the Specification to another standards organization.\n\n**1.2.\tCopyright Attribution.**  As a condition, anyone exercising this copyright license must include attribution to the Working Group in any derivative work based on materials developed by the Working Group.  That attribution must include, at minimum, the material’s name, version number, and source from where the materials were retrieved.  Attribution is not required for implementations of the Specification.\n\n**2.\tPatents.**\n\n**2.1.\tPatent License.**\n\n**2.1.1.\tAs a Result of Contributions.**\n\n**2.1.1.1.\tAs a Result of Contributions to Draft Specifications.**  Contributor grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims in 1) Contributor’s Contributions and 2) to the Draft Specification that is within Scope as of the date of that Contribution, in both cases for Licensee’s Implementation of the Draft Specification, except for those patent claims excluded by Contributor under Section 3.  \n\n**2.1.1.2.\tFor Approved Specifications.**  Contributor grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims included the Approved Specification that are within Scope for Licensee’s Implementation of the Approved Specification, except for those patent claims excluded by Contributor under Section 3.\n\n**2.1.2.\tPatent Grant from Licensee.**  Licensee grants each other Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims for its Implementation, except for those patent claims excluded under Section 3.\n\n**2.1.3.\tLicensee Acceptance.**  The patent grants set forth in Section 2.1 extend only to Licensees that have indicated their agreement to this License as follows: \n\n**2.1.3.1.\tSource Code Distributions.**  For distribution in source code, by including this License in the root directory of the source code with the Implementation;\n\n**2.1.3.2.\tNon-Source Code Distributions.**  For distribution in any form other than source code, by including this License in the documentation, legal notices, via notice in the software, and/or other written materials provided with the Implementation; or\n\n**2.1.3.3.\tVia Notices.md.**  By issuing pull request or commit to the Specification’s repository’s Notices.md file by the Implementer’s authorized representative, including the Implementer’s name, authorized individual and system identifier, and Specification version.\n\n**2.1.4.\tDefensive Termination.**  If any Licensee files or maintains a claim in a court asserting that a Necessary Claim is infringed by an Implementation, any licenses granted under this License to the Licensee are immediately terminated unless 1) that claim is directly in response to a claim against Licensee regarding an Implementation, or 2) that claim was brought to enforce the terms of this License, including intervention in a third-party action by a Licensee.\n\n**2.1.5.\tAdditional Conditions.**  This License is not an assurance (i) that any of Contributor’s copyrights or issued patent claims cover an Implementation of the Specification or are enforceable or (ii) that an Implementation of the Specification would not infringe intellectual property rights of any third party.\n\n**2.2.\tPatent Licensing Commitment.**  In addition to the rights granted in Section 2.1, Contributor agrees to grant everyone a no charge, royalty-free license on reasonable and non-discriminatory terms to Contributor’s Necessary Claims that are within Scope for:\n1) Implementations of a Draft Specification, where such license applies only to those Necessary Claims infringed by implementing Contributor's Contribution(s) included in that Draft Specification, and\n2) Implementations of the Approved Specification. \n\nThis patent licensing commitment does not apply to those claims subject to Contributor’s Exclusion Notice under Section 3.\n\n**2.3.\tEffect of Withdrawal.**  Contributor may withdraw from the Working Group by issuing a pull request or commit providing notice of withdrawal to the Working Group repository’s Notices.md file.  All of Contributor’s existing commitments and obligations with respect to the Working Group up to the date of that withdrawal notice will remain in effect, but no new obligations will be incurred. \n\n**2.4.\tBinding Encumbrance.**  This License is binding on any future owner, assignee, or party who has been given the right to enforce any Necessary Claims against third parties.\n\n**3.\tPatent Exclusion.**\n\n**3.1.\tAs a Result of Contributions.**  Contributor may exclude Necessary Claims from its licensing commitments incurred under Section 2.1.1 by issuing an Exclusion Notice within 45 days of the date of that Contribution.  Contributor may not issue an Exclusion Notice for any material that has been included in a Draft Deliverable for more than 45 days prior to the date of that Contribution.\n\n**3.2.\tAs a Result of a Draft Specification Becoming an Approved Specification.**  Prior to the adoption of a Draft Specification as an Approved Specification, Contributor may exclude Necessary Claims from its licensing commitments under this Agreement by issuing an Exclusion Notice.  Contributor may not issue an Exclusion Notice for patents that were eligible to have been excluded pursuant to Section 3.1.\n\n**4.\tSource Code License.**  Any source code developed by the Working Group is solely subject the source code license included in the Working Group’s repository for that code.  If no source code license is included, the source code will be subject to the MIT License.\n\n**5.\tNo Other Rights.**  Except as specifically set forth in this License, no other express or implied patent, trademark, copyright, or other rights are granted under this License, including by implication, waiver, or estoppel.\n\n**6.\tAntitrust Compliance.**  Contributor acknowledge that it may compete with other participants in various lines of business and that it is therefore imperative that they and their respective representatives act in a manner that does not violate any applicable antitrust laws and regulations.  This License does not restrict any Contributor from engaging in similar specification development projects. Each Contributor may design, develop, manufacture, acquire or market competitive deliverables, products, and services, and conduct its business, in whatever way it chooses.  No Contributor is obligated to announce or market any products or services.  Without limiting the generality of the foregoing, the Contributors agree not to have any discussion relating to any product pricing, methods or channels of product distribution, division of markets, allocation of customers or any other topic that should not be discussed among competitors under the auspices of the Working Group.\n\n**7.\tNon-Circumvention.**  Contributor agrees that it will not intentionally take or willfully assist any third party to take any action for the purpose of circumventing any obligations under this License.\n\n**8.\tRepresentations, Warranties and Disclaimers.**\n\n**8.1.  Representations, Warranties and Disclaimers.**  Contributor and Licensee represents and warrants that 1) it is legally entitled to grant the rights set forth in this License and 2) it will not intentionally include any third party materials in any Contribution unless those materials are available under terms that do not conflict with this License.  IN ALL OTHER RESPECTS ITS CONTRIBUTIONS ARE PROVIDED \"AS IS.\" The entire risk as to implementing or otherwise using the Contribution or the Specification is assumed by the implementer and user. Except as stated herein, CONTRIBUTOR AND LICENSEE EXPRESSLY DISCLAIM ANY WARRANTIES (EXPRESS, IMPLIED, OR OTHERWISE), INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, CONDITIONS OF QUALITY, OR TITLE, RELATED TO THE CONTRIBUTION OR THE SPECIFICATION.  IN NO EVENT WILL ANY PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any obligations regarding the transfer, successors in interest, or assignment of Necessary Claims will be satisfied if Contributor or Licensee notifies the transferee or assignee of any patent that it knows contains Necessary Claims or necessary claims under this License. Nothing in this License requires Contributor to undertake a patent search. If Contributor is 1) employed by or acting on behalf of an employer, 2) is making a Contribution under the direction or control of a third party, or 3) is making the Contribution as a consultant, contractor, or under another similar relationship with a third party, Contributor represents that they have been authorized by that party to enter into this License on its behalf.\n\n**8.2.  Distribution Disclaimer.**  Any distributions of technical information to third parties must include a notice materially similar to the following: “THESE MATERIALS ARE PROVIDED “AS IS.” The Contributors and Licensees expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the materials.  The entire risk as to implementing or otherwise using the materials is assumed by the implementer and user. IN NO EVENT WILL THE CONTRIBUTORS OR LICENSEES BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS DELIVERABLE OR ITS GOVERNING AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER MEMBER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”\n\n**9.\tDefinitions.**\n\n**9.1.\tAffiliate.** “Affiliate” means an entity that directly or indirectly Controls, is Controlled by, or is under common Control of that party.\n\n**9.2.\tApproved Specification.**  “Approved Specification” means the final version and contents of any Draft Specification designated as an Approved Specification as set forth in the accompanying Governance.md file.\n\n**9.3.\tContribution.**  “Contribution” means any original work of authorship, including any modifications or additions to an existing work, that Contributor submits for inclusion in a Draft Specification, which is included in a Draft Specification or Approved Specification.\n\n**9.4.\tContributor.** “Contributor” means any person or entity that has indicated its acceptance of the License 1) by making a Contribution to the Specification, or 2) by entering into the Community Specification Contributor License Agreement for the Specification.  Contributor includes its Affiliates, assigns, agents, and successors in interest.\n\n**9.5.\tControl.**  “Control” means direct or indirect control of more than 50% of the voting power to elect directors of that corporation, or for any other entity, the power to direct management of such entity.\n\n**9.6.\tDraft Specification.**  “Draft Specification” means all versions of the material (except an Approved Specification) developed by this Working Group for the purpose of creating, commenting on, revising, updating, modifying, or adding to any document that is to be considered for inclusion in the Approved Specification. \n\n**9.7.\tExclusion Notice.**  “Exclusion Notice” means a written notice made by making a pull request or commit to the repository’s Notices.md file that identifies patents that Contributor is excluding from its patent licensing commitments under this License.  The Exclusion Notice for issued patents and published applications must include the Draft Specification’s name, patent number(s) or title and application number(s), as the case may be, for each of the issued patent(s) or pending patent application(s) that the Contributor is excluding from the royalty-free licensing commitment set forth in this License.  If an issued patent or pending patent application that may contain Necessary Claims is not set forth in the Exclusion Notice, those Necessary Claims shall continue to be subject to the licensing commitments under this License.  The Exclusion Notice for unpublished patent applications must provide either: (i) the text of the filed application; or (ii) identification of the specific part(s) of the Draft Specification whose implementation makes the excluded claim a Necessary Claim.  If (ii) is chosen, the effect of the exclusion will be limited to the identified part(s) of the Draft Specification.\n\n**9.8.\tImplementation.**  “Implementation” means making, using, selling, offering for sale, importing or distributing any implementation of the Specification 1) only to the extent it implements the Specification and 2) so long as all required portions of the Specification are implemented.\n\n**9.9.\tLicense.**  “License” means this Community Specification License.\n\n**9.10.\tLicensee.**  “Licensee” means any person or entity that has indicated its acceptance of the License as set forth in Section 2.1.3.  Licensee includes its Affiliates, assigns, agents, and successors in interest.\n\n**9.11.\tNecessary Claims.**  “Necessary Claims” are those patent claims, if any, that a party owns or controls, including those claims later acquired, that are necessary to implement the required portions (including the required elements of optional portions) of the Specification that are described in detail and not merely referenced in the Specification.\n\n**9.12.\tSpecification.**  “Specification” means a Draft Specification or Approved Specification included in the Working Group’s repository subject to this License, and the version of the Specification implemented by the Licensee.\n\n**9.13.\tScope.**  “Scope” has the meaning as set forth in the accompanying Scope.md file included in this Specification’s repository. Changes to Scope do not apply retroactively.  If no Scope is provided, each Contributor’s Necessary Claims are limited to that Contributor’s Contributions.\n\n**9.14.\tWorking Group.**  “Working Group” means this project to develop specifications, standards, best practices, guidelines, and other similar materials under this License.\n\n\n\n*The text of this Community Specification License is Copyright 2020 Joint Development Foundation and is licensed under the Creative Commons Attribution 4.0 International License available at https://creativecommons.org/licenses/by/4.0/.*\n\nSPDX-License-Identifier: CC-BY-4.0\n"
  },
  {
    "path": "LICENSE.spdx",
    "content": "SPDXVersion: SPDX-2.0\nDataLicense: CC0-1.0\nCreator: FDC3\nPackageName: FDC3\nPackageOriginator: FDC3\nPackageHomePage: https://github.com/finos/FDC3\nPackageLicenseDeclared: Apache-2.0\n"
  },
  {
    "path": "NOTICES.md",
    "content": "# Notices\n\nFDC3 - Fintech Open Source Foundation (https://www.finos.org/)\n\nCopyright OpenFin Inc. (info@openfin.co)\nCopyright FINOS (info@finos.org)\nCopyright Participants of the FDC3 standards project (fdc3-participants@finos.org)\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY WHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS EXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE ENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION, NOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY WHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF ANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE OF THIS STANDARD.\n\n## Code of Conduct\n\nContact for Code of Conduct issues or inquiries:  legal@linuxfoundation.org\n\nPlease see the [Community Code of Conduct](https://www.finos.org/code-of-conduct).\n\n## License Acceptance\n\nPer Community Specification License 1.0 Section 2.1.3.3, Licensees may indicate their acceptance of the Community Specification License by issuing a pull request to the Specification’s repository’s Notice.md file, including the Licensee’s name, authorized individuals' names, and repository system identifier (e.g. GitHub ID), and specification version.\n\nA Licensee may consent to accepting the current Community Specification License version or any future version of the Community Specification License by indicating \"or later\" after their specification version.\n\n---------------------------------------------------------------------------------\n\nLicensee’s name:\n\nAuthorized individual and system identifier:\n\nSpecification version:\n\n---------------------------------------------------------------------------------\n\n## Withdrawals\n\nName of party withdrawing:\n\nDate of withdrawal:  \n\n---------------------------------------------------------------------------------\n\n## Exclusions\n\nThis section includes any Exclusion Notices made against a Draft Deliverable or Approved Deliverable as set forth in the Community Specification Development License.  Each Exclusion Notice must include the following information:\n\n-\tName of party making the Exclusion Notice:\n\n-\tName of patent owner:\n\n-\tSpecification:\n\n-\tVersion number:\n\n**For issued patents and published patent applications:**\n\n\t(i)\tpatent number(s) or title and application number(s), as the case may be:\n\n\t(ii)\tidentification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim.\n\n**For unpublished patent applications must provide either:**\n\n\t(i) the text of the filed application; or\n    \n\t(ii) identification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim.\n\n-----------------------------------------------------------------------------------------"
  },
  {
    "path": "PATENTS-FDC3-1.0.md",
    "content": "# FDC3 v. 1.0 Final Specification Agreement \r\n \r\n## 1. The Purpose of this Agreement.  \r\n\r\nThis Agreement sets forth the terms under which I make certain copyright and patent rights available to you for your Permitted Uses of the Specification.  Capitalized terms are defined in the Agreement’s last section.\r\n\r\n## 2. Copyrights.\r\n \r\n**2.1 Copyright Grant.**   I grant to you a perpetual (for the duration of the applicable copyright), worldwide, non-exclusive, no-charge, royalty-free, copyright license, without any obligation for accounting to me, to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, distribute, and implement the Specification to the full extent of my copyright interest in the Specification.\r\n\r\n**2.2 Attribution.**  As a condition of the copyright grant, you must include an attribution to the Specification in any derivative work you make based on the Specification.  That attribution must include, at minimum, the Specification name and version number. \r\n\r\n## 3. Patents.\r\n \r\n### 3.1. Patent Non-Assert.\r\n\r\n#### 3.1.1. The Promise.  \r\n\r\nI, on behalf of myself and my successors in interest and assigns, irrevocably promise not to assert my Granted Claims against you for your Permitted Uses, subject to the terms and conditions of Section 3.1.  This is a personal promise directly from me to you, and you acknowledge as a condition of benefiting from it that no rights from me are received from suppliers, distributors, or otherwise in connection with this promise. This promise also applies to your Permitted Uses of any other specifications incorporating all required portions of the Specification.\r\n\r\n#### 3.1.2. Termination.\r\n\r\n**3.1.2.1. As a Result of Claims by You.**  All rights, grants, and promises made by me to you under this Agreement are terminated if you file, maintain, or voluntarily participate in a lawsuit against me or any person or entity asserting that its Permitted Uses infringe any Granted Claims you would have had the right to enforce had you signed this Agreement, unless that suit was in response to a corresponding suit first brought against you.\r\n \r\n**3.1.2.2. As a Result of Claims by a Related Entity of Mine.**  If a Related Entity of mine files, maintains, or voluntarily participates in a lawsuit asserting that a Permitted Use infringes any Granted Claims it would have had the right to enforce had it signed this Agreement, then I relinquish any rights, grants, and promises I have received for the Specification from other signatories of this Agreement, unless a) my promise to you was terminated pursuant to section 3.1.2.1, or b) that suit was in response to a corresponding suit first brought by you against the Related Entity.\r\n\r\n#### 3.1.3. Additional Conditions.  \r\n\r\nThis promise is not an assurance (i) that any of my copyrights or issued patent claims cover an implementation of the Specification or are enforceable or (ii) that an implementation of the Specification would not infringe intellectual property rights of any third party. Notwithstanding the personal nature of my promise, this promise is intended to be binding on any future owner, assignee or exclusive licensee to whom has been given the right to enforce any Granted Claims against third parties.\r\n\r\n#### 3.1.4. Bankruptcy.\r\n\r\nSolely for purposes of Section 365(n) of Title 11, United States Bankruptcy Code and any equivalent law in any foreign jurisdiction, this promise will be treated as if it were a license and you may elect to retain your rights under this promise if I (or any owner of any patents or patent applications referenced herein), as a debtor in possession, or a bankruptcy trustee, reject this non-assert.\r\n\r\n### 3.2. Patent License Commitment. \r\n\r\nIn addition to rights granted in 3.1, on behalf of me and my successors in interest and assigns, I agree to grant to you a no charge, royalty free license to my Granted Claims on reasonable and non-discriminatory terms, where such license applies only to those Granted Claims infringed by the implementation of the Specification, solely for your Permitted Uses.\r\n\r\n## 4. No Other Rights. \r\n\r\nExcept as specifically set forth in this Agreement, no other express or implied patent, trademark, copyright, or other property rights are granted under this Agreement, including by implication, waiver, or estoppel.\r\n \r\n## 5. Antitrust Compliance.  \r\n\r\nI acknowledge that I may compete with other participants, that I am under no obligation to implement the Specification, that each participant is free to develop competing technologies and standards, and that each party is free to license its patent rights to third parties, including for the purpose of enabling competing technologies and standards.\r\n\r\n## 6. Non-Circumvention.  \r\n\r\nI agree that I will not intentionally take or willfully assist any third party to take any action for the purpose of circumventing my obligations under this Agreement.\r\n\r\n## 7. Representations, Warranties and Disclaimers.  \r\n\r\nI represent and warrant that I am legally entitled to grant the rights and promises set forth in this Agreement. IN ALL OTHER RESPECTS THE SPECIFICATION IS PROVIDED \"AS IS.\"  The entire risk as to implementing or otherwise using the Specification is assumed by the implementer and user. Except as stated herein, I expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the Specification. IN NO EVENT WILL ANY PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. All of my obligations under Section 3 regarding the transfer, successors in interest, or assignment of Granted Claims will be satisfied if I notify the transferee or assignee of any patent that I know contains Granted Claims of the obligations under Section 3. Nothing in this Agreement requires me to undertake a patent search.\r\n\r\n## 8. Definitions.\r\n\r\n**8.1. Agreement.**  “Agreement” means this Final Specification Agreement, which sets forth the rights, grants, promises, limitations, conditions, obligations, and disclaimers made available for the particular Specification.\r\n\r\n**8.2. Bound Entities.**  “Bound Entities” means the entity listed below and any entities that the Bound Entity Controls.\r\n\r\n**8.3. Control.**  “Control” means direct or indirect control of more than 50% of the voting power to elect directors of that corporation, or for any other entity, the power to direct management of such entity.\r\n\r\n**8.4. Granted Claims.**  \"Granted Claims\" are those patent claims that I own or control, including those patent claims I acquire or control after the Date below, that are infringed by Permitted Uses. Granted Claims include only those patent claims that are infringed by the implementation of any portions of the Specification where the Specification describes the functionality causing the infringement in detail and does not merely reference the functionality causing the infringement. \r\n\r\n**8.5. I, Me, or My.**   “I,” “me,” or “my” refers to the signatory below and its Bound Entities, if applicable.\r\n\r\n**8.6. Permitted Uses.**  “Permitted Uses” means making, using, selling, offering for sale, importing or distributing any implementation of the Specification 1) only to the extent it implements the Specification and 2) so long as all required portions of the Specification are implemented. Permitted Uses do not extend to any portion of an implementation that is not included in the Specification.\r\n\r\n**8.7. Related Entities.**  “Related Entities” means 1) any entity that Controls the Bound Entity (“Upstream Entity”), and 2) any other entity that is Controlled by an Upstream Entity that is not itself a Bound Entity.\r\n\r\n**8.8. Specification.**  “Specification” means the Specification identified below.\r\n\r\n**8.9. You or Your.**  “You,” “you,” or “your” means any person or entity who exercises copyright or patent rights granted under this Agreement, and any person or entity you Control.\r\n \r\n \r\n# Scope\r\n\r\n\r\nSpecification and version this Agreement applies to:\r\nFDC3 version 1.0, comprising the following specifications:\r\nAPI (https://fdc3.finos.org/docs/1.0/api/api-spec)\r\nIntents (https://fdc3.finos.org/docs/1.0/intents-spec)\r\nContext Data (https://fdc3.finos.org/docs/1.0/context-spec)\r\nApp Directory (https://fdc3.finos.org/docs/1.0/appd-spec)\r\n \r\nThe “required portions” of the specifications as referenced in Section 8.6 (“Permitted Uses”) are defined by https://fdc3.finos.org/docs/1.0/fdc3-compliance.\r\n\r\n\r\n# Signatures\r\n\r\nI certify that I am authorized to execute this agreement on behalf of the Bound Entity named below, and that all promises made herein relating to this Specification are commitments of the Bound Entity.\r\n\r\n* Adaptive Financial Consulting, 110 Bishopsgate, London EC2N 4AY, UK (2019-03-13)\r\n* ChartIQ, Inc., 609 East Market St, Suite 111, Charlottesville, VA 22902 (2019-03-12)\r\n* Cloud9 Technologies LLC, 565 5th Avenue, 18th Floor, NY, NY 10017 (2019-03-21)\r\n* FactSet Research Systems Inc., 601 Merritt 7, 3rd Floor, Norwalk, CT 06851 (2019-05-28)\r\n* Green Key Technologies, 55 W Monroe St Suite 1650, Chicago IL 60603 (2019-04-04)\r\n* IHS Markit, 450 West 33rd Street, New York, NY 10001 (2019-04-05)\r\n* OpenFin Inc., 25 Broadway, FL9, New York, NY 10004 (2019-03-12)\r\n* Refinitiv, 3 Times Square, New York, NY 10036 (2019-03-14)\r\n* Scott Logic, 1 St. James Gate, Newcastle, NE1 4XF, UK\r\n* Tick42 OOD, 31 Aleksandar Malinov Blvd, Sofia 1729, Bulgaria\r\n"
  },
  {
    "path": "README.md",
    "content": "# FDC3 - Financial Desktop Connectivity and Collaboration Consortium\n\n<a href='http://fdc3.finos.org'><img src='./website/static/img/fdc3-logo-2019-color.png' height='150' alt='FDC3 Logo' aria-label='fdc3.finos.org' /></a>\n\n[![Latest Standard](https://img.shields.io/badge/release-2.2-blue)](https://github.com/finos/fdc3/releases/v2.2)\n[![npm](https://img.shields.io/npm/v/@finos/fdc3)](https://www.npmjs.com/package/@finos/fdc3)\n[![FINOS - Released](https://cdn.jsdelivr.net/gh/finos/contrib-toolbox@main/images/badge-released.svg)](https://finosfoundation.atlassian.net/wiki/display/FINOS/Released)\n[![License Code](https://img.shields.io/badge/code_license-Apache_2.0-blue)](https://opensource.org/licenses/Apache-2.0)\n[![License Standard](https://img.shields.io/badge/standard_license-CSL_1.0-blue)](https://github.com/finos/FDC3?tab=License-1-ov-file#readme)\n[![Stack Overflow](https://img.shields.io/badge/stackoverflow-fdc3-orange.svg)](https://stackoverflow.com/questions/tagged/fdc3)\n[![npm-build](https://github.com/finos/FDC3/workflows/npm-build/badge.svg)](https://github.com/finos/FDC3/actions?query=workflow%3Anpm-build)\n[![Slack](https://img.shields.io/badge/slack-@finos/fdc3-green.svg?logo=slack)](https://finos-lf.slack.com/messages/fdc3/)\n[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6579/badge)](https://bestpractices.coreinfrastructure.org/projects/6579)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/finos/FDC3/badge)](https://scorecard.dev/viewer/?uri=github.com/finos/FDC3)\n\n## What Is It?\n\n[FDC3](https://fdc3.finos.org) is an open standard for applications on financial desktop to interoperate and exchange data with each other.  \n\n- Users benefit from a more joined-up experience, which reduces the \"friction\" in getting common tasks done,\n- By enabling applications to:\n  - launch other apps (build a launcher),\n  - respond to activity in other apps (context sharing),\n  - request functionality from other apps (raising intents).\n\n### What Are The Benefits?\n\n#### 📇 Help Manage Information Overload\n\n> Finance is an information-dense environment.  \n> Typically, traders will use serveral different displays so that they can keep track of multiple information sources at once.\n> FDC3 helps with this by sharing the \"context\" between multiple applications, so that they collectively track the topic the user is focused on.\n\n#### 🏃‍♂️ Work Faster\n\n> FDC3 standardizes a way to call actions between applications (called \"intents\").\n> Applications can raise intents for other apps to resolve, extending each other's functionality.\n> Instead of the user copy-and-pasting bits of data from one application to another, FDC3 makes sure the intents have the data they need to seamlessly transition activity between applications.\n\n#### 🖥️  Platform Agnostic\n\n> As an open standard, FDC3 can be implemented on any platform and in any language.\n> All that is required is a \"Desktop Agent\" that implements the FDC3 standard, which is responsible for co-ordinating application interactions.  (For a list of open source and proprietary desktop agents, see \"Platform providers\" [here](https://fdc3.finos.org/community#type-platform-provider).)\n> FDC3 is successfully running on Web and Native platforms in financial institutions around the world.\n\n#### 🔌  End the Integration Nightmare\n\n> By providing support for FDC3, vendors and financial organizations alike can avoid the bilateral or trilateral integration projects that plague desktop app roll-out, cause vendor lock-in and result in a slow pace of change on the Financial Services desktop.\n\n#### 👐 Open Standards Promote Innovation\n\n> FDC3 is developed collaboratively by a [consortium of industry participants](https://fdc3.finos.org/community#type-all) including banks, agent vendors, app developers and FinTech firms.  By design, FDC3 is open to extension.  We have an active community working on growing and improving the standard with new data and intents.\n\n## How Does It Work?\n\nFDC3 includes a standardized API for a Desktop agent, an OpenAPI App Directory, standard verbs to invoke actions between applications (called \"intents\"), standard formats for data passed between applications (called \"context data\") and a wire-protocol for Desktop Agents to communicate with each other (called \"Desktop Agent Bridging\").\n\nHence, the standard currently consists of five parts:\n\n1. [API Part](https://fdc3.finos.org/docs/api/spec)\n2. [App Directory Part](https://fdc3.finos.org/docs/app-directory/overview)\n3. [Intents part](https://fdc3.finos.org/docs/intents/spec)\n4. [Context Data Part](https://fdc3.finos.org/docs/context/spec)\n5. [Agent Bridging Part](https://fdc3.finos.org/docs/next/agent-bridging/spec) [`@experimental`](https://fdc3.finos.org/docs/fdc3-compliance#experimental-features)\n\nThe specifications are informed by agreed [business use cases](https://fdc3.finos.org/docs/use-cases/overview), and implemented and used by leading [financial industry participants](https://fdc3.finos.org/community#type-all).\n\n### More Resources\n\n- See <https://fdc3.finos.org> for more information, including on [Compliance](https://fdc3.finos.org/docs/fdc3-compliance) and the [FDC3 charter](https://fdc3.finos.org/docs/fdc3-charter), as well as a comprehensive [API Reference](https://fdc3.finos.org/docs/api/ref/DesktopAgent).\n- You can also take the free [FDC3 Training](https://www.edx.org/course/fdc3-interoperability-for-the-financial-desktop) for an introduction to FDC3's core concepts and usage.\n- The [FDC3 Community Page Training Tab](https://fdc3.finos.org/community#type-examples-and-training) also contains a selection of online resources to browse.\n- FINOS' open source Desktop Agent, [FDC3 Sail](https://github.com/finos/FDC3-Sail) project written with Node / Electron.\n\n## Supported Platforms\n\n- As an open standard, FDC3 can be implemented on any platform and in any language.\n- All that is required is a \"desktop agent\" that supports the FDC3 standard, which is responsible for coordinating application interactions.\n- Get started using FDC3 on the web with TypeScript by reading the [supported platforms](https://fdc3.finos.org/docs/supported-platforms) page.\n\n## FDC3 Project Structure\n\nThis project (the FDC3 Standard repo) is now a monorepo containing the following modules:\n\n| Directory                            | Release Coordinates                                    | Purpose                                                                                                                                                                                                                | Testing / Coverage    |\n|--------------------------------------|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|\n| `packages/fdc3-schema`               | `@finos/fdc3-schema` (npm)                             | Contains the FDC3 For The Web and Desktop Agent Bridging protocol schemas.   Generates `BridgingTypes.ts` and `BrowserTypes.ts` versions of those schemas for consumption in typescript code.                          | n/a                   |\n| `packages/fdc3-context`              | `@finos/fdc3-context` (npm)                            | Contains the schemas for standard FDC3 context types.  Generates the `ContextTypes.ts` typescript version of the schema for consumption in typescript/javascript.                                                      | n/a                   |\n| `packages/fdc3-standard`             | `@finos/fdc3-standard` (npm)                           | Interface definitions for the FDC3 standard in typescript (e.g. the `DesktopAgent` interface) and the app directory schema.                                                                                            | Jest, embedded NYC    |\n| `packages/fdc3-agent-proxy`          | `@finos/fdc3-agent-proxy` (npm)                        | Contains a complete implementation of the FDC3 DACP.  Written in a platform-agnostic manner.                                                                                                                            | Cucumber, NYC         |\n| `packages/fdc3-get-agent`            | `@finos/fdc3-get-agent` (npm)                          | Implements the `getAgent` and `fdc3Ready()` functions as well as the FDC3 Web Connection protocol to allow FDC3 to work on the web or in an electron container.                                                     | Cucumber, NYC         |\n| `packages/testing`                   | -not released-                                         | Contains testing tools used by the cucumber tests used within other modules of this project.                                                                                                                           |                       |\n| `toolbox/fdc3-conformance`           | -not released-                                         | Contains definitions of the [FDC3 conformance test suite](https://fdc3.finos.org/docs/api/conformance/Conformance-Overview)                                                         | Test Definitions Only |\n| `toolbox/fdc3-workbench`             | [here](https://fdc3.finos.org/toolbox/fdc3-workbench/) | Contains an FDC3-For-Web ready version of the [FDC3 Workbench](toolbox/fdc3-workbench/README.md).                                                                                                                      |                       |\n| `toolbox/fdc3-explained`             | [Here](https://fdc3.finos.org/toolbox/fdc3-explained)  | [Readme Here](toolbox/fdc3-explained/README.md)                                                                                                                                                                        |                       |\n| `toolbox/fdc3-for-web/fdc3-web-impl` | `@finos/fdc3-web-impl` (npm)                           | Portable and reusable implementation of the FDC3 For-The-Web Desktop Agent-Side protocol,                                                                                                                              | Cucumber, NYC         |\n| `toolbox/fdc3-for-web/demo`          | -not released-                                         | A reference implementation of an FDC3-For-The-Web Desktop Agent, using the above implementation and conforming to  the conformance test suite (see above) |                       |\n| `packages/fdc3`                      | `@finos/fdc3` (npm)                                    | Imports `fdc3-standard`, `fdc3-context`, `fdc3-schema` and `fdc3-get-agent` sub-modules.  This is intended to be the main entry point for typescript / javascript applications using FDC3         |                       |\n| `packages/fdc3-commonjs`                      | `@finos/fdc3-commonjs` (npm)                                    | A roll-up of the `fdc3` sub-module.  This is for **backwards compatibility where CommonJS is required**.  May not be provided in future versions of FDC3.         |                       |\n\n\n### Building and Running The FDC3 Modules\n\nFrom the root package, you can run `npm run build` to build all the modules, or `npm run test` to run all the tests.  `npm run dev` will start the `demo` and `fdc3-workbench` modules.  You can play with both of these components in your browser at <http://localhost:4000/static/da/index.html>.  Additionally, the conformance suite is included as one of the demo apps, and can also be run.  \n\nFor installation and usage instructions, see: <https://fdc3.finos.org/docs/supported-platforms#usage>\n\n### Releasing FDC3 to NPM (for maintainers)\n\nPublishing to npm is handled automatically by the [Publish To NPM](.github/workflows/release.yml) GitHub Actions workflow, which is triggered when a GitHub Release is published. The workflow will lint, test and build the project, then publish all public workspace packages to both npmjs.org and GitHub Packages.\n\nThe npm dist-tag is determined by the version in the root `package.json`: versions containing a hyphen (e.g. `2.3.0-beta.1`) are published with the `prerelease` tag, while all other versions are published with the `latest` tag.\n\n1.  **Create a release branch**\n\n  ```bash\n  git checkout -b release/v2.3\n  ```\n\n2.  **Update version numbers**\n\n  All workspace versions and the root `package.json` version must match. Update them as follows:\n\n  ```bash\n  npm version <new-version> --include-workspace-root --workspaces\n  npm run syncpack   # synchronizes @finos/* dependency versions and verifies consistency\n  npm up             # fixes node_module references\n  npm run build      # builds all modules against the new version\n  ```\n\n  The `syncpack` script will automatically run `version-check` to verify that the root version matches all public workspace versions. You can also run `npm run version-check` independently at any time.\n\n3.  **Push the branch and create a PR**\n\n  ```bash\n  git add .\n  git commit -m \"Updated to version v2.3.0\"\n  git push origin release/v2.3\n  ```\n\n  Create a PR to merge the release branch into main. You will need other FDC3 maintainers to review and approve the PR.\n\n4.  **Create a GitHub Release to publish to npm**\n\n  Once the PR is merged, [create a new GitHub Release](https://github.com/finos/FDC3/releases/new) targeting the main branch. Publishing the release will trigger the workflow, which will publish all packages to npm and GitHub Packages.\n\n  The workflow also runs a version consistency check before publishing — if the root version doesn't match the workspace versions, the workflow will fail before any packages are published.\n\n### Releasing the FDC3 Website (for maintainers)\n\nPlease see instructions in the [website README](./website/README.md).\n\n## Getting Involved\n\n### Using the standard? Let us know\n\nIf you are an existing individual or corporate user of the FDC3 standard, we would love to hear from you: just email [fdc3@finos.org](mailto:fdc3@finos.org) with details about how you are using the standard.\n\n- If you'd like to be listed as on the community page, please fill out the [Usage Form](https://share.hsforms.com/1gOo0_A70QqyahOygzryVQg1fux8).\n- If listing your logo publicly requires legal evaluation, you can reach out **privately** to the [FDC3 Maintainers](mailto:fdc3-maintainers-private@finos.org).\n\n### Interact with the FDC3 community\n\n#### GitHub\n\n- FDC3 activity primarily happens in this [FDC3 GitHub repository](https://github.com/finos/fdc3). [Watch](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) the repository in order to be notified of new Pull Requests and issues.\n\n#### Slack\n\n- The fastest and more interactive way to connect and ask questions to the FDC3 community is to join the [#fdc3 channel on the FINOS slack](https://finos-lf.slack.com/messages/fdc3/).\n\n#### Email\n\n- If you'd like to receive official updates, and/or you don't have access to Slack, please send an email to [fdc3@finos.org](mailto:fdc3@finos.org). You can join the list by sending an email to [fdc3+subscribe@finos.org](mailto:fdc3+subscribe@finos.org).\n- To contact the FDC3 maintainers, send an email to [fdc3-maintainers@finos.org](mailto:fdc3-maintainers@finos.org).\n\n#### Meetings\n\nAnother great way to interact with the community is to attend one of the following meetings:\n\n- **FDC3 General Meeting** - *Every 6 months on the third Tuesday* ([Join Meeting](https://calendar.finos.org/signup?eventId=6stt9c3m0r4boisrb6tjt4q0v7_20260317T140000Z&title=FDC3+General+Meeting))\n- **FDC3 Identity & Security Working Group** - *Monthly on the second Thursday* ([Join Meeting](https://zoom-lfx.platform.linuxfoundation.org/meeting/92600977319?password=17e9e8f8-7d4e-47b4-b8f0-8c68b02005de&invite=true))\n- **FDC3 Standard Working Group** - *Monthly on the fourth Thursday* ([Join Meeting](https://zoom-lfx.platform.linuxfoundation.org/meeting/96839365264?password=b5c2bc6a-bc47-43a5-bc49-7be3e0b422c3&invite=true))\n- **FDC3 Use Cases and Workflows Discussion Group** - *Monthly on the first Thursday* ([Join Meeting](https://zoom-lfx.platform.linuxfoundation.org/meeting/91001005768?password=0c878e0c-b8a4-42d3-9786-e8c1524d6d1c&invite=true))\n- **FDC3 Web Browsers + Bridging Discussion group** - *Monthly on the third Thursday* ([Join Meeting](https://zoom-lfx.platform.linuxfoundation.org/meeting/96615992377?password=88ed4841-afa2-41a6-8de3-e246967e5566&invite=true))\n\nAlso consider:\n\n- **FDC3 Sail Project Meeting** - *Every 2 weeks on Mondays* ([Join Meeting](https://zoom-lfx.platform.linuxfoundation.org/meeting/95252800112?password=90638454-991c-4ab0-8aed-791fc372623c&invite=true))\n\n\n\n#### Need help?\n\n- Email [fdc3@finos.org](mailto:fdc3@finos.org) if you need help getting started in the FDC3 Community.\n- If you encounter technical difficulties accessing repositories, joining Slack, mailing lists or meetings, please email [help@finos.org](mailto:help@finos.org).\n\n### Roadmap\n\nWork on FDC3 is split into several [discussion groups](GOVERNANCE.md#1roles) and releases.  \n\n- Discussion groups each have their own regular meetings in the [FINOS Community Calendar](https://calendar.google.com/calendar/embed?src=finos.org_fac8mo1rfc6ehscg0d80fi8jig%40group.calendar.google.com).  \n\n- Releases can be tracked on the [FDC3 Milestones](https://github.com/finos/FDC3/milestones) page.\n\n### Contributing\n\nPlease see the [Contributing](CONTRIBUTING.md) guide for details on how to contribute to FDC3.\n\n_NOTE:_\n\n- Issues that change the Standard usually need discussion. You can post comments directly on the issue or can ask for it to be added to a Standards Working Group meeting agenda by emailing [fdc3@finos.org](mailto:fdc3@finos.org), sending a message to the [#fdc3 channel on the FINOS slack](https://finos-lf.slack.com/messages/fdc3/) or tag the FDC3 maintainers (`@finos/fdc3-maintainers`) in your issue.\n- Contributions merged into the main branch of the FDC3 repository will form part of the next pre-draft of the FDC3 Standard (as defined by the [FDC3 Governance document](./GOVERNANCE.md)), which must be approved by a Standard Working Group vote before it is accepted as a draft and subsequently released as the next version of the Standard.\n\n### Why should you get involved in FDC3?\n\nIf you or your firm intends to make use of the FDC3 Standard (by implementing a Desktop Agent or App Directory, by adding support to apps to interoperate with others via FDC3, or even by using apps, Desktop Agents or App Directories written by others) then contributing to the governance, maintenance and onward development of the FDC3 Standard will help to protect and strengthen the ecosystem developing around FDC3. Doing so will also empower you to help guide the Standard in directions that are relevant to your use or that of your firm.\n\nIf you or your firm are new to contributing to open source projects, please see the variety of resources available from FINOS, (such as the [Open Source readiness project](https://www.finos.org/open-source-readiness)), Linux Foundation ([Participating in Open Source communities](https://www.linuxfoundation.org/tools/participating-in-open-source-communities/)) and others (e.g. [opensource.guide](https://opensource.guide/)).\n\n### What Roles Do Participants Hold?\n\nPlease refer to the FDC3 [Governance document](GOVERNANCE.md#1roles) for details of the different roles on the FDC3 project.\n\n### FINOS Code of Conduct\n\nParticipants of FINOS standards projects should follow the FINOS Code of Conduct, which can be found at: <https://community.finos.org/docs/governance/code-of-conduct>\n\n## License & Patents\n\n- This version of the FDC3 Standard is licensed under the [Community Specification License](LICENSE.md).  SPDX-License-Identifier: [Community-Spec-1.0](https://spdx.org/licenses/Community-Spec-1.0). \n\n- Reference implementations and other software contained in FDC3 repositories is licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). SPDX-License-Identifier: [Apache-2.0](https://spdx.org/licenses/Apache-2.0). \n\n- See [Licenses in the FDC3 Charter](https://fdc3.finos.org/docs/fdc3-charter) for details of licensing for previous versions of the FDC3 Standard and [NOTICES.md](./NOTICES.md) for details of license acceptance, withdrawals and exclusions. \n\n- See [Intellectual Property Claims in the FDC3 Charter](https://fdc3.finos.org/docs/fdc3-charter#intellectual-property-claims) for details of patents in the 1.1-present versions of FDC3.  \n\n- See [PATENTS-FDC3-1.0](PATENTS-FDC3-1.0.md) for details of patents in the 1.0 version of FDC3.\n\n## Vulnerabilities / Security\n\nPlease see our [Security Policy](SECURITY.md)\n\n## Intellectual Property Claims\n\nUsers of the FDC3 standard are requested to submit, with their comments, notification of any relevant patent claims or other intellectual property rights of which they may be aware that might be infringed by any implementation of the standard set forth in this document, and to provide supporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY WHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS EXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE ENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION, NOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY WHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF ANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE OF THIS STANDARD.\n\n## FDC3 Archive\n\nAn archive of FDC3 documentation and meeting notes from the early days of FDC3 is available at <https://finosfoundation.atlassian.net/wiki/spaces/FDC3/overview>. Later meeting minutes cam be found in closed Github issues.\n\nThe mailing list archive for [fdc3@finos.org](mailto:fdc3@finos.org) is available at <https://groups.google.com/a/finos.org/g/fdc3>\n"
  },
  {
    "path": "SCOPE.md",
    "content": "# Scope\n\nThe FDC3 Standard specifies protocols and taxonomies to enable applications in financial services workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements between app developers.\n\nFinancial applications include any type of application used in common financial workflows, including:\n\n* Containerized Web applications - Interoperability platforms extending Chromium (e.g. Electron, OpenFin, interop.io's io.Connect)\n* PWAs & Web applications running in a commercial browser\n* Traditional native applications implemented in C++, .NET, Java, Python, etc.\n* Hybrid web/native applications - stand alone native apps embedding a WebView (e.g. Electron, CEF, WebView2, NW.js etc.)\n* Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, Slack, etc.\n\nThis standards group is focused specifically on establishing and promoting standards for the interoperability of front-end applications, hence, its activities are focused on:\n\n* The discovery, configuration, identity and use of financial services applications (e.g. the FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview)),\n* APIs for communication and interaction between applications (e.g. the [Desktop Agent API](https://fdc3.finos.org/docs/api/spec) and [Agent Bridging API](https://fdc3.finos.org/docs/agent-bridging/spec)),\n* Message formats used for communication (e.g. [Context Data](https://fdc3.finos.org/docs/context/spec))\n* Names for requested functionality and workflow steps (e.g. [Intents](https://fdc3.finos.org/docs/intents/spec))\n* Creating and promoting tests for conformance to these standards (e.g. the FDC3 Conformance Framework) and training & certification programs that relate to them (e.g. [Introduction to FDC3](https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/))\n\n\nThe group's activities do not include:\n\n* Interoperability or communication between back-end platforms.\n* Defining financial objects - where existing standards are well established and can be reused.\n\nAny changes of Scope are not retroactive.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nUse this section to tell people about which versions of your project are currently being supported with security updates.\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 1.2     | :white_check_mark: |\n| 2.0     | :white_check_mark: |\n| < 1.2   | :x:                |\n\n## Reporting a Vulnerability\n\nIf you uncover vulnerabilities in this software, please contact `help@finos.org` privately.  We aim to respond within 3 working days.\n\n## FINOS Security Scanning\n\nThe FDC3 project is scanned using [GitHub Actions](https://github.com/finos/FDC3/actions) provided by the [FINOS Security Scanning](https://github.com/finos/security-scanning) project. If, as a maintainer, you can't access the results of these, please contact [FINOS Help](mailto:help@finos.org).\n"
  },
  {
    "path": "allow-list.json",
    "content": "{\n    \"ignore\": [\n        { \"id\": \"CVE-2023-45857\", \"reason\": \"False positive as already on 0.28.1\" }\n    ]\n}\n"
  },
  {
    "path": "comment-template.md",
    "content": "## Coverage Report\n\nCommit: [{{short_commit_sha}}]({{commit_link}})\nBase: [{{base_ref}}@{{base_short_commit_sha}}]({{base_commit_link}})\n\n| Type                      | Base                                       | This PR                                                                            |\n|---------------------------|--------------------------------------------|------------------------------------------------------------------------------------|\n| Total Statements Coverage | {{base_total_statements_coverage_percent}} | {{total_statements_coverage_percent}} ({{total_statements_coverage_percent_diff}}) |\n| Total Branches Coverage   | {{base_total_branches_coverage_percent}}   | {{total_branches_coverage_percent}} ({{total_branches_coverage_percent_diff}})     |\n| Total Functions Coverage  | {{base_total_functions_coverage_percent}}  | {{total_functions_coverage_percent}} ({{total_functions_coverage_percent_diff}})   |\n| Total Lines Coverage      | {{base_total_lines_coverage_percent}}      | {{total_lines_coverage_percent}} ({{total_lines_coverage_percent_diff}})           |\n\n<details>\n<summary>Details (changed files)</summary>\n{{changed_files_coverage_table}}\n</details>\n<details>\n<summary>Details (all files)</summary>\n{{files_coverage_table}}\n</details>"
  },
  {
    "path": "netlify.toml",
    "content": "[build]\n  ignore = \"git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF . ../{packages,website,toolbox}/\"\n\n[[headers]]\n  # Define which paths this specific [[headers]] block will cover.\n  for = \"/*\"\n    [headers.values]\n    Access-Control-Allow-Origin = \"*\"\n    \n[build.environment]\n  NODE_VERSION = \"22\"\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@finos/fdc3\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"main\": \"dist/index.js\",\n  \"typings\": \"dist/index.d.ts\",\n  \"module\": \"dist/fdc3.esm.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"workspaces\": [\n    \"packages/fdc3-schema\",\n    \"packages/fdc3-context\",\n    \"packages/fdc3-standard\",\n    \"packages/testing\",\n    \"packages/fdc3-agent-proxy\",\n    \"toolbox/fdc3-for-web/fdc3-web-impl\",\n    \"packages/fdc3-get-agent\",\n    \"packages/fdc3\",\n    \"packages/fdc3-commonjs\",\n    \"toolbox/fdc3-for-web/reference-ui\",\n    \"toolbox/fdc3-for-web/demo\",\n    \"toolbox/fdc3-workbench\",\n    \"toolbox/fdc3-conformance\"\n  ],\n  \"scripts\": {\n    \"clean\": \"npm run clean --workspaces --if-present\",\n    \"build\": \"npm run build --workspaces --if-present\",\n    \"test\": \"npm run test --workspaces --if-present\",\n    \"merge\": \"istanbul-merge --out coverage/complete.json packages/fdc3-standard/coverage/coverage-final.json packages/fdc3-get-agent/coverage/coverage-final.json packages/fdc3-agent-proxy/coverage/coverage-final.json toolbox/fdc3-for-web/fdc3-web-impl/coverage/coverage-final.json\",\n    \"report\": \"nyc report --reporter json-summary --report-dir nyc-coverage-report --exclude-after-remap false --temp-dir coverage\",\n    \"lint\": \"npm run lint --workspaces --if-present\",\n    \"syncpack\": \"npm exec syncpack -- fix --dependencies \\\"@finos/*\\\" && npm run version-check\",\n    \"version-check\": \"node scripts/version-check.js\",\n    \"dev\": \"concurrently \\\"cd toolbox/fdc3-conformance && npm run dev\\\" \\\"cd toolbox/fdc3-workbench && npm run dev\\\" \\\"cd toolbox/fdc3-for-web/reference-ui && npm run dev\\\" \\\"cd toolbox/fdc3-for-web/demo && npm run dev\\\"\",\n    \"prepare\": \"husky\"\n  },\n  \"prettier\": {\n    \"semi\": true,\n    \"singleQuote\": true,\n    \"arrowParens\": \"avoid\",\n    \"trailingComma\": \"es5\",\n    \"endOfLine\": \"auto\",\n    \"printWidth\": 120\n  },\n  \"dependencies\": {\n    \"syncpack\": \"^14.0.0\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.19.0\",\n    \"@types/mocha\": \"^10.0.10\",\n    \"@types/node\": \"^20.16.11\",\n    \"@vitest/coverage-v8\": \"^3.2.4\",\n    \"concurrently\": \"^8.2.2\",\n    \"eslint\": \"^9.32.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"globals\": \"^15.14.0\",\n    \"husky\": \"^9.1.7\",\n    \"istanbul-merge\": \"^2.0.0\",\n    \"lint-staged\": \"^15.2.10\",\n    \"nyc\": \"17.1.0\",\n    \"pixelmatch\": \"^7.1.0\",\n    \"prettier\": \"3.4.1\",\n    \"rimraf\": \"^6.0.1\",\n    \"tsx\": \"^4.19.1\",\n    \"typescript\": \"^5.6.3\",\n    \"typescript-eslint\": \"^8.17.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"overrides\": {\n    \"serialize-javascript\": \"^7.0.5\"\n  },\n  \"lint-staged\": {\n    \"**/*\": \"prettier --write --ignore-unknown\"\n  }\n}\n"
  },
  {
    "path": "packages/fdc3/README.md",
    "content": "# FDC3\n\nThis npm module is the main entry point for the Financial Desktop Connectivity and Collaboration Consortium (FDC3) JavaScript API.\n\nSince version 2.2.0 this module only provides an ES6 module. Applications requiring a CommonJS module should either update to ES6 or switch to the [@finos/fdc3-commonjs module](https://npmjs.com/package/@finos/fdc3-commonjs) (provided for backwards compatibility).\n\n## Installation\n\nTo install the FDC3 module, use npm:\n\n```bash\nnpm install @finos/fdc3\n```\n\n## Usage\n\nTo use the FDC3 module in your project, import it as follows:\n\n```javascript\nimport { getAgent } from '@finos/fdc3';\n// getAgent() returns the FDC3 Desktop Agent\nconst fdc3 = getAgent();\n\n// Example usage\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n};\n\nfdc3.raiseIntent('ViewProfile', contact);\n```\n\n## Documentation\n\nFor detailed documentation and API reference, please visit the [official FDC3 documentation](https://fdc3.finos.org/docs/api/spec).\n\n## Contributing\n\nWe welcome contributions to the FDC3 project. Please see our [contributing guidelines](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for more information.\n\n## License\n\nThis project is licensed under the [Apache 2.0 License](LICENSE).\n\n## Contact\n\nFor any questions or support, please reach out to the FDC3 community on our [Slack channel](https://finos-lf.slack.com/archives/CJ8Q8H4Q1) or [mailing list](mailto:fdc3@finos.org).\n\n## Further Details\n\nFurther details are avilable in the main [FDC3 Project README](https://github.com/finos/FDC3)\n"
  },
  {
    "path": "packages/fdc3/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"clean\": \"npx rimraf dist\",\n    \"build\": \"tsc\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3-context\": \"2.2.2\",\n    \"@finos/fdc3-get-agent\": \"2.2.2\",\n    \"@finos/fdc3-schema\": \"2.2.2\",\n    \"@finos/fdc3-standard\": \"2.2.2\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/fdc3/src/index.ts",
    "content": "export * from '@finos/fdc3-context';\n\nimport { BrowserTypes, BridgingTypes } from '@finos/fdc3-schema';\nexport { BridgingTypes, BrowserTypes };\n\nimport { DesktopAgent, AppIdentifier } from '@finos/fdc3-standard';\nexport * from '@finos/fdc3-standard';\nexport { AppIdentifier };\n\nimport { getAgent, fdc3Ready } from '@finos/fdc3-get-agent';\nexport { getAgent, fdc3Ready };\n\ndeclare global {\n  interface Window {\n    fdc3?: DesktopAgent;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.root.json\",\n  \"compilerOptions\": {\n    \"rootDirs\": [\n      \"src\"\n    ],\n    \"outDir\": \"dist\",\n  },\n  \"include\": [\n    \"src\",\n  ],\n  \"exclude\": [],\n  \"references\": [\n    {\n      \"path\": \"../fdc3-schema\"\n    },\n    {\n      \"path\": \"../fdc3-context\"\n    },\n    {\n      \"path\": \"../fdc3-get-agent\"\n    },\n    {\n      \"path\": \"../fdc3-standard\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-agent-proxy/README.md",
    "content": "# FDC3 Agent Proxy\n\nThis package contains complete implementation of the FDC3 Desktop Agent Communication Protocol (DACP).  \n\nFurther details:\n - https://github.com/finos/FDC3\n - [FDC3 Specification](https://fdc3.finos.org/)\n - Main FDC3 module: https://www.npmjs.com/package/@finos/fdc3"
  },
  {
    "path": "packages/fdc3-agent-proxy/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-agent-proxy\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"type\": \"module\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc && vitest run\",\n    \"test:watch\": \"vitest\",\n    \"test:coverage\": \"vitest run --coverage\",\n    \"clean\": \"rimraf dist coverage node_modules\",\n    \"lint\": \"eslint src/\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3-standard\": \"2.2.2\"\n  },\n  \"devDependencies\": {\n    \"@cucumber/cucumber\": \"10.3.1\",\n    \"@finos/testing\": \"2.2.2\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"eslint-plugin-import\": \"^2.31.0\",\n    \"eslint-plugin-prettier\": \"3.3.1\",\n    \"is-ci\": \"2.0.0\",\n    \"jsonpath-plus\": \"^10.1.0\",\n    \"quickpickle\": \"^1.0.0\",\n    \"uuid\": \"^9.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/DesktopAgentProxy.ts",
    "content": "import {\n  AppIdentifier,\n  AppMetadata,\n  ContextHandler,\n  DesktopAgent,\n  EventHandler,\n  FDC3EventTypes,\n  ImplementationMetadata,\n  IntentHandler,\n  IntentResolution,\n  Listener,\n  LogLevel,\n} from '@finos/fdc3-standard';\nimport { ChannelSupport } from './channels/ChannelSupport.js';\nimport { AppSupport } from './apps/AppSupport.js';\nimport { IntentSupport } from './intents/IntentSupport.js';\nimport { Connectable, Channel } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { HeartbeatSupport } from './heartbeat/HeartbeatSupport.js';\nimport { Logger } from './util/Logger.js';\n\n/**\n * This splits out the functionality of the desktop agent into\n * app, channels and intents concerns.\n */\nexport class DesktopAgentProxy implements DesktopAgent, Connectable {\n  readonly heartbeat: HeartbeatSupport;\n  readonly channels: ChannelSupport;\n  readonly intents: IntentSupport;\n  readonly apps: AppSupport;\n  readonly connectables: Connectable[];\n\n  constructor(\n    heartbeat: HeartbeatSupport,\n    channels: ChannelSupport,\n    intents: IntentSupport,\n    apps: AppSupport,\n    connectables: Connectable[],\n    logLevel: LogLevel | null\n  ) {\n    this.heartbeat = heartbeat;\n    this.intents = intents;\n    this.channels = channels;\n    this.apps = apps;\n    this.connectables = connectables;\n    //Default log level is set in the Logger utility\n    if (logLevel) {\n      Logger.setLogLevel(logLevel);\n    }\n\n    //bind all functions to allow destructuring\n    this.addEventListener = this.addEventListener.bind(this);\n    this.getInfo = this.getInfo.bind(this);\n    this.broadcast = this.broadcast.bind(this);\n    this.addContextListener = this.addContextListener.bind(this);\n    this.getUserChannels = this.getUserChannels.bind(this);\n    this.getSystemChannels = this.getSystemChannels.bind(this);\n    this.getOrCreateChannel = this.getOrCreateChannel.bind(this);\n    this.createPrivateChannel = this.createPrivateChannel.bind(this);\n    this.leaveCurrentChannel = this.leaveCurrentChannel.bind(this);\n    this.joinUserChannel = this.joinUserChannel.bind(this);\n    this.joinChannel = this.joinChannel.bind(this);\n    this.getCurrentChannel = this.getCurrentChannel.bind(this);\n    this.joinChannel = this.joinChannel.bind(this);\n    this.findIntent = this.findIntent.bind(this);\n    this.findIntentsByContext = this.findIntentsByContext.bind(this);\n    this.raiseIntent = this.raiseIntent.bind(this);\n    this.addIntentListener = this.addIntentListener.bind(this);\n    this.raiseIntentForContext = this.raiseIntentForContext.bind(this);\n    this.open = this.open.bind(this);\n    this.findInstances = this.findInstances.bind(this);\n    this.getAppMetadata = this.getAppMetadata.bind(this);\n    this.disconnect = this.disconnect.bind(this);\n    this.connect = this.connect.bind(this);\n  }\n\n  addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise<Listener> {\n    return this.channels.addEventListener(handler, type);\n  }\n\n  getInfo(): Promise<ImplementationMetadata> {\n    return this.apps.getImplementationMetadata();\n  }\n\n  async broadcast(context: Context): Promise<void> {\n    const channel = await this.channels.getUserChannel();\n    if (channel) {\n      return channel.broadcast(context);\n    } else {\n      return Promise.resolve();\n    }\n  }\n\n  addContextListener(\n    contextTypeOrHandler: ContextHandler | string | null,\n    handler?: ContextHandler\n  ): Promise<Listener> {\n    let theContextType: string | null;\n    let theHandler: ContextHandler;\n\n    if (contextTypeOrHandler == null && typeof handler === 'function') {\n      theContextType = null;\n      theHandler = handler;\n    } else if (typeof contextTypeOrHandler === 'string' && typeof handler === 'function') {\n      theContextType = contextTypeOrHandler;\n      theHandler = handler;\n    } else if (typeof contextTypeOrHandler === 'function') {\n      // deprecated one-arg version\n      theContextType = null;\n      theHandler = contextTypeOrHandler as ContextHandler;\n    } else {\n      //invalid call\n      // TODO: Replace with Standardized error when #1490 is resolved\n      throw new Error('Invalid arguments passed to addContextListener!');\n    }\n\n    return this.channels.addContextListener(theHandler, theContextType);\n  }\n\n  getUserChannels() {\n    return this.channels.getUserChannels();\n  }\n\n  getSystemChannels() {\n    return this.channels.getUserChannels();\n  }\n\n  getOrCreateChannel(channelId: string) {\n    return this.channels.getOrCreate(channelId);\n  }\n\n  createPrivateChannel() {\n    return this.channels.createPrivateChannel();\n  }\n\n  leaveCurrentChannel() {\n    return this.channels.leaveUserChannel();\n  }\n\n  joinUserChannel(channelId: string) {\n    return this.channels.joinUserChannel(channelId);\n  }\n\n  joinChannel(channelId: string) {\n    return this.channels.joinUserChannel(channelId);\n  }\n\n  getCurrentChannel(): Promise<Channel | null> {\n    return this.channels.getUserChannel();\n  }\n\n  findIntent(intent: string, context: Context, resultType: string | undefined) {\n    return this.intents.findIntent(intent, context, resultType);\n  }\n\n  findIntentsByContext(context: Context) {\n    return this.intents.findIntentsByContext(context);\n  }\n\n  private ensureAppId(app?: string | AppIdentifier): AppIdentifier | undefined {\n    if (typeof app === 'string') {\n      return {\n        appId: app,\n      };\n    } else if (app?.appId) {\n      return app as AppIdentifier;\n    } else {\n      return undefined;\n    }\n  }\n\n  raiseIntent(intent: string, context: Context, app?: string | AppIdentifier) {\n    return this.intents.raiseIntent(intent, context, this.ensureAppId(app));\n  }\n\n  addIntentListener(intent: string, handler: IntentHandler) {\n    return this.intents.addIntentListener(intent, handler);\n  }\n\n  raiseIntentForContext(context: Context, app?: string | AppIdentifier): Promise<IntentResolution> {\n    return this.intents.raiseIntentForContext(context, this.ensureAppId(app));\n  }\n\n  open(app: string | AppIdentifier, context?: Context | undefined) {\n    return this.apps.open(this.ensureAppId(app)!, context);\n  }\n\n  findInstances(app: AppIdentifier) {\n    return this.apps.findInstances(app);\n  }\n\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata> {\n    return this.apps.getAppMetadata(app);\n  }\n\n  async disconnect(): Promise<void> {\n    await Promise.all(this.connectables.map(c => c.disconnect()));\n  }\n\n  async connect(): Promise<void> {\n    await Promise.all(this.connectables.map(c => c.connect()));\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/Messaging.ts",
    "content": "import { AppIdentifier } from '@finos/fdc3-standard';\nimport { RegisterableListener } from './listeners/RegisterableListener.js';\nimport {\n  AppRequestMessage,\n  AgentResponseMessage,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport interface Messaging {\n  /**\n   * Creates UUIDs used in outgoing messages\n   */\n  createUUID(): string;\n\n  /**\n   * Post an outgoing message\n   */\n  post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void>;\n\n  /**\n   * Registers a listener for incoming messages.\n   */\n  register(l: RegisterableListener): void;\n\n  /**\n   * Unregister a listener with the given id\n   * @param id\n   */\n  unregister(id: string): void;\n\n  /** Create a metadata element to attach to outgoing messages. */\n  createMeta(): AppRequestMessage['meta'];\n\n  /**\n   * Waits for a specific matching message\n   */\n  waitFor<X extends AgentResponseMessage>(\n    filter: (m: X) => boolean,\n    timeoutMs?: number,\n    timeoutErrorMessage?: string\n  ): Promise<X>;\n\n  /**\n   * Sends a request message and waits for a response. If the response contains a payload.error, it is thrown.\n   * @param message The request message to send.\n   */\n  exchange<X extends AgentResponseMessage>(\n    message: AppRequestMessage,\n    expectedTypeName: string,\n    timeoutMs: number\n  ): Promise<X>;\n\n  /**\n   * App identification used to provide source information used in\n   * message meta elements, IntentResolution etc..\n   */\n  getAppIdentifier(): AppIdentifier;\n\n  /** Disconnects the underlying message transport. */\n  disconnect(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/apps/AppSupport.ts",
    "content": "import { AppIdentifier, AppMetadata, ImplementationMetadata } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\n\nexport interface AppSupport {\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n  getImplementationMetadata(): Promise<ImplementationMetadata>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/apps/DefaultAppSupport.ts",
    "content": "import { AppIdentifier, AppMetadata, ImplementationMetadata, OpenError, ResolveError } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { AppSupport } from './AppSupport.js';\nimport { Messaging } from '../Messaging.js';\nimport {\n  FindInstancesRequest,\n  FindInstancesResponse,\n  GetAppMetadataRequest,\n  GetAppMetadataResponse,\n  GetInfoRequest,\n  GetInfoResponse,\n  OpenRequest,\n  OpenResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { throwIfUndefined } from '../util/throwIfUndefined.js';\nimport { Logger } from '../util/Logger.js';\n\nexport class DefaultAppSupport implements AppSupport {\n  readonly messaging: Messaging;\n  readonly messageExchangeTimeout: number;\n  readonly appLaunchTimeout: number;\n\n  constructor(messaging: Messaging, messageExchangeTimeout: number, appLaunchTimeout: number) {\n    this.messaging = messaging;\n    this.messageExchangeTimeout = messageExchangeTimeout;\n    this.appLaunchTimeout = appLaunchTimeout;\n  }\n\n  async findInstances(app: AppIdentifier): Promise<AppIdentifier[]> {\n    const request: FindInstancesRequest = {\n      type: 'findInstancesRequest',\n      payload: {\n        app,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const out = await this.messaging.exchange<FindInstancesResponse>(\n      request,\n      'findInstancesResponse',\n      this.messageExchangeTimeout\n    );\n    return out.payload.appIdentifiers ?? [];\n  }\n\n  async getAppMetadata(app: AppIdentifier): Promise<AppMetadata> {\n    const request: GetAppMetadataRequest = {\n      type: 'getAppMetadataRequest',\n      payload: {\n        app: app as AppIdentifier,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const response = await this.messaging.exchange<GetAppMetadataResponse>(\n      request,\n      'getAppMetadataResponse',\n      this.messageExchangeTimeout\n    );\n\n    throwIfUndefined(\n      response.payload.appMetadata,\n      'Invalid response from Desktop Agent to getAppMetadata!',\n      response,\n      ResolveError.TargetAppUnavailable\n    );\n\n    return response.payload.appMetadata!;\n  }\n\n  async open(app: AppIdentifier, context?: Context | undefined): Promise<AppIdentifier> {\n    const request: OpenRequest = {\n      type: 'openRequest',\n      payload: {\n        app: {\n          appId: app.appId,\n          instanceId: app.instanceId,\n        },\n        context,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const response = await this.messaging.exchange<OpenResponse>(request, 'openResponse', this.appLaunchTimeout);\n\n    throwIfUndefined(\n      response.payload.appIdentifier,\n      'Invalid response from Desktop Agent to open!',\n      response,\n      OpenError.AppNotFound\n    );\n\n    return response.payload.appIdentifier!;\n  }\n\n  async getImplementationMetadata(): Promise<ImplementationMetadata> {\n    const request: GetInfoRequest = {\n      type: 'getInfoRequest',\n      payload: {},\n      meta: this.messaging.createMeta(),\n    };\n\n    const response = await this.messaging.exchange<GetInfoResponse>(\n      request,\n      'getInfoResponse',\n      this.messageExchangeTimeout\n    );\n\n    if (response.payload.implementationMetadata) {\n      return response.payload.implementationMetadata;\n    } else {\n      //This will only happen if the DA implementation returns an invalid message with a missing implementationMetadata property\n      Logger.error('Invalid response from Desktop Agent to open!', response);\n      const unknownImpl: ImplementationMetadata = {\n        fdc3Version: 'unknown',\n        provider: 'unknown',\n        appMetadata: { appId: 'unknown', instanceId: 'unknown' },\n        optionalFeatures: {\n          OriginatingAppMetadata: false,\n          UserChannelMembershipAPIs: false,\n          DesktopAgentBridging: false,\n        },\n      };\n      return unknownImpl;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/channels/ChannelSupport.ts",
    "content": "import {\n  Channel,\n  Connectable,\n  ContextHandler,\n  EventHandler,\n  FDC3EventTypes,\n  Listener,\n  PrivateChannel,\n} from '@finos/fdc3-standard';\n\nexport interface ChannelSupport extends Connectable {\n  getUserChannel(): Promise<Channel | null>;\n  getUserChannels(): Promise<Channel[]>;\n  getOrCreate(id: string): Promise<Channel>;\n  createPrivateChannel(): Promise<PrivateChannel>;\n  leaveUserChannel(): Promise<void>;\n  joinUserChannel(id: string): Promise<void>;\n  addContextListener(handler: ContextHandler, type: string | null): Promise<Listener>;\n\n  /**\n   * TODO: Move handling for userChannelChanged out of ChannelSupport and update type to filter to channel events only.\n   */\n  addEventListener(handler: EventHandler, type: FDC3EventTypes | null): Promise<Listener>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/channels/DefaultChannel.ts",
    "content": "import { ContextHandler, DisplayMetadata, Listener, Channel, EventHandler } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { Messaging } from '../Messaging.js';\nimport { DefaultContextListener } from '../listeners/DefaultContextListener.js';\nimport {\n  BroadcastRequest,\n  BroadcastResponse,\n  ClearContextRequest,\n  ClearContextResponse,\n  GetCurrentContextRequest,\n  GetCurrentContextResponse,\n} from '@finos/fdc3-schema/generated/api/BrowserTypes.js';\nimport { RegisterableListener } from '../listeners/RegisterableListener.js';\nimport { EventListener } from '../listeners/EventListener.js';\n\nexport class DefaultChannel implements Channel {\n  protected readonly messaging: Messaging;\n  protected readonly messageExchangeTimeout;\n  readonly id: string;\n  readonly type: 'user' | 'app' | 'private';\n  readonly displayMetadata?: DisplayMetadata | undefined;\n\n  constructor(\n    messaging: Messaging,\n    messageExchangeTimeout: number,\n    id: string,\n    type: 'user' | 'app' | 'private',\n    displayMetadata?: DisplayMetadata\n  ) {\n    this.messaging = messaging;\n    this.messageExchangeTimeout = messageExchangeTimeout;\n    this.id = id;\n    this.type = type;\n    this.displayMetadata = displayMetadata;\n\n    //bind all functions to allow destructuring\n    this.broadcast = this.broadcast.bind(this);\n    this.getCurrentContext = this.getCurrentContext.bind(this);\n    this.addContextListener = this.addContextListener.bind(this);\n  }\n\n  async broadcast(context: Context): Promise<void> {\n    const request: BroadcastRequest = {\n      meta: this.messaging.createMeta(),\n      payload: {\n        channelId: this.id,\n        context,\n      },\n      type: 'broadcastRequest',\n    };\n    await this.messaging.exchange<BroadcastResponse>(request, 'broadcastResponse', this.messageExchangeTimeout);\n  }\n\n  async getCurrentContext(contextType?: string | undefined): Promise<Context | null> {\n    // first, ensure channel state is up-to-date\n    const request: GetCurrentContextRequest = {\n      meta: this.messaging.createMeta(),\n      payload: {\n        channelId: this.id,\n        contextType: contextType ?? null,\n      },\n      type: 'getCurrentContextRequest',\n    };\n    const response = await this.messaging.exchange<GetCurrentContextResponse>(\n      request,\n      'getCurrentContextResponse',\n      this.messageExchangeTimeout\n    );\n\n    return response.payload.context ?? null;\n  }\n\n  async addContextListener(\n    contextTypeOrHandler: string | null | ContextHandler,\n    handler?: ContextHandler\n  ): Promise<Listener> {\n    let theContextType: string | null;\n    let theHandler: ContextHandler;\n\n    if (contextTypeOrHandler == null && typeof handler === 'function') {\n      theContextType = null;\n      theHandler = handler;\n    } else if (typeof contextTypeOrHandler === 'string' && typeof handler === 'function') {\n      theContextType = contextTypeOrHandler;\n      theHandler = handler;\n    } else if (typeof contextTypeOrHandler === 'function') {\n      // deprecated one-arg version\n      theContextType = null;\n      theHandler = contextTypeOrHandler as ContextHandler;\n    } else {\n      //invalid call\n      // TODO: Replace with Standardized error when #1490 is resolved\n      throw new Error('Invalid arguments passed to addContextListener!');\n    }\n\n    return await this.addContextListenerInner(theContextType, theHandler);\n  }\n\n  async addContextListenerInner(contextType: string | null, theHandler: ContextHandler): Promise<Listener> {\n    const listener = new DefaultContextListener(\n      this.messaging,\n      this.messageExchangeTimeout,\n      this.id,\n      contextType,\n      theHandler\n    );\n    await listener.register();\n    return listener;\n  }\n\n  async clearContext(contextType?: string): Promise<void> {\n    // first, ensure channel state is up-to-date\n    const request: ClearContextRequest = {\n      meta: this.messaging.createMeta(),\n      payload: {\n        channelId: this.id,\n        contextType: contextType ?? null,\n      },\n      type: 'clearContextRequest',\n    };\n    await this.messaging.exchange<ClearContextResponse>(request, 'clearContextResponse', this.messageExchangeTimeout);\n  }\n\n  async addEventListener(type: string | null, handler: EventHandler): Promise<Listener> {\n    let listener: RegisterableListener;\n    switch (type) {\n      case 'contextCleared':\n        listener = new EventListener(this.messaging, 'contextCleared', handler);\n        break;\n      default:\n        throw new Error('Unsupported event type: ' + type);\n    }\n    await listener.register();\n    return listener;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/channels/DefaultChannelSupport.ts",
    "content": "import {\n  Channel,\n  Connectable,\n  ContextHandler,\n  Listener,\n  PrivateChannel,\n  ChannelSelector,\n  EventHandler,\n  ChannelError,\n  ApiEvent,\n  FDC3ChannelChangedEvent,\n  FDC3EventTypes,\n} from '@finos/fdc3-standard';\nimport { Messaging } from '../Messaging.js';\nimport { ChannelSupport } from './ChannelSupport.js';\nimport { DefaultPrivateChannel } from './DefaultPrivateChannel.js';\nimport { DefaultChannel } from './DefaultChannel.js';\nimport { DefaultContextListener } from '../listeners/DefaultContextListener.js';\nimport { UserChannelContextListener } from '../listeners/UserChannelContextListener.js';\nimport { DesktopAgentEventListener } from '../listeners/DesktopAgentEventListener.js';\nimport {\n  GetCurrentChannelResponse,\n  GetCurrentChannelRequest,\n  GetUserChannelsResponse,\n  GetUserChannelsRequest,\n  GetOrCreateChannelResponse,\n  GetOrCreateChannelRequest,\n  CreatePrivateChannelResponse,\n  CreatePrivateChannelRequest,\n  LeaveCurrentChannelResponse,\n  LeaveCurrentChannelRequest,\n  JoinUserChannelResponse,\n  JoinUserChannelRequest,\n  BroadcastEvent,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { throwIfUndefined } from '../util/throwIfUndefined.js';\nimport { Logger } from '../util/Logger.js';\n\nexport class DefaultChannelSupport implements ChannelSupport, Connectable {\n  readonly messaging: Messaging;\n  readonly channelSelector: ChannelSelector;\n  readonly messageExchangeTimeout: number;\n  protected userChannels: Channel[] | null = null;\n  protected userChannelListeners: UserChannelContextListener[] = [];\n  private currentChannel: Channel | null = null;\n\n  constructor(messaging: Messaging, channelSelector: ChannelSelector, messageExchangeTimeout: number) {\n    this.messaging = messaging;\n    this.channelSelector = channelSelector;\n    this.messageExchangeTimeout = messageExchangeTimeout;\n    this.channelSelector.setChannelChangeCallback((channelId: string | null) => {\n      Logger.debug('Channel selector reports channel changed: ', channelId);\n      if (channelId == null) {\n        this.leaveUserChannel();\n      } else {\n        this.joinUserChannel(channelId);\n      }\n    });\n  }\n\n  async connect(): Promise<void> {\n    //retrieve the current user channel in case the Desktop Agent started us on a channel\n    this.currentChannel = await this.getUserChannel();\n\n    //register for channelChangedEvents to track any DesktopAgent managed user channel changes\n    await this.addEventListener(async (e: ApiEvent) => {\n      const cce = e as FDC3ChannelChangedEvent;\n      const newChannelId = cce.details.currentChannelId;\n      Logger.debug('Desktop Agent reports channel changed: ', newChannelId);\n\n      let theChannel: Channel | null = null;\n\n      // if theres a newChannelId, retrieve details of the channel\n      if (newChannelId != null) {\n        theChannel = (await this.getUserChannels()).find(uc => uc.id == newChannelId) ?? null;\n        if (!theChannel) {\n          // Channel not found - query user channels in case they have changed for some reason\n          Logger.debug('Unknown user channel, querying Desktop Agent for updated user channels: ', newChannelId);\n          await this.getUserChannels();\n          theChannel = (await this.getUserChannels()).find(uc => uc.id == newChannelId) ?? null;\n          if (!theChannel) {\n            Logger.warn(\n              'Received user channel update with unknown user channel (user channel listeners will not work): ',\n              newChannelId\n            );\n          }\n        }\n      }\n\n      this.currentChannel = theChannel;\n      this.channelSelector.updateChannel(theChannel?.id ?? null, await this.getUserChannels());\n    }, 'userChannelChanged');\n  }\n\n  async disconnect(): Promise<void> {\n    // no-op\n  }\n\n  async addEventListener(handler: EventHandler, type: FDC3EventTypes | null): Promise<Listener> {\n    const listener = new DesktopAgentEventListener(this.messaging, this.messageExchangeTimeout, type, handler);\n    await listener.register();\n    return listener;\n  }\n\n  async getUserChannel(): Promise<Channel | null> {\n    if (this.currentChannel) {\n      //if the current channel is know,, return it as this variable is maintained by a channelChangedEvent listener\n      return this.currentChannel;\n    } else {\n      const request: GetCurrentChannelRequest = {\n        meta: this.messaging.createMeta(),\n        type: 'getCurrentChannelRequest',\n        payload: {},\n      };\n      const response = await this.messaging.exchange<GetCurrentChannelResponse>(\n        request,\n        'getCurrentChannelResponse',\n        this.messageExchangeTimeout\n      );\n\n      throwIfUndefined(\n        response.payload.channel,\n        'Invalid response from Desktop Agent to getCurrentChannel (channel should be explicitly null if no channel is set)!',\n        response,\n        ChannelError.NoChannelFound\n      );\n\n      //handle successful responses - errors will already have been thrown by exchange above\n      /* istanbul ignore else */\n      if (response.payload.channel) {\n        return new DefaultChannel(\n          this.messaging,\n          this.messageExchangeTimeout,\n          response.payload.channel.id,\n          'user',\n          response.payload.channel.displayMetadata\n        );\n      } else if (response.payload.channel === null) {\n        //this is a valid response if no channel is set\n        return null;\n      } else {\n        //Should not reach here as we will throw in exchange or throwIfNotFound\n        return null;\n      }\n    }\n  }\n\n  async getUserChannels(): Promise<Channel[]> {\n    //If the user channels are known, return them as they are not expected to change\n    if (this.userChannels) {\n      return this.userChannels;\n    } else {\n      const request: GetUserChannelsRequest = {\n        meta: this.messaging.createMeta(),\n        type: 'getUserChannelsRequest',\n        payload: {},\n      };\n      const response = await this.messaging.exchange<GetUserChannelsResponse>(\n        request,\n        'getUserChannelsResponse',\n        this.messageExchangeTimeout\n      );\n\n      //handle successful responses\n      const channels = response.payload.userChannels!;\n      this.userChannels = channels.map(\n        c => new DefaultChannel(this.messaging, this.messageExchangeTimeout, c.id, 'user', c.displayMetadata)\n      );\n      return this.userChannels;\n    }\n  }\n\n  async getOrCreate(id: string): Promise<Channel> {\n    const request: GetOrCreateChannelRequest = {\n      meta: this.messaging.createMeta(),\n      type: 'getOrCreateChannelRequest',\n      payload: {\n        channelId: id,\n      },\n    };\n    const response = await this.messaging.exchange<GetOrCreateChannelResponse>(\n      request,\n      'getOrCreateChannelResponse',\n      this.messageExchangeTimeout\n    );\n\n    throwIfUndefined(\n      response.payload.channel,\n      'Invalid response from Desktop Agent to getOrCreate!',\n      response,\n      ChannelError.CreationFailed\n    );\n\n    const out = new DefaultChannel(\n      this.messaging,\n      this.messageExchangeTimeout,\n      id,\n      'app',\n      response.payload.channel!.displayMetadata\n    );\n    return out;\n  }\n\n  async createPrivateChannel(): Promise<PrivateChannel> {\n    const request: CreatePrivateChannelRequest = {\n      meta: this.messaging.createMeta(),\n      type: 'createPrivateChannelRequest',\n      payload: {},\n    };\n    const response = await this.messaging.exchange<CreatePrivateChannelResponse>(\n      request,\n      'createPrivateChannelResponse',\n      this.messageExchangeTimeout\n    );\n\n    throwIfUndefined(\n      response.payload.privateChannel,\n      'Invalid response from Desktop Agent to createPrivateChannel!',\n      response,\n      ChannelError.CreationFailed\n    );\n\n    return new DefaultPrivateChannel(this.messaging, this.messageExchangeTimeout, response.payload.privateChannel!.id);\n  }\n\n  async leaveUserChannel(): Promise<void> {\n    const request: LeaveCurrentChannelRequest = {\n      meta: this.messaging.createMeta(),\n      type: 'leaveCurrentChannelRequest',\n      payload: {},\n    };\n    await this.messaging.exchange<LeaveCurrentChannelResponse>(\n      request,\n      'leaveCurrentChannelResponse',\n      this.messageExchangeTimeout\n    );\n    this.currentChannel = null;\n    this.channelSelector.updateChannel(null, await this.getUserChannels());\n  }\n\n  async joinUserChannel(id: string) {\n    const request: JoinUserChannelRequest = {\n      meta: this.messaging.createMeta(),\n      type: 'joinUserChannelRequest',\n      payload: {\n        channelId: id,\n      },\n    };\n    await this.messaging.exchange<JoinUserChannelResponse>(\n      request,\n      'joinUserChannelResponse',\n      this.messageExchangeTimeout\n    );\n\n    const userChannels = await this.getUserChannels();\n    this.currentChannel = userChannels.find(c => c.id == id) ?? null;\n    if (this.currentChannel == null) {\n      throw new Error(ChannelError.NoChannelFound);\n    }\n    this.channelSelector.updateChannel(id, userChannels);\n    for (const l of this.userChannelListeners) {\n      await l.changeChannel();\n    }\n  }\n\n  async addContextListener(handler: ContextHandler, type: string | null): Promise<Listener> {\n    /**\n     *  Utility class used to wrap the DefaultContextListener to match the internal channel id\n     *  and ensure it gets removed when its unsubscribe function is called.\n     */\n    class UnsubscribingDefaultContextListener extends DefaultContextListener implements UserChannelContextListener {\n      container: DefaultChannelSupport;\n\n      constructor(\n        container: DefaultChannelSupport,\n        messaging: Messaging,\n        messageExchangeTimeout: number,\n        contextType: string | null,\n        handler: ContextHandler,\n        messageType: string = 'broadcastEvent'\n      ) {\n        super(messaging, messageExchangeTimeout, null, contextType, handler, messageType);\n        this.container = container;\n      }\n\n      async unsubscribe(): Promise<void> {\n        super.unsubscribe();\n        this.container.userChannelListeners = this.container.userChannelListeners.filter(l => l != this);\n      }\n\n      async register(): Promise<void> {\n        await super.register();\n        await this.changeChannel();\n      }\n\n      async changeChannel(): Promise<void> {\n        if (this.container.currentChannel != null) {\n          const context = await this.container.currentChannel?.getCurrentContext(this.contextType ?? undefined);\n          if (context) {\n            this.handler(context);\n          }\n        }\n      }\n\n      onAMatchingChannel(m: BroadcastEvent): boolean {\n        return this.container.currentChannel != null && m.payload.channelId == this.container.currentChannel.id;\n      }\n\n      openBroadcastEvent(m: BroadcastEvent): boolean {\n        return m.payload.channelId == null;\n      }\n\n      filter(m: BroadcastEvent): boolean {\n        return (\n          m.type == this.messageType &&\n          (this.onAMatchingChannel(m) || this.openBroadcastEvent(m)) &&\n          (m.payload.context?.type == this.contextType || this.contextType == null)\n        );\n      }\n    }\n\n    const listener = new UnsubscribingDefaultContextListener(\n      this,\n      this.messaging,\n      this.messageExchangeTimeout,\n      type,\n      handler\n    );\n    this.userChannelListeners.push(listener);\n    await listener.register();\n    return listener;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/channels/DefaultPrivateChannel.ts",
    "content": "import {\n  ApiEvent,\n  ContextHandler,\n  EventHandler,\n  Listener,\n  PrivateChannel,\n  PrivateChannelEventTypes,\n} from '@finos/fdc3-standard';\nimport { DefaultChannel } from './DefaultChannel.js';\nimport { Messaging } from '../Messaging.js';\nimport {\n  PrivateChannelNullEventListener,\n  PrivateChannelAddContextEventListener,\n  PrivateChannelDisconnectEventListener,\n  PrivateChannelUnsubscribeEventListener,\n} from '../listeners/PrivateChannelEventListener.js';\nimport { DefaultContextListener } from '../listeners/DefaultContextListener.js';\nimport { RegisterableListener } from '../listeners/RegisterableListener.js';\nimport {\n  PrivateChannelDisconnectRequest,\n  PrivateChannelDisconnectResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class DefaultPrivateChannel extends DefaultChannel implements PrivateChannel {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, id: string) {\n    super(messaging, messageExchangeTimeout, id, 'private');\n\n    //bind all functions to allow destructuring\n    this.addContextListener = this.addContextListener.bind(this);\n    this.addEventListener = this.addEventListener.bind(this);\n    this.disconnect = this.disconnect.bind(this);\n  }\n\n  async addEventListener(type: PrivateChannelEventTypes | null, handler: EventHandler): Promise<Listener> {\n    let a: RegisterableListener;\n    switch (type) {\n      case 'addContextListener':\n        a = new PrivateChannelAddContextEventListener(this.messaging, this.messageExchangeTimeout, this.id, handler);\n        break;\n      case 'unsubscribe':\n        a = new PrivateChannelUnsubscribeEventListener(this.messaging, this.messageExchangeTimeout, this.id, handler);\n        break;\n      case 'disconnect':\n        a = new PrivateChannelDisconnectEventListener(this.messaging, this.messageExchangeTimeout, this.id, handler);\n        break;\n      case null:\n        a = new PrivateChannelNullEventListener(this.messaging, this.messageExchangeTimeout, this.id, handler);\n        break;\n      default:\n        throw new Error('Unsupported event type: ' + type);\n    }\n    await a.register();\n    return a;\n  }\n\n  //implementations of the deprecated listener functions\n  onAddContextListener(handler: (contextType?: string) => void): Listener {\n    //Adapt handler type for differences between addEventListener and onAddContextListener handler types\n    const adaptorHandler: EventHandler = (event: ApiEvent) => {\n      handler(event.details.contextType ?? undefined);\n    };\n    const l = new PrivateChannelAddContextEventListener(\n      this.messaging,\n      this.messageExchangeTimeout,\n      this.id,\n      adaptorHandler\n    );\n    l.register();\n    return l;\n  }\n\n  onUnsubscribe(handler: (contextType?: string) => void): Listener {\n    //Adapt handler type for differences between addEventListener and onUnsubscribeListener handler types\n    const adaptorHandler: EventHandler = (event: ApiEvent) => {\n      handler(event.details.contextType ?? undefined);\n    };\n    const l = new PrivateChannelUnsubscribeEventListener(\n      this.messaging,\n      this.messageExchangeTimeout,\n      this.id,\n      adaptorHandler\n    );\n    l.register();\n    return l;\n  }\n\n  onDisconnect(handler: () => void): Listener {\n    //Adapt handler type for differences between addEventListener and onDisconnectListener handler types\n    const adaptorHandler: EventHandler = () => {\n      handler();\n    };\n    const l = new PrivateChannelDisconnectEventListener(\n      this.messaging,\n      this.messageExchangeTimeout,\n      this.id,\n      adaptorHandler\n    );\n    l.register();\n    return l;\n  }\n\n  async disconnect(): Promise<void> {\n    const msg: PrivateChannelDisconnectRequest = {\n      meta: this.messaging.createMeta(),\n      payload: {\n        channelId: this.id,\n      },\n      type: 'privateChannelDisconnectRequest',\n    };\n    await this.messaging.exchange<PrivateChannelDisconnectResponse>(\n      msg,\n      'privateChannelDisconnectResponse',\n      this.messageExchangeTimeout\n    );\n  }\n\n  async addContextListenerInner(contextType: string | null, theHandler: ContextHandler): Promise<Listener> {\n    const listener = new DefaultContextListener(\n      this.messaging,\n      this.messageExchangeTimeout,\n      this.id,\n      contextType,\n      theHandler\n    );\n    await listener.register();\n    return listener;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/heartbeat/DefaultHeartbeatSupport.ts",
    "content": "import { HeartbeatListener } from '../listeners/HeartbeatListener.js';\nimport { Messaging } from '../Messaging.js';\nimport { HeartbeatSupport } from './HeartbeatSupport.js';\n\n/**\n * Handles disconnection and heartbeats for the proxy.\n */\nexport class DefaultHeartbeatSupport implements HeartbeatSupport {\n  readonly messaging: Messaging;\n  private heartbeatListener: HeartbeatListener | null = null;\n\n  constructor(messaging: Messaging) {\n    this.messaging = messaging;\n  }\n\n  async connect(): Promise<void> {\n    this.heartbeatListener = new HeartbeatListener(this.messaging);\n    this.heartbeatListener.register();\n  }\n\n  async disconnect(): Promise<void> {\n    await this.heartbeatListener?.unsubscribe();\n    return this.messaging.disconnect();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/heartbeat/HeartbeatSupport.ts",
    "content": "import { Connectable } from '@finos/fdc3-standard';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface HeartbeatSupport extends Connectable { }\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/index.ts",
    "content": "import { DesktopAgentProxy } from './DesktopAgentProxy.js';\nimport { Messaging } from './Messaging.js';\nimport { AbstractMessaging } from './messaging/AbstractMessaging.js';\nimport { DefaultChannel } from './channels/DefaultChannel.js';\nimport { ChannelSupport } from './channels/ChannelSupport.js';\nimport { DefaultIntentSupport } from './intents/DefaultIntentSupport.js';\nimport { DefaultChannelSupport } from './channels/DefaultChannelSupport.js';\nimport { IntentSupport } from './intents/IntentSupport.js';\nimport { RegisterableListener } from './listeners/RegisterableListener.js';\nimport { DefaultAppSupport } from './apps/DefaultAppSupport.js';\nimport { AppSupport } from './apps/AppSupport.js';\nimport { DefaultHeartbeatSupport } from './heartbeat/DefaultHeartbeatSupport.js';\nimport { Connectable } from '@finos/fdc3-standard';\nimport { AbstractFDC3Logger } from './util/AbstractFDC3Logger.js';\n\nexport {\n  type Messaging,\n  AbstractMessaging,\n  DesktopAgentProxy,\n  DefaultChannel,\n  type AppSupport,\n  type IntentSupport,\n  type ChannelSupport,\n  DefaultAppSupport,\n  DefaultChannelSupport,\n  DefaultIntentSupport,\n  DefaultHeartbeatSupport,\n  RegisterableListener,\n  Connectable,\n  AbstractFDC3Logger,\n};\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/intents/DefaultIntentResolution.ts",
    "content": "import { AppIdentifier, IntentResolution, IntentResult } from '@finos/fdc3-standard';\nimport { Messaging } from '../Messaging.js';\n\nexport class DefaultIntentResolution implements IntentResolution {\n  readonly messaging: Messaging;\n  readonly source: AppIdentifier;\n  readonly intent: string;\n  readonly result: Promise<IntentResult>;\n\n  constructor(messaging: Messaging, result: Promise<IntentResult>, source: AppIdentifier, intent: string) {\n    this.messaging = messaging;\n    this.result = result;\n    this.source = source;\n    this.intent = intent;\n\n    //bind all functions to allow destructuring\n    this.getResult = this.getResult.bind(this);\n  }\n\n  getResult(): Promise<IntentResult> {\n    return this.result;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/intents/DefaultIntentSupport.ts",
    "content": "import {\n  AppIntent,\n  AppIdentifier,\n  IntentResolution,\n  IntentHandler,\n  Listener,\n  ResolveError,\n  IntentResult,\n  IntentResolver,\n  IntentResolutionChoice,\n} from '@finos/fdc3-standard';\nimport { IntentSupport } from './IntentSupport.js';\nimport { Messaging } from '../Messaging.js';\nimport { DefaultIntentResolution } from './DefaultIntentResolution.js';\nimport { DefaultIntentListener } from '../listeners/DefaultIntentListener.js';\nimport { DefaultChannel } from '../channels/DefaultChannel.js';\nimport { DefaultPrivateChannel } from '../channels/DefaultPrivateChannel.js';\nimport { Context } from '@finos/fdc3-context';\nimport {\n  FindIntentRequest,\n  FindIntentResponse,\n  FindIntentsByContextRequest,\n  FindIntentsByContextResponse,\n  RaiseIntentForContextRequest,\n  RaiseIntentForContextResponse,\n  RaiseIntentRequest,\n  RaiseIntentResponse,\n  RaiseIntentResultResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { throwIfUndefined } from '../util/throwIfUndefined.js';\n\nconst convertIntentResult = async (\n  { payload }: RaiseIntentResultResponse,\n  messaging: Messaging,\n  messageExchangeTimeout: number\n): Promise<IntentResult> => {\n  const result = payload.intentResult;\n  if (result?.channel) {\n    const { channel } = result;\n    switch (channel.type) {\n      case 'private': {\n        return new DefaultPrivateChannel(messaging, messageExchangeTimeout, channel.id);\n      }\n      case 'app':\n      case 'user':\n      default: {\n        return new DefaultChannel(messaging, messageExchangeTimeout, channel.id, channel.type, channel.displayMetadata);\n      }\n    }\n  } else if (result?.context) {\n    return result.context;\n  } else {\n    return;\n  }\n};\n\nexport class DefaultIntentSupport implements IntentSupport {\n  readonly messaging: Messaging;\n  readonly intentResolver: IntentResolver;\n  readonly messageExchangeTimeout: number;\n  readonly appLaunchTimeout: number;\n\n  constructor(\n    messaging: Messaging,\n    intentResolver: IntentResolver,\n    messageExchangeTimeout: number,\n    appLaunchTimeout: number\n  ) {\n    this.messaging = messaging;\n    this.intentResolver = intentResolver;\n    this.messageExchangeTimeout = messageExchangeTimeout;\n    this.appLaunchTimeout = appLaunchTimeout;\n  }\n\n  async findIntent(intent: string, context: Context, resultType: string | undefined): Promise<AppIntent> {\n    const request: FindIntentRequest = {\n      type: 'findIntentRequest',\n      payload: {\n        intent,\n        context,\n        resultType,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const result = await this.messaging.exchange<FindIntentResponse>(\n      request,\n      'findIntentResponse',\n      this.messageExchangeTimeout\n    );\n    const appIntent = result.payload.appIntent!;\n    if (appIntent.apps.length == 0) {\n      throw new Error(ResolveError.NoAppsFound);\n    } else {\n      return {\n        intent: appIntent.intent,\n        apps: appIntent.apps,\n      };\n    }\n  }\n\n  async findIntentsByContext(context: Context): Promise<AppIntent[]> {\n    const request: FindIntentsByContextRequest = {\n      type: 'findIntentsByContextRequest',\n      payload: {\n        context,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const result: FindIntentsByContextResponse = await this.messaging.exchange(\n      request,\n      'findIntentsByContextResponse',\n      this.messageExchangeTimeout\n    );\n    const appIntents = result.payload.appIntents;\n    if (!appIntents || appIntents.length == 0) {\n      throw new Error(ResolveError.NoAppsFound);\n    } else {\n      return appIntents;\n    }\n  }\n\n  private async createResultPromise(request: RaiseIntentRequest | RaiseIntentForContextRequest): Promise<IntentResult> {\n    const rp = await this.messaging.waitFor<RaiseIntentResultResponse>(\n      m => m.type == 'raiseIntentResultResponse' && m.meta.requestUuid == request.meta.requestUuid\n    );\n\n    const ir = await convertIntentResult(rp, this.messaging, this.messageExchangeTimeout);\n    return ir;\n  }\n\n  async raiseIntent(intent: string, context: Context, app: AppIdentifier): Promise<IntentResolution> {\n    const meta = this.messaging.createMeta();\n    const request: RaiseIntentRequest = {\n      type: 'raiseIntentRequest',\n      payload: {\n        intent,\n        context,\n        app: app,\n      },\n      meta: meta,\n    };\n\n    const resultPromise = this.createResultPromise(request);\n    const response = await this.messaging.exchange<RaiseIntentResponse>(\n      request,\n      'raiseIntentResponse',\n      this.appLaunchTimeout\n    );\n\n    throwIfUndefined(\n      response.payload.appIntent ?? response.payload.intentResolution,\n      'Invalid response from Desktop Agent to raiseIntent, either payload.appIntent or payload.intentResolution must be set!',\n      response,\n      ResolveError.NoAppsFound\n    );\n\n    if (response.payload.appIntent) {\n      // Needs further resolution, we need to invoke the resolver\n      const result: IntentResolutionChoice | void = await this.intentResolver.chooseIntent(\n        [response.payload.appIntent],\n        context\n      );\n      if (result) {\n        return this.raiseIntent(intent, context, result.appId);\n      } else {\n        throw new Error(ResolveError.UserCancelled);\n      }\n    } else {\n      // Was resolved\n      const details = response.payload.intentResolution!;\n      return new DefaultIntentResolution(this.messaging, resultPromise, details.source, details.intent);\n    }\n  }\n\n  async raiseIntentForContext(context: Context, app?: AppIdentifier | undefined): Promise<IntentResolution> {\n    const request: RaiseIntentForContextRequest = {\n      type: 'raiseIntentForContextRequest',\n      payload: {\n        context,\n        app: app,\n      },\n      meta: this.messaging.createMeta(),\n    };\n\n    const resultPromise = this.createResultPromise(request);\n    const response = await this.messaging.exchange<RaiseIntentForContextResponse>(\n      request,\n      'raiseIntentForContextResponse',\n      this.appLaunchTimeout\n    );\n\n    throwIfUndefined(\n      response.payload.appIntents ?? response.payload.intentResolution,\n      'Invalid response from Desktop Agent to raiseIntentForContext, either payload.appIntents or payload.intentResolution must be set!',\n      response,\n      ResolveError.NoAppsFound\n    );\n\n    if (response.payload.appIntents) {\n      // Needs further resolution, we need to invoke the resolver\n      const result: IntentResolutionChoice | void = await this.intentResolver.chooseIntent(\n        response.payload.appIntents,\n        context\n      );\n      if (result) {\n        return this.raiseIntent(result.intent, context, result.appId);\n      } else {\n        throw new Error(ResolveError.UserCancelled);\n      }\n    } else {\n      // Was resolved\n      const details = response.payload.intentResolution!;\n      return new DefaultIntentResolution(this.messaging, resultPromise, details.source, details.intent);\n    }\n  }\n\n  async addIntentListener(intent: string, handler: IntentHandler): Promise<Listener> {\n    const out = new DefaultIntentListener(this.messaging, intent, handler, this.messageExchangeTimeout);\n    await out.register();\n    return out;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/intents/IntentSupport.ts",
    "content": "import { AppIdentifier, AppIntent, IntentHandler, IntentResolution, Listener } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\n\nexport interface IntentSupport {\n  findIntent(intent: string, context: Context, resultType: string | undefined): Promise<AppIntent>;\n  findIntentsByContext(context: Context): Promise<AppIntent[]>;\n  raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/AbstractListener.ts",
    "content": "import {\n  AgentEventMessage,\n  AddContextListenerRequest,\n  AddIntentListenerRequest,\n  AddEventListenerRequest,\n  PrivateChannelAddEventListenerRequest,\n  AddIntentListenerResponse,\n  AddContextListenerResponse,\n  AddEventListenerResponse,\n  ContextListenerUnsubscribeRequest,\n  IntentListenerUnsubscribeRequest,\n  EventListenerUnsubscribeRequest,\n  PrivateChannelAddEventListenerResponse,\n  PrivateChannelUnsubscribeEventListenerRequest,\n  ContextListenerUnsubscribeResponse,\n  IntentListenerUnsubscribeResponse,\n  EventListenerUnsubscribeResponse,\n  PrivateChannelUnsubscribeEventListenerResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Messaging } from '../Messaging.js';\nimport { RegisterableListener } from './RegisterableListener.js';\nimport { throwIfUndefined } from '../util/throwIfUndefined.js';\nimport { ChannelError } from '@finos/fdc3-standard';\n\ntype SubscriptionRequest =\n  | AddContextListenerRequest\n  | AddIntentListenerRequest\n  | AddEventListenerRequest\n  | PrivateChannelAddEventListenerRequest;\ntype SubscriptionResponse =\n  | AddContextListenerResponse\n  | AddIntentListenerResponse\n  | AddEventListenerResponse\n  | PrivateChannelAddEventListenerResponse;\ntype UnsubscribeRequest =\n  | ContextListenerUnsubscribeRequest\n  | IntentListenerUnsubscribeRequest\n  | EventListenerUnsubscribeRequest\n  | PrivateChannelUnsubscribeEventListenerRequest;\ntype UnsubscribeResponse =\n  | ContextListenerUnsubscribeResponse\n  | IntentListenerUnsubscribeResponse\n  | EventListenerUnsubscribeResponse\n  | PrivateChannelUnsubscribeEventListenerResponse;\n\n/**\n * Common to all listeners - they need to be registered and unregistered with messaging and also\n * send notification messages when connected and disconnected\n */\nexport abstract class AbstractListener<X, Y extends SubscriptionRequest> implements RegisterableListener {\n  readonly messaging: Messaging;\n  readonly messageExchangeTimeout: number;\n  private readonly subscribeRequestType: Y['type'];\n  private readonly subscribeResponseType: SubscriptionResponse['type'];\n  private readonly unsubscribeRequestType: UnsubscribeRequest['type'];\n  private readonly unsubscribeResponseType: UnsubscribeResponse['type'];\n  private readonly subscriptionPayload: Y['payload'];\n  id: string | null = null;\n  readonly handler: X;\n\n  constructor(\n    messaging: Messaging,\n    messageExchangeTimeout: number,\n    subscriptionPayload: Y['payload'],\n    handler: X,\n    subscribeRequestType: Y['type'],\n    subscribeResponseType: SubscriptionResponse['type'],\n    unsubscribeRequestType: UnsubscribeRequest['type'],\n    unsubscribeResponseType: UnsubscribeResponse['type']\n  ) {\n    this.messaging = messaging;\n    this.messageExchangeTimeout = messageExchangeTimeout;\n    this.handler = handler;\n    this.subscriptionPayload = subscriptionPayload;\n    this.subscribeRequestType = subscribeRequestType;\n    this.subscribeResponseType = subscribeResponseType;\n    this.unsubscribeRequestType = unsubscribeRequestType;\n    this.unsubscribeResponseType = unsubscribeResponseType;\n  }\n\n  abstract filter(m: AgentEventMessage): boolean;\n\n  abstract action(m: AgentEventMessage): void;\n\n  async unsubscribe(): Promise<void> {\n    /* istanbul ignore else */\n    if (this.id) {\n      this.messaging.unregister(this.id);\n      const unsubscribeMessage: UnsubscribeRequest = {\n        meta: this.messaging.createMeta(),\n        payload: {\n          listenerUUID: this.id,\n        },\n        type: this.unsubscribeRequestType,\n      };\n      await this.messaging.exchange<UnsubscribeResponse>(\n        unsubscribeMessage,\n        this.unsubscribeResponseType,\n        this.messageExchangeTimeout\n      );\n      return;\n    } else {\n      //should never happen as we throw on creating a listener without an ID\n      throw new Error(\"This listener doesn't have an id and hence can't be removed!\");\n    }\n  }\n\n  async register(): Promise<void> {\n    const subscribeMessage: Y = {\n      meta: this.messaging.createMeta() as Y['meta'],\n      payload: this.subscriptionPayload as Y['payload'],\n      type: this.subscribeRequestType as Y['type'],\n    } as Y;\n\n    const response = await this.messaging.exchange<SubscriptionResponse>(\n      subscribeMessage,\n      this.subscribeResponseType,\n      this.messageExchangeTimeout\n    );\n    this.id = response?.payload?.listenerUUID ?? null;\n\n    //coalesce so that nullish values become undefined\n    throwIfUndefined(\n      this.id ?? undefined,\n      \"The Desktop Agent's response did not include a listenerUUID, which will mean this listener can't be removed!\",\n      response,\n      ChannelError.CreationFailed\n    );\n\n    this.messaging.register(this);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/DefaultContextListener.ts",
    "content": "import { AppIdentifier, ContextHandler } from '@finos/fdc3-standard';\nimport { Messaging } from '../Messaging.js';\nimport { AbstractListener } from './AbstractListener.js';\nimport { AddContextListenerRequest, BroadcastEvent } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { RegisterableListener } from './RegisterableListener.js';\n\nexport class DefaultContextListener\n  extends AbstractListener<ContextHandler, AddContextListenerRequest>\n  implements RegisterableListener\n{\n  private readonly channelId: string | null;\n  protected readonly messageType: string;\n  protected readonly contextType: string | null;\n\n  constructor(\n    messaging: Messaging,\n    messageExchangeTimeout: number,\n    channelId: string | null,\n    contextType: string | null,\n    handler: ContextHandler,\n    messageType: string = 'broadcastEvent'\n  ) {\n    super(\n      messaging,\n      messageExchangeTimeout,\n      { channelId, contextType },\n      handler,\n      'addContextListenerRequest',\n      'addContextListenerResponse',\n      'contextListenerUnsubscribeRequest',\n      'contextListenerUnsubscribeResponse'\n    );\n    this.channelId = channelId;\n    this.messageType = messageType;\n    this.contextType = contextType;\n  }\n\n  filter(m: BroadcastEvent): boolean {\n    return (\n      m.type == this.messageType &&\n      m.payload.channelId == this.channelId &&\n      (m.payload.context?.type == this.contextType || this.contextType == null)\n    );\n  }\n\n  action(m: BroadcastEvent): void {\n    this.handler(m.payload.context, {\n      source: m.payload.originatingApp as AppIdentifier,\n    });\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/DefaultIntentListener.ts",
    "content": "import { IntentHandler, IntentResult, AppIdentifier } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { Messaging } from '../Messaging.js';\nimport { AbstractListener } from './AbstractListener.js';\nimport {\n  AddIntentListenerRequest,\n  IntentEvent,\n  IntentResultRequest,\n  IntentResultResponse,\n  //RaiseIntentResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class DefaultIntentListener extends AbstractListener<IntentHandler, AddIntentListenerRequest> {\n  readonly intent: string;\n\n  constructor(messaging: Messaging, intent: string, action: IntentHandler, messageExchangeTimeout: number) {\n    super(\n      messaging,\n      messageExchangeTimeout,\n      { intent },\n      action,\n      'addIntentListenerRequest',\n      'addIntentListenerResponse',\n      'intentListenerUnsubscribeRequest',\n      'intentListenerUnsubscribeResponse'\n    );\n    this.intent = intent;\n  }\n\n  filter(m: IntentEvent): boolean {\n    return m.type == 'intentEvent' && m.payload.intent == this.intent;\n  }\n\n  action(m: IntentEvent): void {\n    const done = this.handler(m.payload.context, {\n      source: m.payload.originatingApp as AppIdentifier,\n    });\n\n    this.handleIntentResult(done, m);\n  }\n\n  private intentResultRequestMessage(ir: IntentResult, m: IntentEvent): IntentResultRequest {\n    const out: IntentResultRequest = {\n      type: 'intentResultRequest',\n      meta: {\n        requestUuid: m.meta.eventUuid,\n        timestamp: new Date(),\n      },\n      payload: {\n        intentResult: convertIntentResult(ir),\n        intentEventUuid: m.meta.eventUuid,\n        raiseIntentRequestUuid: m.payload.raiseIntentRequestUuid,\n      },\n    };\n\n    return out;\n  }\n\n  private handleIntentResult(done: Promise<IntentResult> | void, m: IntentEvent) {\n    if (done == null) {\n      // send an empty intent result response\n      return this.messaging.exchange<IntentResultResponse>(\n        this.intentResultRequestMessage(undefined, m),\n        'intentResultResponse',\n        this.messageExchangeTimeout\n      );\n    } else {\n      // respond after promise completes\n      return done.then(ir => {\n        return this.messaging.exchange<IntentResultResponse>(\n          this.intentResultRequestMessage(ir, m),\n          'intentResultResponse',\n          this.messageExchangeTimeout\n        );\n      });\n    }\n  }\n}\n\nfunction convertIntentResult(intentResult: IntentResult): IntentResultRequest['payload']['intentResult'] {\n  if (!intentResult) {\n    //consider any falsy result to be void...\n    return {}; // void result\n  }\n  switch (intentResult.type) {\n    case 'user':\n    case 'app':\n    case 'private':\n      // it's a channel\n      return {\n        channel: {\n          type: intentResult.type,\n          id: intentResult.id as string,\n          displayMetadata: intentResult.displayMetadata,\n        },\n      };\n    default:\n      // it's a context\n      return {\n        context: intentResult as Context,\n      };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/DesktopAgentEventListener.ts",
    "content": "import { EventHandler, FDC3ChannelChangedEvent, FDC3EventTypes } from '@finos/fdc3-standard';\nimport {\n  AddEventListenerRequest,\n  AddEventListenerRequestPayload,\n  AgentEventMessage,\n  ChannelChangedEvent,\n} from '@finos/fdc3-schema/generated/api/BrowserTypes.js';\nimport { Messaging } from '../Messaging.js';\nimport { AbstractListener } from './AbstractListener.js';\n\nfunction wrapHandler(handler: EventHandler): (msg: AgentEventMessage) => void {\n  return (m: AgentEventMessage) => {\n    //backwards compatibility, see issue #1585\n    if (m.type === 'channelChangedEvent' && m.payload.newChannelId) {\n      const restructured: FDC3ChannelChangedEvent = {\n        type: 'userChannelChanged',\n        details: {\n          currentChannelId: m.payload.newChannelId,\n        },\n      };\n\n      handler(restructured);\n    } else {\n      // currently unused but meeting issue #1585\n      handler({\n        type: m.type,\n        details: m.payload,\n      });\n    }\n  };\n}\n\nfunction getRequestPayload(type: FDC3EventTypes | null): AddEventListenerRequestPayload {\n  if (type == 'userChannelChanged') {\n    return {\n      type: 'USER_CHANNEL_CHANGED',\n    };\n  } else if (type == null) {\n    return {\n      type: null,\n    };\n  } else {\n    throw new Error('UnknownEventType');\n  }\n}\n\nfunction getEventType(type: FDC3EventTypes | null): ChannelChangedEvent['type'] | null {\n  if (type == 'userChannelChanged') {\n    return 'channelChangedEvent';\n  } else if (type == null) {\n    return null;\n  } else {\n    throw new Error('UnknownEventType');\n  }\n}\n\n/**\n * Listens to channel changed events (currently) from the desktop agent and forwards them to the provided handler.\n */\nexport class DesktopAgentEventListener extends AbstractListener<\n  (msg: AgentEventMessage) => void,\n  AddEventListenerRequest\n> {\n  type: string | null;\n\n  constructor(\n    messaging: Messaging,\n    messageExchangeTimeout: number,\n    type: FDC3EventTypes | null,\n    handler: EventHandler\n  ) {\n    super(\n      messaging,\n      messageExchangeTimeout,\n      getRequestPayload(type),\n      wrapHandler(handler),\n      'addEventListenerRequest',\n      'addEventListenerResponse',\n      'eventListenerUnsubscribeRequest',\n      'eventListenerUnsubscribeResponse'\n    );\n    this.type = getEventType(type);\n  }\n\n  action(m: AgentEventMessage): void {\n    this.handler(m);\n  }\n\n  filter(m: AgentEventMessage): boolean {\n    return m.type === this.type || this.type == null;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/EventListener.ts",
    "content": "import { ApiEvent, EventHandler } from '@finos/fdc3-standard';\nimport { Messaging } from '../Messaging.js';\nimport { RegisterableListener } from './RegisterableListener.js';\nimport { AgentEventMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class EventListener implements RegisterableListener {\n  readonly id: string;\n  readonly messaging: Messaging;\n  readonly type: string;\n  readonly handler: EventHandler;\n\n  constructor(messaging: Messaging, type: string, handler: EventHandler) {\n    this.id = type + '-' + messaging.createUUID();\n    this.messaging = messaging;\n    this.type = type;\n    this.handler = handler;\n  }\n\n  filter(m: AgentEventMessage): boolean {\n    return m.type === this.type;\n  }\n\n  action(m: AgentEventMessage): void {\n    if (m.type === this.type) {\n      this.handler({\n        type: this.type,\n        details: m.payload,\n      } as ApiEvent);\n    }\n  }\n\n  async register(): Promise<void> {\n    this.messaging.register(this);\n  }\n\n  async unsubscribe(): Promise<void> {\n    this.messaging.unregister(this.id);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/HeartbeatListener.ts",
    "content": "import {\n  AgentEventMessage,\n  HeartbeatAcknowledgementRequest,\n  HeartbeatEvent,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Messaging } from '../Messaging.js';\nimport { RegisterableListener } from './RegisterableListener.js';\nimport { Logger } from '../util/Logger.js';\n\nexport class HeartbeatListener implements RegisterableListener {\n  readonly id: string;\n  readonly messaging: Messaging;\n\n  constructor(messaging: Messaging) {\n    this.id = 'heartbeat-' + messaging.createUUID();\n    this.messaging = messaging;\n  }\n\n  filter(m: AgentEventMessage): boolean {\n    return m.type === 'heartbeatEvent';\n  }\n\n  action(_m: AgentEventMessage): void {\n    Logger.debug('Responding to heartbeat request', _m);\n    const request: HeartbeatAcknowledgementRequest = {\n      type: 'heartbeatAcknowledgementRequest',\n      meta: {\n        requestUuid: this.messaging.createUUID(),\n        timestamp: new Date(),\n      },\n      payload: {\n        heartbeatEventUuid: (_m as HeartbeatEvent).meta.eventUuid,\n      },\n    };\n    this.messaging.post(request);\n  }\n\n  async register(): Promise<void> {\n    this.messaging.register(this);\n  }\n\n  async unsubscribe(): Promise<void> {\n    this.messaging.unregister(this.id);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/PrivateChannelEventListener.ts",
    "content": "import { Messaging } from '../Messaging.js';\nimport { AbstractListener } from './AbstractListener.js';\nimport {\n  ApiEvent,\n  EventHandler,\n  PrivateChannelAddContextListenerEvent,\n  PrivateChannelDisconnectEvent,\n  PrivateChannelEvent,\n  PrivateChannelEventTypes,\n  PrivateChannelUnsubscribeEvent,\n} from '@finos/fdc3-standard';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { Logger } from '../util/Logger.js';\nconst {\n  isPrivateChannelOnAddContextListenerEvent,\n  isPrivateChannelOnDisconnectEvent,\n  isPrivateChannelOnUnsubscribeEvent,\n} = BrowserTypes;\ntype PrivateChannelAddEventListenerRequest = BrowserTypes.PrivateChannelAddEventListenerRequest;\ntype PrivateChannelOnAddContextListenerEvent = BrowserTypes.PrivateChannelOnAddContextListenerEvent;\ntype PrivateChannelOnDisconnectEvent = BrowserTypes.PrivateChannelOnDisconnectEvent;\ntype PrivateChannelOnUnsubscribeEvent = BrowserTypes.PrivateChannelOnUnsubscribeEvent;\n\ntype PrivateChannelEventMessages =\n  | PrivateChannelOnAddContextListenerEvent\n  | PrivateChannelOnUnsubscribeEvent\n  | PrivateChannelOnDisconnectEvent;\ntype PrivateChannelEventMessageTypes = PrivateChannelEventMessages['type'];\n\nabstract class AbstractPrivateChannelEventListener extends AbstractListener<\n  (msg: PrivateChannelEventMessages) => void,\n  PrivateChannelAddEventListenerRequest\n> {\n  readonly privateChannelId: string;\n  readonly eventMessageTypes: PrivateChannelEventMessageTypes[];\n\n  constructor(\n    messaging: Messaging,\n    messageExchangeTimeout: number,\n    privateChannelId: string,\n    eventMessageTypes: PrivateChannelEventMessageTypes[],\n    eventType: PrivateChannelEventTypes | null,\n    handler: (msg: PrivateChannelEventMessages) => void\n  ) {\n    super(\n      messaging,\n      messageExchangeTimeout,\n      { privateChannelId, listenerType: eventType },\n      handler,\n      'privateChannelAddEventListenerRequest',\n      'privateChannelAddEventListenerResponse',\n      'privateChannelUnsubscribeEventListenerRequest',\n      'privateChannelUnsubscribeEventListenerResponse'\n    );\n    this.privateChannelId = privateChannelId;\n    this.eventMessageTypes = eventMessageTypes;\n  }\n\n  filter(m: PrivateChannelEventMessages): boolean {\n    return this.eventMessageTypes.includes(m.type) && this.privateChannelId == m.payload.privateChannelId;\n  }\n\n  action(m: PrivateChannelEventMessages): void {\n    this.handler(m);\n  }\n}\n\nexport class PrivateChannelNullEventListener extends AbstractPrivateChannelEventListener {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, channelId: string, handler: EventHandler) {\n    const wrappedHandler = (msg: PrivateChannelEventMessages) => {\n      let type: PrivateChannelEventTypes;\n      let details:\n        | PrivateChannelAddContextListenerEvent['details']\n        | PrivateChannelUnsubscribeEvent['details']\n        | PrivateChannelDisconnectEvent['details'];\n      switch (msg.type) {\n        case 'privateChannelOnAddContextListenerEvent':\n          type = 'addContextListener';\n          details = { contextType: msg.payload.contextType };\n          break;\n        case 'privateChannelOnUnsubscribeEvent':\n          type = 'unsubscribe';\n          details = { contextType: msg.payload.contextType };\n          break;\n        case 'privateChannelOnDisconnectEvent':\n          type = 'disconnect';\n          details = null;\n          break;\n      }\n\n      const event: PrivateChannelEvent = {\n        type,\n        details,\n      };\n      handler(event);\n    };\n\n    super(\n      messaging,\n      messageExchangeTimeout,\n      channelId,\n      [\n        'privateChannelOnAddContextListenerEvent',\n        'privateChannelOnUnsubscribeEvent',\n        'privateChannelOnDisconnectEvent',\n      ],\n      'addContextListener',\n      wrappedHandler\n    );\n  }\n}\n\nexport class PrivateChannelDisconnectEventListener extends AbstractPrivateChannelEventListener {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, channelId: string, handler: EventHandler) {\n    const wrappedHandler = (msg: PrivateChannelEventMessages) => {\n      if (isPrivateChannelOnDisconnectEvent(msg)) {\n        const event: PrivateChannelDisconnectEvent = {\n          type: 'disconnect',\n          details: null,\n        };\n        handler(event);\n      } else {\n        Logger.error('PrivateChannelDisconnectEventListener was called for a different message type!', msg);\n      }\n    };\n\n    super(\n      messaging,\n      messageExchangeTimeout,\n      channelId,\n      ['privateChannelOnDisconnectEvent'],\n      'disconnect',\n      wrappedHandler\n    );\n  }\n}\n\nexport class PrivateChannelAddContextEventListener extends AbstractPrivateChannelEventListener {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, channelId: string, handler: EventHandler) {\n    const wrappedHandler = (msg: PrivateChannelEventMessages) => {\n      if (isPrivateChannelOnAddContextListenerEvent(msg)) {\n        const event: ApiEvent = {\n          type: 'addContextListener',\n          details: { contextType: msg.payload.contextType },\n        };\n        handler(event);\n      } else {\n        Logger.error('PrivateChannelAddContextEventListener was called for a different message type!', msg);\n      }\n    };\n    super(\n      messaging,\n      messageExchangeTimeout,\n      channelId,\n      ['privateChannelOnAddContextListenerEvent'],\n      'addContextListener',\n      wrappedHandler\n    );\n  }\n}\n\nexport class PrivateChannelUnsubscribeEventListener extends AbstractPrivateChannelEventListener {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, channelId: string, handler: EventHandler) {\n    const wrappedHandler = (msg: PrivateChannelEventMessages) => {\n      if (isPrivateChannelOnUnsubscribeEvent(msg)) {\n        const event: ApiEvent = {\n          type: 'unsubscribe',\n          details: { contextType: msg.payload.contextType },\n        };\n        handler(event);\n      } else {\n        Logger.error('PrivateChannelUnsubscribeEventListener was called for a different message type!', msg);\n      }\n    };\n    super(\n      messaging,\n      messageExchangeTimeout,\n      channelId,\n      ['privateChannelOnUnsubscribeEvent'],\n      'unsubscribe',\n      wrappedHandler\n    );\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/RegisterableListener.ts",
    "content": "import { AgentEventMessage, AgentResponseMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Listener } from '@finos/fdc3-standard';\n\n/**\n * Extends the basic concept of FDC3 listeners to include lifecycle methods.\n * All fdc3-agent-proxy listeners implement this interface and should be\n * initialized with the register() method before use.\n */\nexport interface RegisterableListener extends Listener {\n  id: string | null;\n  filter(m: AgentEventMessage | AgentResponseMessage): boolean;\n  action(m: AgentEventMessage | AgentResponseMessage): void;\n  /**\n   * Listeners need to be registered in order to set their IDs.\n   */\n  register(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/listeners/UserChannelContextListener.ts",
    "content": "import { Listener } from '@finos/fdc3-standard';\nimport { RegisterableListener } from './RegisterableListener.js';\n\n/**\n * This is a special version of a ContextListener created when the user calls the\n * fdc3.addContextListener method. In this scenario, the listener will respond to broadcasts\n * on whatever is the current user channel.\n */\nexport interface UserChannelContextListener extends Listener, RegisterableListener {\n  /**\n   * This method is called when the user channel changes.  The listener should then\n   * call it's handler with the latest piece of relevant channel state and start responding to\n   * events on the new channelId.\n   */\n  changeChannel(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/messaging/AbstractMessaging.ts",
    "content": "import { AgentError, AppIdentifier } from '@finos/fdc3-standard';\nimport { Messaging } from '../Messaging.js';\nimport { RegisterableListener } from '../listeners/RegisterableListener.js';\nimport {\n  AgentResponseMessage,\n  AppRequestMessage,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Logger } from '../util/Logger.js';\n\nexport abstract class AbstractMessaging implements Messaging {\n  private appIdentifier: AppIdentifier;\n\n  abstract createUUID(): string;\n  abstract post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void>;\n  abstract register(l: RegisterableListener): void;\n  abstract unregister(id: string): void;\n  abstract createMeta(): AppRequestMessage['meta'];\n\n  constructor(appIdentifier: AppIdentifier) {\n    this.appIdentifier = appIdentifier;\n  }\n\n  waitFor<X extends AgentResponseMessage>(\n    filter: (m: X) => boolean,\n    timeoutMs?: number,\n    timeoutErrorMessage?: string\n  ): Promise<X> {\n    const id = this.createUUID();\n    return new Promise<X>((resolve, reject) => {\n      let done = false;\n      let timeout: NodeJS.Timeout | null = null;\n      const l: RegisterableListener = {\n        id,\n        filter: filter,\n        action: m => {\n          Logger.debug('Received from DesktopAgent: ', m);\n          done = true;\n          this.unregister(id);\n          if (timeout) {\n            clearTimeout(timeout);\n          }\n          resolve(m as X);\n        },\n        register: async () => {\n          this.register(l);\n        },\n        unsubscribe: async () => {\n          this.unregister(id);\n        },\n      };\n\n      this.register(l);\n\n      if (timeoutMs) {\n        timeout = setTimeout(() => {\n          this.unregister(id);\n          if (!done) {\n            Logger.error(\n              `waitFor rejecting after ${timeoutMs}ms at ${new Date().toISOString()} with ${timeoutErrorMessage}`\n            );\n            reject(new Error(timeoutErrorMessage));\n          }\n        }, timeoutMs);\n      }\n    });\n  }\n\n  async exchange<X extends AgentResponseMessage>(\n    message: AppRequestMessage,\n    expectedTypeName: AgentResponseMessage['type'],\n    timeoutMs: number\n  ): Promise<X> {\n    const prom = this.waitFor<X>(\n      m => {\n        return m.type == expectedTypeName && m.meta.requestUuid == message.meta.requestUuid;\n      },\n      timeoutMs,\n      AgentError.ApiTimeout\n    );\n\n    Logger.debug('Sending to DesktopAgent: ', message);\n    this.post(message);\n    try {\n      const out: X = await prom;\n\n      if (out?.payload?.error) {\n        throw new Error(out.payload.error);\n      } else {\n        return out;\n      }\n    } catch (error) {\n      if ((error as Error).message == AgentError.ApiTimeout) {\n        Logger.error(`Timed-out while waiting for ${expectedTypeName} with requestUuid ${message.meta.requestUuid}`);\n      }\n      throw error;\n    }\n  }\n\n  getAppIdentifier(): AppIdentifier {\n    return this.appIdentifier;\n  }\n\n  abstract disconnect(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/util/AbstractFDC3Logger.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { LogLevel } from '@finos/fdc3-standard';\n\n//check if color is supported in (node) console;\nlet noColor = true;\n//else only occurs in a browser and can't be tested in node\n/* istanbul ignore if */\nif (typeof process !== 'undefined') {\n  const argv = process.argv || /* istanbul ignore next */ [];\n  const env = process.env || /* istanbul ignore next */ {};\n  noColor =\n    (!!env.NO_COLOR || argv.includes('--no-color')) &&\n    !(\n      !!env.FORCE_COLOR ||\n      argv.includes('--color') ||\n      process.platform === 'win32' /* istanbul ignore next */ ||\n      ((process.stdout || {}).isTTY && env.TERM !== 'dumb') ||\n      /* istanbul ignore next */ !!env.CI\n    );\n}\n\ntype ColorFn = (aString: string) => string;\n\nexport abstract class AbstractFDC3Logger {\n  /** This should be overridden by sub-classes to set the prefix applied\n   * to log messages. */\n  /* istanbul ignore next */ static get prefix(): string {\n    return '';\n  }\n\n  //sub-classes should override this default log level\n  private static logLevel: LogLevel = LogLevel.DEBUG;\n\n  public static setLogLevel(level: LogLevel) {\n    if (level in LogLevel) {\n      this.logLevel = level;\n    } else {\n      /* istanbul ignore next */\n      this.error(\n        `Ignoring unrecognized LogLevel '${level}'! Current log level: '${this.logLevel} (${LogLevel[this.logLevel]})'`\n      );\n    }\n  }\n\n  protected static debugColor(value: string): string {\n    return noColor ? /* istanbul ignore next */ value : '\\x1b[30m\\x1b[2m' + value + '\\x1b[22m\\x1b[39m';\n  }\n  protected static logColor(value: string): string {\n    return noColor ? /* istanbul ignore next */ value : '\\x1b[32m\\x1b[2m' + value + '\\x1b[22m\\x1b[39m';\n  }\n  protected static warnColor(value: string): string {\n    return noColor ? /* istanbul ignore next */ value : '\\x1b[33m' + value + '\\x1b[39m';\n  }\n  protected static errorColor(value: string): string {\n    return noColor ? /* istanbul ignore next */ value : '\\x1b[31m' + value + '\\x1b[39m';\n  }\n\n  public static debug(...params: any[]) {\n    if (this.logLevel >= LogLevel.DEBUG) {\n      console.debug(...this.prefixAndColorize(this.prefix, params, this.debugColor));\n    }\n  }\n\n  public static log(...params: any[]) {\n    if (this.logLevel >= LogLevel.INFO) {\n      console.log(...this.prefixAndColorize(this.prefix, params, this.logColor));\n    }\n  }\n\n  public static warn(...params: any[]) {\n    if (this.logLevel >= LogLevel.WARN) {\n      console.warn(...this.prefixAndColorize(this.prefix, params, this.warnColor));\n    }\n  }\n\n  public static error(...params: any[]) {\n    if (this.logLevel >= LogLevel.ERROR) {\n      console.error(...this.prefixAndColorize(this.prefix, params, this.errorColor));\n    }\n  }\n\n  protected static prefixAndColorize = (prefix: string, params: any[], colorFn: ColorFn): string[] => {\n    const prefixed = [prefix, ...params];\n    return prefixed.map(value => {\n      if (typeof value === 'string') {\n        //just color strings\n        return colorFn(value);\n      } else if (value && value.stack && value.message) {\n        //probably an error\n        return colorFn(value.stack);\n      } else {\n        //something else... lets hope it stringifies\n        return colorFn(JSON.stringify(value, null, 2));\n      }\n    });\n  };\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/util/Logger.ts",
    "content": "import { LogLevel } from '@finos/fdc3-standard';\nimport { AbstractFDC3Logger } from './AbstractFDC3Logger.js';\n\n/**\n * Logging utility used by the DesktopAgentProxy, which defaults to\n * only printing WARN and ERROR level messages. The INFO level is used\n * to message exchanges with Desktop Agents. The DEBUG level is used\n * to log heartbeat messages from the DesktopAgent.\n */\nexport class Logger extends AbstractFDC3Logger {\n  static override get prefix(): string {\n    return 'FDC3 DesktopAgentProxy: ';\n  }\n\n  //set default log level - will not be picked up in test scope so ignored\n  /* istanbul ignore next */\n  logLevel: LogLevel = LogLevel.WARN;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/src/util/throwIfUndefined.ts",
    "content": "import { AgentEventMessage, AgentResponseMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { ChannelError, OpenError, ResolveError } from '@finos/fdc3-standard';\nimport { Logger } from './Logger.js';\n\nexport type ErrorMessages = ChannelError | OpenError | ResolveError;\n\n/** Utility function that logs and throws a specified error if a specified property does not exist.\n *  Used to lightly validate messages being processed primarily to catch errors in Desktop Agent\n *  implementations.\n */\nexport const throwIfUndefined = (\n  property: object | string | number | null | undefined,\n  absentMessage: string,\n  message: AgentResponseMessage | AgentEventMessage,\n  absentError: ErrorMessages\n): void => {\n  if (property === undefined) {\n    Logger.error(absentMessage, '\\nDACP message that resulted in the undefined property: ', message);\n    throw new Error(absentError);\n  }\n};\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/app-channels.feature",
    "content": "Feature: Channel Listeners Support\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    Given User Channels one, two and three\n    Given A Desktop Agent in \"api1\"\n    Given \"instrumentMessageOne\" is a BroadcastEvent message on channel \"channel-name\" with context \"fdc3.instrument\"\n    Given \"countryMessageOne\" is a BroadcastEvent message on channel \"channel-name\" with context \"fdc3.country\"\n    Given \"instrumentContext\" is a \"fdc3.instrument\" context\n    Given \"resultHandler\" pipes context to \"contexts\"\n\n  Scenario: Configuring two context listeners should mean they both pick up data\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n      | AAPL      | fdc3.instrument | Apple |\n    Then messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | channel-name      | {null}              | getOrCreateChannelRequest |\n      | channel-name      | fdc3.instrument     | addContextListenerRequest |\n      | channel-name      | fdc3.instrument     | addContextListenerRequest |\n\n  Scenario: Unsubscribing a context listener prevents it collecting data.\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I call \"{result}\" with \"unsubscribe\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is empty\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type                      |\n      | channel-name      | {null}              | getOrCreateChannelRequest         |\n      | channel-name      | fdc3.instrument     | addContextListenerRequest         |\n      | {null}            | {null}              | contextListenerUnsubscribeRequest |\n\n  Scenario: I can create a listener which listens for any context type\n        In this version we are using the deprecated 1-arg approach\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameter \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    And messaging receives \"{countryMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | type            | name   |\n      | fdc3.instrument | Apple  |\n      | fdc3.country    | Sweden |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | channel-name      | {null}              | getOrCreateChannelRequest |\n      | channel-name      | {null}              | addContextListenerRequest |\n\n  Scenario: I can create a listener which listens for any context type\n        In this version we are using the non-deprecated 2 args approach\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"{null}\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    And messaging receives \"{countryMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | type            | name   |\n      | fdc3.instrument | Apple  |\n      | fdc3.country    | Sweden |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | channel-name      | {null}              | getOrCreateChannelRequest |\n      | channel-name      | {null}              | addContextListenerRequest |\n\n  Scenario: Passing invalid arguments to an app channel's addContextListener fn throws an error\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    # Specific error message not tested as its not currently standardized\n    # TODO: Fix when #1490 is resolved\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"{true}\" and \"{resultHandler}\"\n    Then \"{result}\" is an error\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"{null}\" and \"{true}\"\n    Then \"{result}\" is an error\n\n  Scenario: Destructured channel methods - broadcast and addContextListener\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I destructure methods \"addContextListener\", \"broadcast\" from \"{channel1}\"\n    And I call destructured \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | channel-name      | {null}              | getOrCreateChannelRequest |\n      | channel-name      | fdc3.instrument     | addContextListenerRequest |\n\n  Scenario: Destructured getCurrentContext after broadcast\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I destructure methods \"broadcast\", \"getCurrentContext\" from \"{channel1}\"\n    And I call destructured \"broadcast\" with parameter \"{instrumentContext}\"\n    And I call destructured \"getCurrentContext\" with parameter \"fdc3.instrument\"\n    Then \"{result}\" is an object with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: Destructured listener receives filtered context\n    Given \"countryContext\" is a \"fdc3.country\" context\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I destructure methods \"addContextListener\", \"broadcast\" from \"{channel1}\"\n    And I call destructured \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: App channel context listener receives originating app metadata\n    Given \"resultHandler\" pipes context and metadata to \"contexts\" and \"metadatas\"\n    When I call \"{api1}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And \"{metadatas}\" is an array of objects with the following contents\n      | source.appId      | source.instanceId     |\n      | broadcasting-app   | broadcasting-instance |"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/app-metadata.feature",
    "content": "Feature: Desktop Agent Information\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And A Desktop Agent in \"api\"\n    And app \"chipShop/c1\"\n\n  Scenario: Getting App metadata\n    When I call \"{api}\" with \"getAppMetadata\" with parameter \"{c1}\"\n    Then \"{result}\" is an object with the following contents\n      | appId    | name          | description          |\n      | chipShop | Metadata Name | Metadata Description |\n    And messaging will have posts\n      | payload.app.appId | payload.app.instanceId | matches_type          |\n      | chipShop          | c1                     | getAppMetadataRequest |\n\n  Scenario: Getting own info\n    When I call \"{api}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | provider          |\n      |         2.0 | cucumber-provider |\n    And \"{result.appMetadata}\" is an object with the following contents\n      | appId        | instanceId        |\n      | cucumber-app | cucumber-instance |\n\n  Scenario: Getting instance information\n    When I call \"{api}\" with \"findInstances\" with parameter \"{c1}\"\n    Then \"{result}\" is an array of objects with the following contents\n      | appId | instanceId |\n      | One   |          1 |\n      | Two   |          2 |\n      | Three |          3 |\n    And messaging will have posts\n      | payload.app.appId | payload.app.instanceId | matches_type         |\n      | chipShop          | c1                     | findInstancesRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/broadcast.feature",
    "content": "Feature: Broadcasting\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    Given User Channels one, two and three\n    Given A Desktop Agent in \"api\"\n    Given \"instrumentMessageOne\" is a BroadcastEvent message on channel \"channel-name\" with context \"fdc3.instrument\"\n    Given \"countryMessageOne\" is a BroadcastEvent message on channel \"channel-name\" with context \"fdc3.country\"\n    Given \"instrumentContext\" is a \"fdc3.instrument\" context\n\n  Scenario: Broadcasting on a named app channel\n    When I call \"{api}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"broadcast\" with parameter \"{instrumentContext}\"\n    Then messaging will have posts\n      | payload.channelId | payload.context.type | payload.context.name | matches_type     |\n      | channel-name      | fdc3.instrument      | Apple                | broadcastRequest |\n\n  Scenario: Broadcasting using the api directly, with no user channel set\n    When I call \"{api}\" with \"broadcast\" with parameter \"{instrumentContext}\"\n    Then messaging will have posts\n      | payload.channelId | payload.context.type | payload.context.name |\n\n  Scenario: Broadcasting using the api directly, with user channel set\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"broadcast\" with parameter \"{instrumentContext}\"\n    Then messaging will have posts\n      | payload.channelId | payload.context.type | payload.context.name | matches_type             |\n      | one               | {null}               | {null}               | joinUserChannelRequest   |\n      | {null}            | {null}               | {null}               | getUserChannelsRequest   |\n      | one               | fdc3.instrument      | Apple                | broadcastRequest         |\n\n  Scenario: Context listener receives originating app metadata\n    Given \"resultHandler\" pipes context and metadata to \"contexts\" and \"metadatas\"\n    When I call \"{api}\" with \"getOrCreateChannel\" with parameter \"channel-name\"\n    And I refer to \"{result}\" as \"channel1\"\n    And I call \"{channel1}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And \"{metadatas}\" is an array of objects with the following contents\n      | source.appId      | source.instanceId     |\n      | broadcasting-app   | broadcasting-instance |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/find-intents.feature",
    "content": "Feature: Basic Intents Support\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And A Desktop Agent in \"api\"\n    And app \"chipShop/c1\" resolves intent \"OrderFood\" with result type \"void\"\n    And app \"chipShop/c2\" resolves intent \"OrderFood\" with result type \"channel<fdc3.chips>\"\n    And app \"library/l1\" resolves intent \"BorrowBooks\" with result type \"channel<fdc3.book>\"\n    And app \"bank/b1\" resolves intent \"Buy\" with context \"fdc3.instrument\" and result type \"fdc3.order\"\n    And app \"bank/b1\" resolves intent \"Sell\" with context \"fdc3.instrument\" and result type \"fdc3.order\"\n    And app \"travelAgent/t1\" resolves intent \"Buy\" with context \"fdc3.currency\" and result type \"fdc3.order\"\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n    And \"crazyContext\" is a \"fdc3.unsupported\" context\n\n  Scenario: Find Intent can return the same intent with multiple apps\n    When I call \"{api}\" with \"findIntent\" with parameter \"Buy\"\n    Then \"{result.intent}\" is an object with the following contents\n      | name |\n      | Buy  |\n    And \"{result.apps}\" is an array of objects with the following contents\n      | appId       | instanceId |\n      | bank        | b1         |\n      | travelAgent | t1         |\n    And messaging will have posts\n      | payload.intent | matches_type      |\n      | Buy            | findIntentRequest |\n\n  Scenario: Find Intent can return an error when an intent doesn't match\n    When I call \"{api}\" with \"findIntent\" with parameter \"Bob\"\n    Then \"{result}\" is an error with message \"NoAppsFound\"\n    And messaging will have posts\n      | payload.intent | matches_type      |\n      | Bob            | findIntentRequest |\n\n  Scenario: Find Intent can filter by a context type\n    When I call \"{api}\" with \"findIntent\" with parameters \"Buy\" and \"{instrumentContext}\"\n    Then \"{result.intent}\" is an object with the following contents\n      | name |\n      | Buy  |\n    And \"{result.apps}\" is an array of objects with the following contents\n      | appId |\n      | bank  |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type      |\n      | Buy            | fdc3.instrument      | AAPL                      | findIntentRequest |\n\n  Scenario: Find Intent can filter by generic result type\n    When I call \"{api}\" with \"findIntent\" with parameters \"OrderFood\" and \"{empty}\" and \"channel<fdc3.chips>\"\n    Then \"{result.intent}\" is an object with the following contents\n      | name      |\n      | OrderFood |\n    And \"{result.apps}\" is an array of objects with the following contents\n      | appId    | instanceId |\n      | chipShop | c2         |\n    And messaging will have posts\n      | payload.intent | payload.resultType  | matches_type      |\n      | OrderFood      | channel<fdc3.chips> | findIntentRequest |\n\n  Scenario: Find Intents By Context\n    When I call \"{api}\" with \"findIntentsByContext\" with parameter \"{instrumentContext}\"\n    Then \"{result}\" is an array of objects with the following contents\n      | intent.name | apps[0].appId | apps.length |\n      | Buy         | bank          |           1 |\n      | Sell        | bank          |           1 |\n    And messaging will have posts\n      | payload.context.type | payload.context.id.ticker | matches_type                |\n      | fdc3.instrument      | AAPL                      | findIntentsByContextRequest |\n\n  Scenario: Find Intents By Context can return an error when an intent doesn't match\n    When I call \"{api}\" with \"findIntentsByContext\" with parameter \"{crazyContext}\"\n    Then \"{result}\" is an error with message \"NoAppsFound\"\n    And messaging will have posts\n      | payload.context.type | payload.context.bogus | matches_type                |\n      | fdc3.unsupported     | {true}                | findIntentsByContextRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/heartbeat.feature",
    "content": "Feature: Heartbeats\n\n  Background: Desktop Agent API\n    Given A Desktop Agent in \"api\"\n    And schemas loaded\n\n  Scenario: Send A Heartbeat\n    When messaging receives a heartbeat event\n    And messaging will have posts\n      | matches_type                    |\n      | heartbeatAcknowledgementRequest |\n\n  Scenario: Saying Goodbye\n    When I call \"{api}\" with \"disconnect\"\n    And we wait for a period of \"100\" ms\n    Then messaging will have posts\n      | matches_type |\n      | WCP6Goodbye  |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/intent-listener.feature",
    "content": "Feature: Intent Listeners\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n    And A Desktop Agent in \"api1\"\n    And \"intentMessageOne\" is a intentEvent message with intent \"BuyStock\" and context \"{instrumentContext}\"\n\n  Scenario: Intent Listeners Work\n    Given \"resultHandler\" pipes intent to \"intents\"\n    When I call \"{api1}\" with \"addIntentListener\" with parameters \"BuyStock\" and \"{resultHandler}\"\n    And messaging receives \"{intentMessageOne}\"\n    Then \"{intents}\" is an array of objects with the following contents\n      | context.type    | context.name | metadata.source.appId |\n      | fdc3.instrument | Apple        | some-app-id           |\n    And messaging will have posts\n      | type                |\n      | intentResultRequest |\n\n  Scenario: Intent Listeners Can Return Results (Context)\n    Given \"resultHandler\" returns a context item\n    When I call \"{api1}\" with \"addIntentListener\" with parameters \"BuyStock\" and \"{resultHandler}\"\n    And messaging receives \"{intentMessageOne}\"\n    Then messaging will have posts\n      | type                | payload.intentResult.context.type | payload.intentResolution.intent |\n      | intentResultRequest | fdc3.returned-intent              | {empty}                         |\n\n  Scenario: Intent Listeners Can Return Results (Channel)\n    Given \"resultHandler\" returns a channel\n    When I call \"{api1}\" with \"addIntentListener\" with parameters \"BuyStock\" and \"{resultHandler}\"\n    And messaging receives \"{intentMessageOne}\"\n    Then messaging will have posts\n      | type                | payload.intentResult.channel.type | payload.intentResult.channel.id |\n      | intentResultRequest | private                           | some-channel-id                 |\n\n  Scenario: Intent Listeners Can Return A Void Result\n    Given \"resultHandler\" returns a void promise\n    When I call \"{api1}\" with \"addIntentListener\" with parameters \"BuyStock\" and \"{resultHandler}\"\n    And messaging receives \"{intentMessageOne}\"\n    Then messaging will have posts\n      | type                | payload.intentResult.channel | payload.intentResult.context |\n      | intentResultRequest | {empty}                      | {empty}                      |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/intent-results.feature",
    "content": "Feature: Intents Can Return Different Results\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And A Desktop Agent in \"api\"\n    And app \"chipShop/c1\" resolves intent \"OrderFood\"\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n\n  Scenario: Raise Intent times out\n    Given Raise Intent times out\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    Then \"{result}\" is an error with message \"ApiTimeout\"\n\n  Scenario: Raise Intent Fails With An Error\n    Given Raise Intent will throw a \"TargetAppUnavailable\" error\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    Then \"{result}\" is an error with message \"TargetAppUnavailable\"\n\n  Scenario: void is returned in the result\n    Given Raise Intent returns no result\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I call \"{result}\" with \"getResult\"\n    Then \"{result}\" is undefined\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Raising An intent With The App Parameter\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\" and \"{c1}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId | intent    |\n      | chipShop     | c1                | OrderFood |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | payload.app.appId | payload.app.instanceId | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | chipShop          | c1                     | raiseIntentRequest |\n\n  Scenario: Context Data is returned in the result\n    Given Raise Intent returns a context of \"{instrumentContext}\"\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I call \"{result}\" with \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type            | name  |\n      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: App Channel is returned in the result\n    Given Raise Intent returns an app channel\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I call \"{result}\" with \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type | id             |\n      | app  | result-channel |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: User Channel is returned in the result\n    Given Raise Intent returns a user channel\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I call \"{result}\" with \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type | id             |\n      | user | result-channel |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Private Channel is returned in the result\n    Given Raise Intent returns a private channel\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I call \"{result}\" with \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type    | id             |\n      | private | result-channel |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Destructured getResult returns context data\n    Given Raise Intent returns a context of \"{instrumentContext}\"\n    When I destructure method \"raiseIntent\" from \"{api}\"\n    And I call destructured \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I destructure method \"getResult\" from \"{result}\"\n    And I call destructured \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type            | name  |\n      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Destructured raiseIntent with app parameter\n    When I destructure method \"raiseIntent\" from \"{api}\"\n    And I call destructured \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\" and \"{c1}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId | intent    |\n      | chipShop     | c1                | OrderFood |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | payload.app.appId | payload.app.instanceId | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | chipShop          | c1                     | raiseIntentRequest |\n\n  Scenario: Destructured getResult returns app channel\n    Given Raise Intent returns an app channel\n    When I destructure method \"raiseIntent\" from \"{api}\"\n    And I call destructured \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I destructure method \"getResult\" from \"{result}\"\n    And I call destructured \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type | id             |\n      | app  | result-channel |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Destructured getResult returns private channel\n    Given Raise Intent returns a private channel\n    When I destructure method \"raiseIntent\" from \"{api}\"\n    And I call destructured \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    And I destructure method \"getResult\" from \"{result}\"\n    And I call destructured \"getResult\"\n    Then \"{result}\" is an object with the following contents\n      | type    | id             |\n      | private | result-channel |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/open.feature",
    "content": "Feature: Desktop Agent Information\n\n  Background: Desktop Agent API\n    Given A Desktop Agent in \"api\"\n    And schemas loaded\n    And app \"chipShop/c1\"\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n\n  Scenario: Open An App\n    When I call \"{api}\" with \"open\" with parameters \"{c1}\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | appId    | instanceId |\n      | chipShop | abc123     |\n    And messaging will have posts\n      | payload.app.appId | payload.context.type | payload.context.id.ticker | matches_type |\n      | chipShop          | fdc3.instrument      | AAPL                      | openRequest  |\n\n  Scenario: Open An App Using App ID\n    When I call \"{api}\" with \"open\" with parameters \"chipShop\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | appId    | instanceId |\n      | chipShop | abc123     |\n    And messaging will have posts\n      | payload.app.appId | payload.context.type | payload.context.id.ticker | matches_type |\n      | chipShop          | fdc3.instrument      | AAPL                      | openRequest  |\n\n  Scenario: Opening a non-existent App\n    When I call \"{api}\" with \"open\" with parameters \"nonExistent\" and \"{instrumentContext}\"\n    Then \"{result}\" is an error with message \"AppNotFound\"\n    And messaging will have posts\n      | payload.app.appId | payload.context.type | payload.context.id.ticker | matches_type |\n      | nonExistent       | fdc3.instrument      | AAPL                      | openRequest  |\n\n  Scenario: Open An App - Destructured\n    When I destructure method \"open\" from \"{api}\"\n    And I call destructured \"open\" with parameters \"{c1}\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | appId    | instanceId |\n      | chipShop | abc123     |\n    And messaging will have posts\n      | payload.app.appId | payload.context.type | payload.context.id.ticker | matches_type |\n      | chipShop          | fdc3.instrument      | AAPL                      | openRequest  |\n\n  Scenario: Open An App Using App ID - Destructured\n    When I destructure method \"open\" from \"{api}\"\n    And I call destructured \"open\" with parameters \"chipShop\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | appId    | instanceId |\n      | chipShop | abc123     |\n    And messaging will have posts\n      | payload.app.appId | payload.context.type | payload.context.id.ticker | matches_type |\n      | chipShop          | fdc3.instrument      | AAPL                      | openRequest  |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/private-channels-deprecated.feature",
    "content": "Feature: Basic Private Channels Support\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And User Channels one, two and three\n    And A Desktop Agent in \"api\"\n    And I call \"{api}\" with \"createPrivateChannel\"\n    And I refer to \"{result}\" as \"privateChannel\"\n    And \"instrumentMessageOne\" is a BroadcastEvent message on channel \"{privateChannel.id}\" with context \"fdc3.instrument\"\n\n  Scenario: Adding and then unsubscribing an \"onAddContextListener\" listener will send a notification of each event to the agent\n    Given \"typesHandler\" pipes types to \"types\"\n    When I call \"{privateChannel}\" with \"onAddContextListener\" with parameter \"{typesHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And we wait for a period of \"100\" ms\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | addContextListener   | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"onAddContextListener\" on a given Private Channel to receive a notification\n    Given \"onAddContextListenerMessage\" is a PrivateChannelOnAddContextListenerEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    And \"typesHandler\" pipes types to \"types\"\n    When I call \"{privateChannel}\" with \"onAddContextListener\" with parameter \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onAddContextListenerMessage}\"\n    Then \"{types}\" is an array of strings with the following values\n      | value           |\n      | fdc3.instrument |\n\n  Scenario: Adding and then unsubscribing an \"onUnsubscribe\" listener will send a notification of each event to the agent\n    Given \"typesHandler\" pipes types to \"types\"\n    When I call \"{privateChannel}\" with \"onUnsubscribe\" with parameter \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And I refer to \"{result}\" as \"theListener\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | unsubscribe          | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"onUnsubscribe\" on a given Private Channel to receive a notification\n    Given \"onUnsubscribeListenerMessage\" is a PrivateChannelOnUnsubscribeEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    And \"typesHandler\" pipes types to \"types\"\n    When I call \"{privateChannel}\" with \"onUnsubscribe\" with parameter \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onUnsubscribeListenerMessage}\"\n    Then \"{types}\" is an array of strings with the following values\n      | value           |\n      | fdc3.instrument |\n\n  Scenario: Adding and then unsubscribing an \"onDisconnect\" listener will send a notification of each event to the agent\n    Given \"voidHandler\" is a invocation counter into \"count\"\n    When I call \"{privateChannel}\" with \"onDisconnect\" with parameter \"{voidHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And we wait for a period of \"100\" ms\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | disconnect           | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"onDisconnect\" on a given Private Channel to receive a notification\n    Given \"onDisconnectListenerMessage\" is a PrivateChannelOnDisconnectEvent message on channel \"{privateChannel.id}\"\n    And \"voidHandler\" is a invocation counter into \"count\"\n    When I call \"{privateChannel}\" with \"onDisconnect\" with parameter \"{voidHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onDisconnectListenerMessage}\"\n    Then \"{count}\" is \"1\"\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/private-channels.feature",
    "content": "Feature: Basic Private Channels Support\n\n  Background: Desktop Agent API\n    Given schemas loaded\n    And User Channels one, two and three\n    And A Desktop Agent in \"api\"\n    And I call \"{api}\" with \"createPrivateChannel\"\n    And I refer to \"{result}\" as \"privateChannel\"\n    And \"instrumentMessageOne\" is a BroadcastEvent message on channel \"{privateChannel.id}\" with context \"fdc3.instrument\"\n\n  Scenario: Adding and then unsubscribing a context listener will send a notification of each event to the agent\n    Given \"contextHandler\" pipes context to \"context\"\n    When I call \"{privateChannel}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{contextHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                              | payload.channelId   | payload.contextType | payload.listenerUUID | matches_type                      |\n      | addContextListenerRequest         | {privateChannel.id} | fdc3.instrument     | {null}               | addContextListenerRequest         |\n      | contextListenerUnsubscribeRequest | {null}              | {null}              | {theListener.id}     | contextListenerUnsubscribeRequest |\n\n  Scenario: Adding a Context Listener on a given Private Channel to receive a notification\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{privateChannel}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: Private channel context listener receives originating app metadata\n    Given \"resultHandler\" pipes context and metadata to \"contexts\" and \"metadatas\"\n    When I call \"{privateChannel}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And \"{metadatas}\" is an array of objects with the following contents\n      | source.appId      | source.instanceId     |\n      | broadcasting-app   | broadcasting-instance |\n\n  Scenario: Adding and then unsubscribing an \"onAddContextListener\" listener will send a notification of each event to the agent\n    Given \"typesHandler\" pipes events to \"types\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"addContextListener\" and \"{typesHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And we wait for a period of \"100\" ms\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | addContextListener   | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"addContextListener\" event handler on a given Private Channel to receive a notification\n    Given \"onAddContextListenerMessage\" is a PrivateChannelOnAddContextListenerEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    And \"typesHandler\" pipes events to \"types\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"addContextListener\" and \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onAddContextListenerMessage}\"\n    Then \"{types}\" is an array of objects with the following contents\n      | contextType     |\n      | fdc3.instrument |\n\n  Scenario: Adding and then unsubscribing an \"onUnsubscribe\" listener will send a notification of each event to the agent\n    Given \"typesHandler\" pipes events to \"types\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"unsubscribe\" and \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And I refer to \"{result}\" as \"theListener\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | unsubscribe          | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"unsubscribe\" event handler on a given Private Channel to receive a notification\n    Given \"onUnsubscribeListenerMessage\" is a PrivateChannelOnUnsubscribeEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    And \"typesHandler\" pipes events to \"types\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"unsubscribe\" and \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onUnsubscribeListenerMessage}\"\n    Then \"{types}\" is an array of objects with the following contents\n      | contextType     |\n      | fdc3.instrument |\n\n  Scenario: Adding an event handler for all events on a given Private Channel to receive a notification\n    Given \"onAddContextListenerMessage\" is a PrivateChannelOnAddContextListenerEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    Given \"onUnsubscribeListenerMessage\" is a PrivateChannelOnUnsubscribeEvent message on channel \"{privateChannel.id}\" with contextType as \"fdc3.instrument\"\n    Given \"onDisconnectListenerMessage\" is a PrivateChannelOnDisconnectEvent message on channel \"{privateChannel.id}\"\n    And \"typesHandler\" pipes events to \"types\"\n    And I call \"{privateChannel}\" with \"addEventListener\" with parameters \"{null}\" and \"{typesHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onAddContextListenerMessage}\"\n    And messaging receives \"{onUnsubscribeListenerMessage}\"\n    And messaging receives \"{onDisconnectListenerMessage}\"\n    Then \"{types}\" is an array of objects with length \"3\"\n\n  Scenario: Adding and then unsubscribing an \"disconnect\" listener will send a notification of each event to the agent\n    Given \"voidHandler\" is a invocation counter into \"count\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"disconnect\" and \"{voidHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And we wait for a period of \"100\" ms\n    And I call \"{theListener}\" with \"unsubscribe\"\n    Then messaging will have posts\n      | type                                          | payload.listenerType | payload.privateChannelId | payload.listenerUUID | matches_type                                  |\n      | privateChannelAddEventListenerRequest         | disconnect           | {privateChannel.id}      | {null}               | privateChannelAddEventListenerRequest         |\n      | privateChannelUnsubscribeEventListenerRequest | {null}               | {null}                   | {theListener.id}     | privateChannelUnsubscribeEventListenerRequest |\n\n  Scenario: Adding an \"onDisconnect\" on a given Private Channel to receive a notification\n    Given \"onDisconnectListenerMessage\" is a PrivateChannelOnDisconnectEvent message on channel \"{privateChannel.id}\"\n    And \"voidHandler\" is a invocation counter into \"count\"\n    When I call \"{privateChannel}\" with \"addEventListener\" with parameters \"disconnect\" and \"{voidHandler}\"\n    And we wait for a period of \"100\" ms\n    And messaging receives \"{onDisconnectListenerMessage}\"\n    Then \"{count}\" is \"1\"\n\n  Scenario: I can broadcast context on a private channel\n    Given \"instrumentContext\" is a \"fdc3.instrument\" context\n    When I call \"{privateChannel}\" with \"broadcast\" with parameter \"{instrumentContext}\"\n    Then messaging will have posts\n      | type             | payload.channelId   | payload.context.type | payload.context.name | matches_type     |\n      | broadcastRequest | {privateChannel.id} | fdc3.instrument      | Apple                | broadcastRequest |\n\n  Scenario: I disconnect from a private channel\n    And I call \"{privateChannel}\" with \"disconnect\"\n    And messaging will have posts\n      | payload.channelId   | matches_type                    |\n      | {null}              | createPrivateChannelRequest     |\n      | {privateChannel.id} | privateChannelDisconnectRequest |\n\n  Scenario: Destructured createPrivateChannel works correctly\n    When I destructure method \"createPrivateChannel\" from \"{api}\"\n    And I call destructured \"createPrivateChannel\"\n    And I refer to \"{result}\" as \"destructuredPrivateChannel\"\n    Then messaging will have posts\n      | payload.channelId | matches_type                |\n      | {null}            | createPrivateChannelRequest |\n\n  Scenario: Destructured private channel methods work correctly\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I destructure methods \"addContextListener\", \"broadcast\" from \"{privateChannel}\"\n    And I call destructured \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I call destructured \"broadcast\" with parameter \"{instrumentContext}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: Destructured disconnect works correctly\n    When I destructure method \"disconnect\" from \"{privateChannel}\"\n    And I call destructured \"disconnect\"\n    Then messaging will have posts\n      | payload.channelId   | matches_type                    |\n      | {privateChannel.id} | privateChannelDisconnectRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/raise-intents.feature",
    "content": "Feature: Basic Intents Support\n\n  Background: Desktop Agent API\n    Given A Desktop Agent in \"api\"\n    And schemas loaded\n    And app \"chipShop/c1\" resolves intent \"OrderFood\" with result type \"void\"\n    And app \"chipShop/c2\" resolves intent \"OrderFood\" with result type \"channel<fdc3.chips>\"\n    And app \"bank/b1\" resolves intent \"Buy\" with context \"fdc3.instrument\" and result type \"fdc3.order\"\n    And app \"bank/b1\" resolves intent \"Sell\" with context \"fdc3.instrument\" and result type \"fdc3.order\"\n    And app \"travelAgent/t1\" resolves intent \"BookFlight\" with context \"fdc3.country\" and result type \"fdc3.order\"\n    And app \"notused/n1\" resolves intent \"Buy\" with context \"fdc3.cancel-me\" and result type \"fdc3.order\"\n    And app \"notused/n2\" resolves intent \"Buy\" with context \"fdc3.cancel-me\" and result type \"fdc3.order\"\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n    And \"countryContext\" is a \"fdc3.country\" context\n    And \"cancelContext\" is a \"fdc3.cancel-me\" context\n\n  Scenario: Raising an intent and invoking the intent resolver when it's not clear which intent is required\n            The intent resolver will just take the first matching application\n            that would resolve the intent.\n\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId |\n      | chipShop     | c1                |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | payload.app.instanceId | matches_type       |\n      | OrderFood      | fdc3.instrument      | AAPL                      | {null}                 | raiseIntentRequest |\n      | OrderFood      | fdc3.instrument      | AAPL                      | c1                     | raiseIntentRequest |\n\n  Scenario: Raising an intent and invoking the intent resolver, but the user cancels it.\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"OrderFood\" and \"{cancelContext}\"\n    Then \"{result}\" is an error with message \"UserCancelledResolution\"\n    And messaging will have posts\n      | payload.intent | payload.context.type | matches_type       |\n      | OrderFood      | fdc3.cancel-me       | raiseIntentRequest |\n\n  Scenario: Raising Intent exactly right, so the resolver isn't required\n    When I call \"{api}\" with \"raiseIntent\" with parameters \"Buy\" and \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId |\n      | bank         | b1                |\n    And messaging will have posts\n      | payload.intent | payload.context.type | payload.context.id.ticker | matches_type       |\n      | Buy            | fdc3.instrument      | AAPL                      | raiseIntentRequest |\n\n  Scenario: Raising Intent By Context and invoking the intent resolver when it's not clear which intent is required\n            The intent resolver will just take the first matching application\n            that would resolve an intent.\n\n    When I call \"{api}\" with \"raiseIntentForContext\" with parameter \"{instrumentContext}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId |\n      | chipShop     | c1                |\n    And messaging will have posts\n      | payload.context.type | payload.context.id.ticker | payload.app.instanceId | matches_type                 |\n      | fdc3.instrument      | AAPL                      | {null}                 | raiseIntentForContextRequest |\n      | fdc3.instrument      | AAPL                      | c1                     | raiseIntentRequest           |\n\n  Scenario: Raising Intent By Context exactly right, so the resolver isn't required\n    When I call \"{api}\" with \"raiseIntentForContext\" with parameters \"{countryContext}\" and \"{t1}\"\n    Then \"{result}\" is an object with the following contents\n      | source.appId | source.instanceId |\n      | travelAgent  | t1                |\n    And messaging will have posts\n      | payload.context.type | payload.context.name | payload.app.appId | payload.app.instanceId | matches_type                 |\n      | fdc3.country         | Sweden               | travelAgent       | t1                     | raiseIntentForContextRequest |\n\n  Scenario: Raising an intent and invoking the intent resolver, but the user cancels it.\n    When I call \"{api}\" with \"raiseIntentForContext\" with parameter \"{cancelContext}\"\n    Then \"{result}\" is an error with message \"UserCancelledResolution\"\n    And messaging will have posts\n      | payload.context.type | matches_type                 |\n      | fdc3.cancel-me       | raiseIntentForContextRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/user-channel-selector.feature",
    "content": "Feature: Updating User Channel State\n\n  Background:\n    Given schemas loaded\n    Given User Channels one, two and three\n    And A Channel Selector in \"selector\" and a Desktop Agent in \"api\"\n\n  Scenario: Selecting a channel updates the DA\n    When The first channel is selected via the channel selector in \"selector\"\n    And The second channel is selected via the channel selector in \"selector\"\n    Then messaging will have posts\n      | payload.channelId | matches_type               |\n      | one               | joinUserChannelRequest     |\n      | two               | joinUserChannelRequest     |\n    And The channel is deselected via the channel selector in \"selector\"\n    Then messaging will have posts\n      | matches_type               |\n      | leaveCurrentChannelRequest |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/user-channel-sync.feature",
    "content": "Feature: Updating User Channel State\n\n  Background:\n    Given schemas loaded\n    Given User Channels one, two and three\n    Given \"instrumentContext\" is a \"fdc3.instrument\" context\n    And \"crazyContext\" is a \"fdc3.unsupported\" context\n    And channel \"one\" has context \"{instrumentContext}\"\n    And channel \"two\" has context \"{crazyContext}\"\n    And A Desktop Agent in \"api\"\n\n  Scenario: Joining A User Channel Receives Correct Context on Listener\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And we wait for a period of \"1000\" ms\n    Then \"{contexts}\" is an array of objects with the following contents\n      | type            | name  |\n      | fdc3.instrument | Apple |\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I call \"{result}\" with \"getCurrentContext\" with parameter \"fdc3.instrument\"\n    Then \"{result}\" is an object with the following contents\n      | type            | name  |\n      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | payload.listenerUUID | matches_type             |\n      | one               | {null}              | {null}               | joinUserChannelRequest   |\n      | {null}            | {null}              | {null}               | getUserChannelsRequest   |\n      | one               | fdc3.instrument     | {null}               | getCurrentContextRequest |\n      | one               | fdc3.instrument     | {null}               | getCurrentContextRequest |\n\n  Scenario: Changing User Channel Doesn't Receive Incorrect Context on Listener\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"two\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | type | name |\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I call \"{result}\" with \"getCurrentContext\" with parameter \"fdc3.instrument\"\n    Then \"{result}\" is null\n\n  Scenario: disconnection\n    When I call \"{api}\" with \"disconnect\"\n    Then \"{result}\" is undefined\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/user-channels-set-by-agent.feature",
    "content": "Feature: User Channels Support where the Desktop Agent puts the app on a channel\n\n  Background: Desktop Agent API\n    Given User Channels one, two and three\n    Given schemas loaded\n    Given A Desktop Agent in \"api\" that puts apps on channel \"one\"\n    Given \"instrumentMessageOne\" is a BroadcastEvent message on channel \"one\" with context \"fdc3.instrument\"\n    \n  Scenario: Initial User Channel\n        At startup, the user channel should be set\n\n    When I call \"{api}\" with \"getCurrentChannel\"\n    Then \"{result}\" is an object with the following contents\n      | id  | type | displayMetadata.color |\n      | one | user | red                   |\n\n  Scenario: Adding a Typed Listener on a given User Channel\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | {null}            | fdc3.instrument     | addContextListenerRequest |\n      | one               | fdc3.instrument     | getCurrentContextRequest  |\n\n  Scenario: I should be able to leave a user channel, and not receive messages on it\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I call \"{api}\" with \"leaveCurrentChannel\"\n    Then messaging will have posts\n      | payload.channelId | payload.contextType | payload.listenerUUID | matches_type               |\n      | {null}            | fdc3.instrument     | {null}               | addContextListenerRequest  |\n      | one               | fdc3.instrument     | {null}               | getCurrentContextRequest   |\n      | {null}            | {null}              | {null}               | leaveCurrentChannelRequest |\n      | {null}            | {null}              | {null}               | getUserChannelsRequest     |\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type | name |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/user-channels.feature",
    "content": "Feature: Basic User Channels Support\n\n  Background: Desktop Agent API\n    Given User Channels one, two and three\n    Given schemas loaded\n    Given A Desktop Agent in \"api\"\n    Given \"instrumentMessageOne\" is a BroadcastEvent message on channel \"one\" with context \"fdc3.instrument\"\n    Given \"countryMessageOne\" is a BroadcastEvent message on channel \"one\" with context \"fdc3.country\"\n    Given \"openMessage\" is a BroadcastEvent message on channel \"{null}\" with context \"fdc3.instrument\"\n    Given \"instrumentContext\" is a \"fdc3.instrument\" context\n    Given \"userChannelMessage1\" is a channelChangedEvent message on channel \"one\"\n    Given \"userChannelMessage2\" is a channelChangedEvent message on channel \"two\"\n    Given \"userChannelMessage3\" is a channelChangedEvent message on channel \"three\"\n    Given \"userChannelMessageBroken\" is a channelChangedEvent message on channel \"nonexistent\"\n\n  Scenario: List User Channels\n        There should be a selection of user channels to choose from\n\n    When I call \"{api}\" with \"getUserChannels\"\n    Then \"{result}\" is an array of objects with the following contents\n      | id    | type | displayMetadata.color | displayMetadata.glyph | displayMetadata.name |\n      | one   | user | red                   | triangle              | The one channel      |\n      | two   | user | red                   | triangle              | The two channel      |\n      | three | user | red                   | triangle              | The three channel    |\n    And messaging will have posts\n      | meta.source.appId | meta.source.instanceId | matches_type           |\n      | cucumber-app      | cucumber-instance      | getUserChannelsRequest |\n\n  Scenario: List User Channels via Deprecated API call\n        There should be a selection of user channels to choose from\n\n    When I call \"{api}\" with \"getSystemChannels\"\n    Then \"{result}\" is an array of objects with the following contents\n      | id    | type | displayMetadata.color | displayMetadata.glyph | displayMetadata.name |\n      | one   | user | red                   | triangle              | The one channel      |\n      | two   | user | red                   | triangle              | The two channel      |\n      | three | user | red                   | triangle              | The three channel    |\n    And messaging will have posts\n      | meta.source.appId | meta.source.instanceId | matches_type           |\n      | cucumber-app      | cucumber-instance      | getUserChannelsRequest |\n\n  Scenario: Initial User Channel\n        At startup, the user channel shouldn't be set\n\n    When I call \"{api}\" with \"getCurrentChannel\"\n    Then \"{result}\" is null\n    And messaging will have posts\n      | meta.source.appId | meta.source.instanceId | matches_type             |\n      | cucumber-app      | cucumber-instance      | getCurrentChannelRequest |\n\n  Scenario: Changing Channel\n        You should be able to join a channel knowing it's ID.\n\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    When I call \"{api}\" with \"getCurrentChannel\"\n    Then \"{result}\" is an object with the following contents\n      | id  | type | displayMetadata.color |\n      | one | user | red                   |\n    And messaging will have posts\n      | payload.channelId | matches_type             |\n      | one               | joinUserChannelRequest   |\n      | {null}            | getUserChannelsRequest   |\n\n  Scenario: Changing Channel via Deprecated API\n        You should be able to join a channel knowing it's ID.\n\n    When I call \"{api}\" with \"joinChannel\" with parameter \"one\"\n    When I call \"{api}\" with \"getCurrentChannel\"\n    Then \"{result}\" is an object with the following contents\n      | id  | type | displayMetadata.color |\n      | one | user | red                   |\n    And messaging will have posts\n      | payload.channelId | matches_type             |\n      | one               | joinUserChannelRequest   |\n      | {null}            | getUserChannelsRequest   |\n\n  Scenario: Adding a Typed Listener on a given User Channel\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | one               | {null}              | joinUserChannelRequest    |\n      | {null}            | {null}              | getUserChannelsRequest    |\n      | {null}            | fdc3.instrument     | addContextListenerRequest |\n      | one               | fdc3.instrument     | getCurrentContextRequest  |\n\n  Scenario: Adding an Un-Typed Listener on a given User Channel\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"{empty}\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | one               | {null}              | joinUserChannelRequest    |\n      | {null}            | {null}              | getUserChannelsRequest    |\n      | {null}            | {null}              | addContextListenerRequest |\n      | one               | {null}              | getCurrentContextRequest  |\n\n  Scenario: Adding an Un-Typed Listener on a given User Channel (deprecated API)\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameter \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | one               | {null}              | joinUserChannelRequest    |\n      | {null}            | {null}              | getUserChannelsRequest    |\n      | {null}            | {null}              | addContextListenerRequest |\n      | one               | {null}              | getCurrentContextRequest  |\n\n  Scenario: If you haven't joined a channel, your listener receives nothing\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is empty\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | {null}            | fdc3.instrument     | addContextListenerRequest |\n\n  Scenario: After unsubscribing, my listener shouldn't receive any more messages\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And messaging receives \"{instrumentMessageOne}\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | payload.listenerUUID | matches_type                      |\n      | one               | {null}              | {null}               | joinUserChannelRequest            |\n      | {null}            | {null}              | {null}               | getUserChannelsRequest            |\n      | {null}            | fdc3.instrument     | {null}               | addContextListenerRequest         |\n      | one               | fdc3.instrument     | {null}               | getCurrentContextRequest          |\n      | {null}            | {null}              | {theListener.id}     | contextListenerUnsubscribeRequest |\n\n  Scenario: I should be able to leave a user channel, and not receive messages on it\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I call \"{api}\" with \"leaveCurrentChannel\"\n    Then messaging will have posts\n      | payload.channelId | payload.contextType | payload.listenerUUID | matches_type               |\n      | one               | {null}              | {null}               | joinUserChannelRequest     |\n      | {null}            | {null}              | {null}               | getUserChannelsRequest     |\n      | {null}            | fdc3.instrument     | {null}               | addContextListenerRequest  |\n      | one               | fdc3.instrument     | {null}               | getCurrentContextRequest   |\n      | {null}            | {null}              | {null}               | leaveCurrentChannelRequest |\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type | name |\n\n  Scenario: Joining a user channel that doesn't exist throws an error\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"nonexistent\"\n    Then \"{result}\" is an error with message \"NoChannelFound\"\n\n  Scenario: Passing invalid arguments to a user channel's addContextListener fn throws an error\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"addContextListener\" with parameters \"{true}\" and \"{resultHandler}\"\n    # Specific error message not tested as its not currently standardized\n    # TODO: Fix when #1490 is resolved\n    Then \"{result}\" is an error\n    And I call \"{api}\" with \"addContextListener\" with parameters \"{null}\" and \"{true}\"\n    Then \"{result}\" is an error\n\n  Scenario: You can get the details of the last context type sent\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I refer to \"{result}\" as \"theChannel\"\n    And I call \"{api}\" with \"broadcast\" with parameter \"{instrumentContext}\"\n    And I call \"{theChannel}\" with \"getCurrentContext\"\n    Then \"{result}\" is an object with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.context.type | payload.context.id.ticker | matches_type             |\n      | one               | {null}               | {null}                    | joinUserChannelRequest   |\n      | {null}            | {null}               | {null}                    | getUserChannelsRequest   |\n      | one               | fdc3.instrument      | AAPL                      | broadcastRequest         |\n      | one               | {null}               | {null}                    | getCurrentContextRequest |\n\n  Scenario: Asking for a piece of context (e.g. an email) when it's not been sent returns null\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I refer to \"{result}\" as \"theChannel\"\n    And messaging receives \"{instrumentMessageOne}\"\n    And I call \"{theChannel}\" with \"getCurrentContext\" with parameter \"fdc3.email\"\n    Then \"{result}\" is null\n\n  Scenario: User Channel Updated By Desktop Agent Changes User Channel Context Listeners\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    When messaging receives \"{userChannelMessage2}\"\n    # Channel changed event handling is async\n    And we wait for a period of \"100\" ms\n    Then \"{channelId}\" is \"two\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type | name |\n\n  Scenario: User Channel Updated By Desktop Agent To A Non-Existent User Channel Sets The Channel To Null\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    When messaging receives \"{userChannelMessageBroken}\"\n    # Channel changed event handling is async and this case involves an extra round trip to the DA\n    And we wait for a period of \"500\" ms\n    Then \"{channelId}\" is \"{null}\"\n\n  Scenario: Adding and removing A User Channel Changed Event Listener\n    Given \"typesHandler\" pipes events to \"types\"\n    When I call \"{api}\" with \"addEventListener\" with parameters \"userChannelChanged\" and \"{typesHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And messaging receives \"{userChannelMessage2}\"\n    And messaging receives \"{userChannelMessage1}\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    And messaging receives \"{userChannelMessage3}\"\n    Then messaging will have posts\n      | payload.type         | type                            | matches_type                    |\n      | USER_CHANNEL_CHANGED | addEventListenerRequest         | addEventListenerRequest         |\n      | USER_CHANNEL_CHANGED | addEventListenerRequest         | addEventListenerRequest         |\n      | {null}               | getUserChannelsRequest          | getUserChannelsRequest          |\n      | {null}               | getUserChannelsRequest          | getUserChannelsRequest          |\n      | {null}               | eventListenerUnsubscribeRequest | eventListenerUnsubscribeRequest |\n    And \"{types}\" is an array of objects with the following contents\n      | currentChannelId |\n      | two              |\n      | one              |\n\n  Scenario: Adding and removing A \"null\" (i.e. wildcard) Event Listener\n    Given \"typesHandler\" pipes events to \"types\"\n    When I call \"{api}\" with \"addEventListener\" with parameters \"{null}\" and \"{typesHandler}\"\n    And I refer to \"{result}\" as \"theListener\"\n    And messaging receives \"{userChannelMessage2}\"\n    And messaging receives \"{userChannelMessage1}\"\n    And I call \"{theListener}\" with \"unsubscribe\"\n    And messaging receives \"{userChannelMessage3}\"\n    Then \"{types}\" is an array of objects with the following contents\n      | currentChannelId |\n      | two              |\n      | one              |\n    And messaging will have posts\n      | payload.type         | type                            | matches_type                    |\n      | USER_CHANNEL_CHANGED | addEventListenerRequest         | addEventListenerRequest         |\n      | {null}               | addEventListenerRequest         | addEventListenerRequest         |\n      | {null}               | getUserChannelsRequest          | getUserChannelsRequest          |\n      | {null}               | getUserChannelsRequest          | getUserChannelsRequest          |\n      | {null}               | eventListenerUnsubscribeRequest | eventListenerUnsubscribeRequest |\n\n  Scenario: Adding An Unknown Event Listener\n    Given \"typesHandler\" pipes events to \"types\"\n    When I call \"{api}\" with \"addEventListener\" with parameters \"unknownEventType\" and \"{typesHandler}\"\n    Then \"{result}\" is an error with message \"UnknownEventType\"\n\n  Scenario: Destructured getUserChannels returns user channels\n    When I destructure method \"getUserChannels\" from \"{api}\"\n    And I call destructured \"getUserChannels\"\n    Then \"{result}\" is an array of objects with the following contents\n      | id    | type | displayMetadata.color | displayMetadata.glyph | displayMetadata.name |\n      | one   | user | red                   | triangle              | The one channel      |\n      | two   | user | red                   | triangle              | The two channel      |\n      | three | user | red                   | triangle              | The three channel    |\n\n  Scenario: Destructured joinUserChannel and getCurrentChannel work correctly\n    When I destructure method \"joinUserChannel\" from \"{api}\"\n    And I call destructured \"joinUserChannel\" with parameter \"one\"\n    And I destructure method \"getCurrentChannel\" from \"{api}\"\n    And I call destructured \"getCurrentChannel\"\n    Then \"{result}\" is an object with the following contents\n      | id  | type | displayMetadata.color |\n      | one | user | red                   |\n    And messaging will have posts\n      | payload.channelId | matches_type             |\n      | one               | joinUserChannelRequest   |\n      | {null}            | getUserChannelsRequest   |\n\n  Scenario: Destructured channel getCurrentContext after broadcast\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I refer to \"{result}\" as \"theChannel\"\n    And I destructure methods \"broadcast\", \"getCurrentContext\" from \"{api}\"\n    And I destructure method \"getCurrentContext\" from \"{theChannel}\"\n    And I call destructured \"broadcast\" with parameter \"{instrumentContext}\"\n    And I call destructured \"getCurrentContext\"\n    Then \"{result}\" is an object with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: Destructured broadcast on user channel\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I destructure method \"broadcast\" from \"{api}\"\n    And I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call destructured \"broadcast\" with parameter \"{instrumentContext}\"\n    And I call \"{api}\" with \"getCurrentChannel\"\n    And I refer to \"{result}\" as \"theChannel\"\n    And I call \"{theChannel}\" with \"getCurrentContext\"\n    Then \"{result}\" is an object with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n\n  Scenario: Destructured user channel addContextListener works correctly\n    Given \"resultHandler\" pipes context to \"contexts\"\n    When I destructure method \"addContextListener\" from \"{api}\"\n    And I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call destructured \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n\n  Scenario: BroadcastEvent on app Opening\n    Given \"resultHandler\" pipes context to \"contexts\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{openMessage}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And messaging will have posts\n      | payload.channelId | payload.contextType | matches_type              |\n      | {null}            | fdc3.instrument     | addContextListenerRequest |\n\n  Scenario: User channel context listener receives originating app metadata\n    Given \"resultHandler\" pipes context and metadata to \"contexts\" and \"metadatas\"\n    When I call \"{api}\" with \"joinUserChannel\" with parameter \"one\"\n    And I call \"{api}\" with \"addContextListener\" with parameters \"fdc3.instrument\" and \"{resultHandler}\"\n    And messaging receives \"{instrumentMessageOne}\"\n    Then \"{contexts}\" is an array of objects with the following contents\n      | id.ticker | type            | name  |\n      | AAPL      | fdc3.instrument | Apple |\n    And \"{metadatas}\" is an array of objects with the following contents\n      | source.appId      | source.instanceId     |\n      | broadcasting-app   | broadcasting-instance |\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/features/utils.feature",
    "content": "Feature: Utility functions\n\n\tScenario: throwIfUndefined is used to check properties\n\t\tWhen I call throwIfUndefined it throws if a specified property is not defined\n\t\tAnd I call throwIfUndefined it does NOT throw if a specified property IS defined\n\t\t\n\tScenario: Logger utility\n\t\tWhen All log functions are used with a message\n\t\tWhen All log functions are used with an error\n\t\t"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/step-definitions/channelSelector.steps.ts",
    "content": "import { Given, When } from 'quickpickle';\nimport { SimpleIntentResolver } from '@finos/testing';\nimport { CustomWorld } from '../world/index.js';\nimport { CHANNEL_STATE } from '@finos/testing';\nimport {\n  DefaultChannelSupport,\n  DefaultHeartbeatSupport,\n  DefaultIntentSupport,\n  DefaultAppSupport,\n  DesktopAgentProxy,\n} from '../../src/index.js';\nimport { TestChannelSelector } from '../support/TestChannelSelector.js';\nimport { TestMessaging } from '../support/TestMessaging.js';\nimport { LogLevel } from '@finos/fdc3-standard';\n\n//Update this to enable debug output when debugging test failures\nconst logLevel = LogLevel.WARN;\n\nGiven(\n  'A Channel Selector in {string} and a Desktop Agent in {string}',\n  async (world: CustomWorld, selectorField: string, daField: string) => {\n    if (!world.messaging) {\n      world.messaging = new TestMessaging(world.props[CHANNEL_STATE]);\n    }\n\n    const ts = new TestChannelSelector();\n    world.props[selectorField] = ts;\n\n    const cs = new DefaultChannelSupport(world.messaging, ts, 10000);\n    const hs = new DefaultHeartbeatSupport(world.messaging);\n    const is = new DefaultIntentSupport(world.messaging, new SimpleIntentResolver(world), 10000, 100000);\n    const as = new DefaultAppSupport(world.messaging, 10000, 100000);\n\n    const da = new DesktopAgentProxy(hs, cs, is, as, [hs], logLevel);\n    await da.connect();\n\n    world.props[daField] = da;\n    world.props['result'] = null;\n\n    //populate the channel selector\n    const channel = await cs.getUserChannel();\n    const userChannels = await cs.getUserChannels();\n    ts.updateChannel(channel?.id ?? null, userChannels);\n  }\n);\n\nWhen(\n  'The first channel is selected via the channel selector in {string}',\n  async (world: CustomWorld, selectorField: string) => {\n    const selector = world.props[selectorField] as TestChannelSelector;\n    selector.selectFirstChannel();\n  }\n);\n\nWhen(\n  'The second channel is selected via the channel selector in {string}',\n  async (world: CustomWorld, selectorField: string) => {\n    const selector = world.props[selectorField] as TestChannelSelector;\n    selector.selectSecondChannel();\n  }\n);\n\nWhen(\n  'The channel is deselected via the channel selector in {string}',\n  async (world: CustomWorld, selectorField: string) => {\n    const selector = world.props[selectorField] as TestChannelSelector;\n    selector.deselectChannel();\n  }\n);\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/step-definitions/channels.steps.ts",
    "content": "import { Given, Then, When } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { Context } from '@finos/fdc3-context';\nimport { handleResolve, matchData } from '@finos/testing';\nimport { CustomWorld } from '../world/index.js';\nimport { CHANNEL_STATE } from '@finos/testing';\nimport { ApiEvent, ContextMetadata } from '@finos/fdc3-standard';\nimport {\n  BroadcastEvent,\n  ChannelChangedEvent,\n  PrivateChannelOnAddContextListenerEvent,\n  PrivateChannelOnDisconnectEvent,\n  PrivateChannelOnUnsubscribeEvent,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nconst contextMap: Record<string, Context> = {\n  'fdc3.instrument': {\n    type: 'fdc3.instrument',\n    name: 'Apple',\n    id: {\n      ticker: 'AAPL',\n    },\n  },\n  'fdc3.country': {\n    type: 'fdc3.country',\n    name: 'Sweden',\n    id: {\n      COUNTRY_ISOALPHA2: 'SE',\n      COUNTRY_ISOALPHA3: 'SWE',\n    },\n  },\n  'fdc3.unsupported': {\n    type: 'fdc3.unsupported',\n    bogus: true,\n  },\n  'fdc3.cancel-me': {\n    type: 'fdc3.cancel-me',\n  },\n};\n\nGiven('{string} is a {string} context', (world: CustomWorld, field: string, type: string) => {\n  world.props[field] = contextMap[type];\n});\n\nGiven(\n  '{string} is a BroadcastEvent message on channel {string} with context {string}',\n  (world: CustomWorld, field: string, channel: string, context: string) => {\n    const message = {\n      meta: {\n        ...world.messaging!.createEventMeta(),\n      },\n      payload: {\n        channelId: handleResolve(channel, world),\n        context: contextMap[context],\n        originatingApp: {\n          appId: 'broadcasting-app',\n          instanceId: 'broadcasting-instance',\n        },\n      },\n      type: 'broadcastEvent',\n    } as BroadcastEvent;\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a {string} message on channel {string}',\n  (world: CustomWorld, field: string, type: string, channel: string) => {\n    const message = {\n      meta: world.messaging!.createEventMeta(),\n      payload: {\n        privateChannelId: handleResolve(channel, world),\n      },\n      type,\n    } as PrivateChannelOnDisconnectEvent;\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a {string} message on channel {string} with listenerType as {string}',\n  (world: CustomWorld, field: string, type: string, channel: string, listenerType: string) => {\n    const message = {\n      meta: world.messaging!.createMeta(),\n      payload: {\n        channelId: handleResolve(channel, world),\n        listenerType,\n      },\n      type,\n    };\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a channelChangedEvent message on channel {string}',\n  (world: CustomWorld, field: string, channel: string) => {\n    const message: ChannelChangedEvent = {\n      meta: {\n        eventUuid: world.messaging!.createUUID(),\n        timestamp: new Date(),\n      },\n      payload: {\n        newChannelId: handleResolve(channel, world),\n      },\n      type: 'channelChangedEvent',\n    };\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a PrivateChannelOnUnsubscribeEvent message on channel {string} with contextType as {string}',\n  (world: CustomWorld, field: string, channel: string, contextType: string) => {\n    const message = {\n      meta: world.messaging!.createEventMeta(),\n      payload: {\n        privateChannelId: handleResolve(channel, world),\n        contextType,\n      },\n      type: 'privateChannelOnUnsubscribeEvent',\n    } as PrivateChannelOnUnsubscribeEvent;\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a PrivateChannelOnAddContextListenerEvent message on channel {string} with contextType as {string}',\n  (world: CustomWorld, field: string, channel: string, contextType: string) => {\n    const message = {\n      meta: world.messaging!.createEventMeta(),\n      payload: {\n        privateChannelId: handleResolve(channel, world),\n        contextType,\n      },\n      type: 'privateChannelOnAddContextListenerEvent',\n    } as PrivateChannelOnAddContextListenerEvent;\n\n    world.props[field] = message;\n  }\n);\n\nGiven(\n  '{string} is a PrivateChannelOnDisconnectEvent message on channel {string}',\n  (world: CustomWorld, field: string, channel: string) => {\n    const message = {\n      meta: world.messaging!.createEventMeta(),\n      payload: {\n        privateChannelId: handleResolve(channel, world),\n      },\n      type: 'privateChannelOnDisconnectEvent',\n    } as PrivateChannelOnDisconnectEvent;\n\n    world.props[field] = message;\n  }\n);\n\nGiven('{string} pipes types to {string}', (world: CustomWorld, typeHandlerName: string, field: string) => {\n  world.props[field] = [];\n  world.props[typeHandlerName] = (s?: string) => {\n    world.props[field].push(s);\n  };\n});\n\nGiven('{string} pipes events to {string}', (world: CustomWorld, typeHandlerName: string, field: string) => {\n  world.props[field] = [];\n  world.props[typeHandlerName] = (s?: ApiEvent) => {\n    world.props[field].push(s?.details);\n  };\n});\n\nGiven('{string} pipes context to {string}', (world: CustomWorld, contextHandlerName: string, field: string) => {\n  world.props[field] = [];\n  world.props[contextHandlerName] = (context: Context) => {\n    world.props[field].push(context);\n  };\n});\n\nGiven(\n  '{string} pipes context and metadata to {string} and {string}',\n  (world: CustomWorld, contextHandlerName: string, contextField: string, metadataField: string) => {\n    world.props[contextField] = [];\n    world.props[metadataField] = [];\n    world.props[contextHandlerName] = (context: Context, metadata?: ContextMetadata) => {\n      world.props[contextField].push(context);\n      world.props[metadataField].push(metadata);\n    };\n  }\n);\n\nWhen('messaging receives {string}', (world: CustomWorld, field: string) => {\n  const message = handleResolve(field, world);\n  console.log(`Sending: `, message);\n  world.messaging!.receive(message, console.log);\n});\n\nThen('messaging will have posts', (world: CustomWorld, dt: DataTable) => {\n  // just take the last few posts and match those\n  const matching = dt.rows().length;\n  let toUse = world.messaging!.allPosts!;\n  if (toUse.length > matching) {\n    toUse = toUse.slice(toUse.length - matching, toUse.length);\n  }\n  matchData(world, toUse, dt);\n});\n\nGiven('channel {string} has context {string}', (world: CustomWorld, channel: string, context: string) => {\n  const ctxObject = handleResolve(context, world);\n  const state = world.props[CHANNEL_STATE] ?? {};\n  world.props[CHANNEL_STATE] = state;\n\n  const cs = state[channel] ?? [];\n  cs.push(ctxObject);\n  state[channel] = cs;\n});\n\nGiven('User Channels one, two and three', (world: CustomWorld) => {\n  world.props[CHANNEL_STATE] = {\n    one: [],\n    two: [],\n    three: [],\n  };\n});\n\nWhen(\n  'I destructure methods {string}, {string} from {string}',\n  (world: CustomWorld, method1: string, method2: string, objectField: string) => {\n    const object = handleResolve(objectField, world);\n    world.props[`destructured_${method1}`] = object[method1];\n    world.props[`destructured_${method2}`] = object[method2];\n  }\n);\n\nWhen('I destructure method {string} from {string}', (world: CustomWorld, methodName: string, objectField: string) => {\n  const object = handleResolve(objectField, world);\n  const destructuredMethod = object[methodName];\n  world.props[`destructured_${methodName}`] = destructuredMethod;\n});\n\nWhen('I call destructured {string}', async (world: CustomWorld, methodName: string) => {\n  const destructuredMethod = world.props[`destructured_${methodName}`];\n  try {\n    const result = await destructuredMethod();\n    world.props['result'] = result;\n  } catch (error) {\n    world.props['error'] = error;\n    world.props['result'] = null;\n  }\n});\n\nWhen(\n  'I call destructured {string} with parameter {string}',\n  async (world: CustomWorld, methodName: string, param: string) => {\n    const destructuredMethod = world.props[`destructured_${methodName}`];\n    const resolvedParam = handleResolve(param, world);\n    try {\n      const result = await destructuredMethod(resolvedParam);\n      world.props['result'] = result;\n    } catch (error) {\n      world.props['error'] = error;\n      world.props['result'] = null;\n    }\n  }\n);\n\nWhen(\n  'I call destructured {string} with parameters {string} and {string}',\n  async (world: CustomWorld, methodName: string, param1: string, param2: string) => {\n    const destructuredMethod = world.props[`destructured_${methodName}`];\n    const resolvedParam1 = handleResolve(param1, world);\n    const resolvedParam2 = handleResolve(param2, world);\n    try {\n      const result = await destructuredMethod(resolvedParam1, resolvedParam2);\n      world.props['result'] = result;\n    } catch (error) {\n      world.props['error'] = error;\n      world.props['result'] = null;\n    }\n  }\n);\n\nWhen(\n  'I call destructured {string} with parameters {string} and {string} and {string}',\n  async (world: CustomWorld, methodName: string, param1: string, param2: string, param3: string) => {\n    const destructuredMethod = world.props[`destructured_${methodName}`];\n    const resolvedParam1 = handleResolve(param1, world);\n    const resolvedParam2 = handleResolve(param2, world);\n    const resolvedParam3 = handleResolve(param3, world);\n    try {\n      const result = await destructuredMethod(resolvedParam1, resolvedParam2, resolvedParam3);\n      world.props['result'] = result;\n    } catch (error) {\n      world.props['error'] = error;\n      world.props['result'] = null;\n    }\n  }\n);\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/step-definitions/generic.steps.ts",
    "content": "import { TestMessaging } from '../support/TestMessaging.js';\nimport { Given, When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport {\n  DesktopAgentProxy,\n  DefaultAppSupport,\n  DefaultChannelSupport,\n  DefaultIntentSupport,\n  DefaultHeartbeatSupport,\n} from '../../src/index.js';\nimport { SimpleIntentResolver, SimpleChannelSelector, CHANNEL_STATE, setupGenericSteps } from '@finos/testing';\nimport { HeartbeatEvent } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { LogLevel } from '@finos/fdc3-standard';\nimport path from 'path';\n\n// Update this to enable debug output when debugging test failures\nconst logLevel = LogLevel.WARN;\n\n// Register shared generic steps from @finos/testing\nconst schemaBasePath = path.join(import.meta.dirname, '../../../');\nsetupGenericSteps(schemaBasePath);\n\nfunction createDesktopAgent(world: CustomWorld, field: string, initialChannelId?: string) {\n  if (!world.messaging) {\n    world.messaging = new TestMessaging(world.props[CHANNEL_STATE], initialChannelId);\n  }\n\n  // n.b. using short timeouts to avoid extending tests unnecessarily\n  const cs = new DefaultChannelSupport(world.messaging, new SimpleChannelSelector(world), 1500);\n  const hs = new DefaultHeartbeatSupport(world.messaging);\n  const is = new DefaultIntentSupport(world.messaging, new SimpleIntentResolver(world), 1500, 3000);\n  const as = new DefaultAppSupport(world.messaging, 1500, 3000);\n\n  const da = new DesktopAgentProxy(hs, cs, is, as, [hs, cs], logLevel);\n  return da;\n}\n\nGiven('A Desktop Agent in {string}', async (world: CustomWorld, field: string) => {\n  const da = createDesktopAgent(world, field);\n  await da.connect();\n\n  world.props[field] = da;\n  world.props['result'] = null;\n});\n\nGiven(\n  'A Desktop Agent in {string} that puts apps on channel {string}',\n  async (world: CustomWorld, field: string, channelId: string) => {\n    const da = createDesktopAgent(world, field, channelId);\n    await da.connect();\n\n    world.props[field] = da;\n    world.props['result'] = null;\n  }\n);\n\nWhen('messaging receives a heartbeat event', (world: CustomWorld) => {\n  world.messaging?.receive({\n    type: 'heartbeatEvent',\n    meta: world.messaging.createEventMeta(),\n    payload: {\n      timestamp: new Date(),\n    },\n  } as HeartbeatEvent);\n});\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/step-definitions/intents.steps.ts",
    "content": "import { Given } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { handleResolve } from '@finos/testing';\nimport { Context } from '@finos/fdc3-context';\nimport { ContextMetadata, ResolveError } from '@finos/fdc3-standard';\nimport { IntentEvent } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nGiven('app {string}', (world: CustomWorld, appStr: string) => {\n  const [appId, instanceId] = appStr.split('/');\n  const app = { appId, instanceId };\n  world.messaging?.addAppIntentDetail({\n    app,\n  });\n  world.props[instanceId] = app;\n});\n\nGiven('app {string} resolves intent {string}', (world: CustomWorld, appStr: string, intent: string) => {\n  const [appId, instanceId] = appStr.split('/');\n  const app = { appId, instanceId };\n  world.messaging?.addAppIntentDetail({\n    app,\n    intent,\n  });\n  world.props[instanceId] = app;\n  world.props[appId] = {\n    appId,\n  };\n});\n\nGiven(\n  'app {string} resolves intent {string} with result type {string}',\n  (world: CustomWorld, appStr: string, intent: string, resultType: string) => {\n    const [appId, instanceId] = appStr.split('/');\n    const app = { appId, instanceId };\n    world.messaging?.addAppIntentDetail({\n      app,\n      intent,\n      resultType,\n    });\n    world.props[instanceId] = app;\n    world.props[appId] = {\n      appId,\n    };\n  }\n);\n\nGiven(\n  'app {string} resolves intent {string} with context {string}',\n  (world: CustomWorld, appStr: string, intent: string, context: string) => {\n    const [appId, instanceId] = appStr.split('/');\n    const app = { appId, instanceId };\n    world.messaging?.addAppIntentDetail({\n      app,\n      intent,\n      context,\n    });\n    world.props[instanceId] = app;\n    world.props[appId] = {\n      appId,\n    };\n  }\n);\n\nGiven(\n  'app {string} resolves intent {string} with context {string} and result type {string}',\n  (world: CustomWorld, appStr: string, intent: string, context: string, resultType: string) => {\n    const [appId, instanceId] = appStr.split('/');\n    const app = { appId, instanceId };\n    world.messaging?.addAppIntentDetail({\n      app,\n      intent,\n      context,\n      resultType,\n    });\n    world.props[instanceId] = app;\n  }\n);\n\nGiven('Raise Intent returns a context of {string}', (world: CustomWorld, result: string) => {\n  world.messaging?.setIntentResult({\n    context: handleResolve(result, world),\n  });\n});\n\nGiven('Raise Intent will throw a {string} error', (world: CustomWorld, error: ResolveError) => {\n  world.messaging?.setIntentResult({\n    error,\n  });\n});\n\nGiven('Raise Intent returns no result', (world: CustomWorld) => {\n  world.messaging?.setIntentResult({});\n});\n\nGiven('Raise Intent times out', (world: CustomWorld) => {\n  world.messaging?.setIntentResult({\n    timeout: true,\n  });\n});\n\nGiven('Raise Intent returns an app channel', (world: CustomWorld) => {\n  world.messaging?.setIntentResult({\n    channel: {\n      type: 'app',\n      id: 'result-channel',\n      displayMetadata: {\n        color: 'purple',\n        name: 'Result Channel',\n      },\n    },\n  });\n});\n\nGiven('Raise Intent returns a user channel', (world: CustomWorld) => {\n  world.messaging?.setIntentResult({\n    channel: {\n      type: 'user',\n      id: 'result-channel',\n      displayMetadata: {\n        color: 'purple',\n        name: 'Result Channel',\n      },\n    },\n  });\n});\n\nGiven('Raise Intent returns a private channel', (world: CustomWorld) => {\n  world.messaging?.setIntentResult({\n    channel: {\n      type: 'private',\n      id: 'result-channel',\n      displayMetadata: {\n        color: 'purple',\n        name: 'Result Channel',\n      },\n    },\n  });\n});\n\nGiven(\n  '{string} is a intentEvent message with intent {string} and context {string}',\n  (world: CustomWorld, field: string, intent: string, context: string) => {\n    const msg: IntentEvent = {\n      type: 'intentEvent',\n      meta: {\n        eventUuid: world.messaging!.createUUID(),\n        timestamp: new Date(),\n      },\n      payload: {\n        originatingApp: {\n          appId: 'some-app-id',\n          desktopAgent: 'some-desktop-agent',\n        },\n        context: handleResolve(context, world),\n        intent,\n        raiseIntentRequestUuid: 'request-id',\n      },\n    };\n\n    world.props[field] = msg;\n  }\n);\n\nGiven('{string} pipes intent to {string}', (world: CustomWorld, intentHandlerName: string, field: string) => {\n  world.props[field] = [];\n  world.props[intentHandlerName] = (context: Context, metadata: ContextMetadata) => {\n    world.props[field].push({\n      context,\n      metadata,\n    });\n  };\n});\n\nGiven('{string} returns a context item', (world: CustomWorld, intentHandlerName: string) => {\n  world.props[intentHandlerName] = async () => {\n    return {\n      type: 'fdc3.returned-intent',\n      id: {\n        in: 'one',\n        out: 'two',\n      },\n    };\n  };\n});\n\nGiven('{string} returns a channel', (world: CustomWorld, intentHandlerName: string) => {\n  world.props[intentHandlerName] = async () => {\n    return {\n      type: 'private',\n      id: 'some-channel-id',\n      displayMetadata: {\n        color: 'ochre',\n        name: 'Some Channel',\n      },\n    };\n  };\n});\n\nGiven('{string} returns a void promise', (world: CustomWorld, intentHandlerName: string) => {\n  world.props[intentHandlerName] = async () => {\n    return null;\n  };\n});\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/step-definitions/util.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { throwIfUndefined } from '../../src/util/throwIfUndefined.js';\nimport { AgentResponseMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { LogLevel, OpenError } from '@finos/fdc3-standard';\nimport { expect } from 'vitest';\nimport { Logger } from '../../src/util/Logger.js';\n\nWhen('I call throwIfUndefined it throws if a specified property is not defined', async (world: CustomWorld) => {\n  let thrown: Error | null = null;\n  const someObject: Record<string, string> = { someProperty: 'value' };\n  const dummyMessage: AgentResponseMessage = {\n    type: 'broadcastResponse',\n    meta: {\n      requestUuid: '123',\n      responseUuid: '456',\n      timestamp: new Date(),\n    },\n    payload: {},\n  };\n  try {\n    throwIfUndefined(\n      someObject.nonExistent,\n      'Deliberately undefined prop did not exist ;-)',\n      dummyMessage,\n      OpenError.MalformedContext\n    );\n  } catch (e) {\n    thrown = e as Error;\n  }\n\n  expect(thrown).not.toBeNull();\n  //should be an error object, with the message we passed in\n  expect(thrown?.message).toEqual(OpenError.MalformedContext);\n});\n\nWhen('I call throwIfUndefined it does NOT throw if a specified property IS defined', async (world: CustomWorld) => {\n  let thrown: Error | null = null;\n  const someObject: Record<string, string> = { someProperty: 'value' };\n  const dummyMessage: AgentResponseMessage = {\n    type: 'broadcastResponse',\n    meta: {\n      requestUuid: '123',\n      responseUuid: '456',\n      timestamp: new Date(),\n    },\n    payload: {},\n  };\n  try {\n    throwIfUndefined(\n      someObject.someProperty,\n      'Deliberately undefined prop did not exist ;-)',\n      dummyMessage,\n      OpenError.MalformedContext\n    );\n  } catch (e) {\n    thrown = e as Error;\n  }\n\n  expect(thrown).toBeNull();\n});\n\nconst TEST_ERROR = 'Test error - This is expected on the console';\n\nWhen('All log functions are used with a message', async (world: CustomWorld) => {\n  Logger.setLogLevel(LogLevel.DEBUG);\n  Logger.debug('Debug msg');\n  Logger.log('Log msg');\n  Logger.warn('Warning msg');\n  Logger.error('Error msg');\n});\n\nWhen('All log functions are used with an error', async (world: CustomWorld) => {\n  Logger.setLogLevel(LogLevel.DEBUG);\n  Logger.debug('debug-level error: ', new Error(TEST_ERROR));\n  Logger.log('log-level error: ', new Error(TEST_ERROR));\n  Logger.warn('warn-level error: ', new Error(TEST_ERROR));\n  Logger.error('error-level error: ', new Error(TEST_ERROR));\n});\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/steps.ts",
    "content": "// Main step definitions entry point for quickpickle\n// This file is loaded by vitest as a setupFile\n\nimport { setWorldConstructor } from 'quickpickle';\nimport { CustomWorld } from './world/index.js';\n\n// Set up the world constructor\nsetWorldConstructor(CustomWorld);\n\n// Import all step definitions\nimport './step-definitions/generic.steps.js';\nimport './step-definitions/channels.steps.js';\nimport './step-definitions/channelSelector.steps.js';\nimport './step-definitions/intents.steps.js';\nimport './step-definitions/util.steps.js';\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/TestChannelSelector.ts",
    "content": "import { Channel, ChannelSelector } from '@finos/fdc3-standard';\n\nexport class TestChannelSelector implements ChannelSelector {\n  private callback: ((channelId: string | null) => void) | null = null;\n  channelId: string | null = null;\n  channels: Channel[] = [];\n\n  constructor() { }\n\n  async updateChannel(channelId: string | null, availableChannels: Channel[]): Promise<void> {\n    this.channelId = channelId;\n    this.channels = availableChannels;\n  }\n\n  setChannelChangeCallback(callback: (channelId: string | null) => void): void {\n    this.callback = callback;\n  }\n\n  async connect(): Promise<void> {\n    console.log('TestChannelSelector was connected');\n  }\n\n  async disconnect(): Promise<void> {\n    console.log('TestChannelSelector was disconnected');\n  }\n\n  selectChannel(channelId: string | null): void {\n    this.channelId = channelId;\n    if (this.callback) {\n      this.callback(this.channelId);\n    } else {\n      throw new Error('Channel selected before Channel Change callback was set!');\n    }\n  }\n\n  selectFirstChannel(): void {\n    this.selectChannel(this.channels[0].id);\n  }\n\n  selectSecondChannel(): void {\n    this.selectChannel(this.channels[1].id);\n  }\n\n  deselectChannel(): void {\n    this.selectChannel(null);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/TestMessaging.ts",
    "content": "import { AppIdentifier, ResolveError } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { v4 as uuidv4 } from 'uuid';\nimport { AbstractMessaging } from '../../src/messaging/AbstractMessaging.js';\nimport { RegisterableListener } from '../../src/listeners/RegisterableListener.js';\nimport { FindIntent } from './responses/FindIntent.js';\nimport { FindIntentByContext } from './responses/FindIntentByContext.js';\nimport { RaiseIntent } from './responses/RaiseIntent.js';\nimport { GetAppMetadata } from './responses/GetAppMetadata.js';\nimport { FindInstances } from './responses/FindInstances.js';\nimport { Open } from './responses/Open.js';\nimport { GetOrCreateChannel } from './responses/GetOrCreateChannel.js';\nimport { ChannelState } from './responses/ChannelState.js';\nimport { GetUserChannels } from './responses/GetUserChannels.js';\nimport { RegisterListeners } from './responses/RegisterListeners.js';\nimport { UnsubscribeListeners } from './responses/UnsubscribeListeners.js';\nimport { CreatePrivateChannel } from './responses/CreatePrivateChannel.js';\nimport { DisconnectPrivateChannel } from './responses/DisconnectPrivateChannel.js';\nimport { IntentResult } from './responses/IntentResult.js';\nimport { RaiseIntentForContext } from './responses/RaiseIntentForContext.js';\nimport {\n  AgentEventMessage,\n  AgentResponseMessage,\n  AppRequestMessage,\n  Channel,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { GetInfo } from './responses/GetInfo.js';\nimport { AddEventListener } from './responses/AddEventListener.js';\n\nexport interface IntentDetail {\n  app?: AppIdentifier;\n  intent?: string;\n  context?: string;\n  resultType?: string;\n}\n\nexport interface AutomaticResponse {\n  filter: (t: string) => boolean;\n  action: (input: AppRequestMessage, m: TestMessaging) => Promise<void>;\n}\n\nexport interface PossibleIntentResult {\n  context?: Context;\n  channel?: Channel;\n  error?: ResolveError;\n  timeout?: boolean;\n}\n\nfunction matchStringOrUndefined(expected: string | undefined, actual: string | undefined) {\n  if (expected && actual) {\n    return expected == actual;\n  } else {\n    return true;\n  }\n}\n\nfunction matchString(expected: string | undefined, actual: string | undefined) {\n  return expected == actual;\n}\n\nfunction removeGenericType(t: string) {\n  const startOfGeneric = t.indexOf('<');\n  if (startOfGeneric > -1) {\n    return t.substring(0, startOfGeneric - 1);\n  } else {\n    return t;\n  }\n}\n\nfunction matchResultTypes(expected: string | undefined, actual: string | undefined) {\n  if (expected) {\n    if (expected.indexOf('<') > -1) {\n      // looking for a complete match involving generics\n      return expected == actual;\n    } else if (actual == undefined) {\n      // no actual, only expected\n      return false;\n    } else {\n      // expected doesn't have generics, match without\n      const actualType = removeGenericType(actual);\n      return expected == actualType;\n    }\n  } else {\n    return true;\n  }\n}\n\nexport function intentDetailMatches(\n  instance: IntentDetail,\n  template: IntentDetail,\n  contextMustMatch: boolean\n): boolean {\n  return (\n    matchStringOrUndefined(template.app?.appId, instance.app?.appId) &&\n    matchStringOrUndefined(template.app?.instanceId, instance.app?.instanceId) &&\n    matchStringOrUndefined(template.intent, instance.intent) &&\n    (contextMustMatch\n      ? matchString(template.context, instance.context)\n      : matchStringOrUndefined(template.context, instance.context)) &&\n    matchResultTypes(template.resultType, instance.resultType)\n  );\n}\n\nexport class TestMessaging extends AbstractMessaging {\n  readonly allPosts: (AppRequestMessage | WebConnectionProtocol6Goodbye)[] = [];\n  readonly listeners: Map<string, RegisterableListener> = new Map();\n  readonly intentDetails: IntentDetail[] = [];\n  readonly channelState: { [key: string]: Context[] };\n  currentChannel: Channel | null = null;\n\n  readonly automaticResponses: AutomaticResponse[];\n\n  constructor(channelState: { [key: string]: Context[] }, initialChannelId?: string) {\n    super({ appId: 'cucumber-app', instanceId: 'cucumber-instance' });\n\n    this.channelState = channelState;\n    this.automaticResponses = [\n      new FindIntent(),\n      new FindIntentByContext(),\n      new RaiseIntent(),\n      new RaiseIntentForContext(),\n      new IntentResult(),\n      new GetAppMetadata(),\n      new GetInfo(),\n      new FindInstances(),\n      new Open(),\n      new GetOrCreateChannel(),\n      new ChannelState(this.channelState, initialChannelId),\n      new GetUserChannels(),\n      new RegisterListeners(),\n      new UnsubscribeListeners(),\n      new CreatePrivateChannel(),\n      new DisconnectPrivateChannel(),\n      new AddEventListener(),\n    ];\n  }\n\n  createUUID(): string {\n    return uuidv4();\n  }\n\n  getTimeoutMs(): number {\n    return 1000;\n  }\n\n  async disconnect(): Promise<void> {\n    //Theres no explicit disconnect call for the DA in FDC3, but the DesktopAgentProxy implementation includes one that is called to pagehide\n    const bye: WebConnectionProtocol6Goodbye = {\n      type: 'WCP6Goodbye',\n      meta: {\n        timestamp: new Date(),\n      },\n    };\n    await this.post(bye);\n  }\n\n  post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void> {\n    this.allPosts.push(message);\n\n    if (message.type != 'WCP6Goodbye') {\n      for (let i = 0; i < this.automaticResponses.length; i++) {\n        const ar = this.automaticResponses[i];\n        if (ar.filter(message.type)) {\n          return ar.action(message, this);\n        }\n      }\n    }\n\n    return Promise.resolve();\n  }\n\n  addAppIntentDetail(id: IntentDetail) {\n    this.intentDetails.push(id);\n  }\n\n  register(l: RegisterableListener) {\n    if (l.id == null) {\n      throw new Error('Listener must have ID set');\n    } else {\n      this.listeners.set(l.id, l);\n    }\n  }\n\n  unregister(id: string) {\n    this.listeners.delete(id);\n  }\n\n  createMeta() {\n    return {\n      requestUuid: this.createUUID(),\n      timestamp: new Date(),\n      source: this.getAppIdentifier(),\n    };\n  }\n\n  /**\n   * Used in testing steps\n   */\n  createResponseMeta() {\n    return {\n      ...this.createMeta(),\n      responseUuid: this.createUUID(),\n    };\n  }\n\n  /**\n   * Used in testing steps\n   */\n  createEventMeta() {\n    return {\n      ...this.createMeta(),\n      eventUuid: this.createUUID(),\n    };\n  }\n\n  receive(m: AgentResponseMessage | AgentEventMessage, log?: (s: string) => void) {\n    this.listeners.forEach((v, k) => {\n      if (v.filter(m)) {\n        if (log) {\n          log('Processing in ' + k);\n        }\n        v.action(m);\n      } else {\n        if (log) {\n          log('Ignoring in ' + k);\n        }\n      }\n    });\n  }\n\n  private ir: PossibleIntentResult | null = null;\n\n  getIntentResult() {\n    return this.ir;\n  }\n\n  setIntentResult(o: PossibleIntentResult) {\n    this.ir = o;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/AddEventListener.ts",
    "content": "import { AutomaticResponse, TestMessaging } from '../TestMessaging';\nimport { createResponseMeta } from './support';\nimport { AddEventListenerRequest, AddEventListenerResponse } from '@finos/fdc3-schema/generated/api/BrowserTypes.js';\n\nexport class AddEventListener implements AutomaticResponse {\n  count: number = 0;\n\n  filter(t: string) {\n    return t == 'addEventListenerRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createResponse(input as AddEventListenerRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: AddEventListenerRequest): AddEventListenerResponse {\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'addEventListenerResponse',\n      payload: {\n        listenerUUID: 'listener-' + this.count++,\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/ChannelState.ts",
    "content": "import { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { Context } from '@finos/fdc3-context';\nimport { createResponseMeta } from './support.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  AddContextListenerRequest,\n  AddContextListenerResponse,\n  AgentResponseMessage,\n  AppRequestMessage,\n  BroadcastRequest,\n  BroadcastResponse,\n  ContextListenerUnsubscribeRequest,\n  ContextListenerUnsubscribeResponse,\n  GetCurrentChannelRequest,\n  GetCurrentChannelResponse,\n  GetCurrentContextRequest,\n  GetCurrentContextResponse,\n  JoinUserChannelRequest,\n  JoinUserChannelResponse,\n  LeaveCurrentChannelRequest,\n  LeaveCurrentChannelResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class ChannelState implements AutomaticResponse {\n  private channelId: string | null = null;\n  private listeners: { [channel: string]: string[] } = {};\n  private contextHistory: { [channel: string]: Context[] } = {};\n\n  constructor(contextHistory: { [channel: string]: Context[] }, initialChannelId?: string) {\n    this.contextHistory = contextHistory;\n    this.channelId = initialChannelId ?? null;\n  }\n\n  filter(t: string) {\n    return (\n      t == 'broadcastRequest' ||\n      t == 'joinUserChannelRequest' ||\n      t == 'leaveCurrentChannelRequest' ||\n      t == 'getCurrentChannelRequest' ||\n      t == 'addContextListenerRequest' ||\n      t == 'contextListenerUnsubscribeRequest' ||\n      t == 'getCurrentContextRequest'\n    );\n  }\n\n  action(input: AppRequestMessage, m: TestMessaging) {\n    let out: AgentResponseMessage | null = null;\n    switch (input.type) {\n      case 'joinUserChannelRequest':\n        out = this.createJoinResponse(input);\n        break;\n      case 'leaveCurrentChannelRequest':\n        out = this.createLeaveResponse(input);\n        break;\n\n      case 'getCurrentChannelRequest':\n        out = this.createGetChannelResponse(input);\n        break;\n\n      case 'addContextListenerRequest':\n        out = this.createAddListenerResponse(input);\n        break;\n\n      case 'contextListenerUnsubscribeRequest':\n        out = this.createUnsubscribeResponse(input);\n        break;\n\n      case 'getCurrentContextRequest':\n        out = this.createGetContextResponse(input);\n        break;\n\n      case 'broadcastRequest':\n        out = this.createBroadcastResponse(input);\n        break;\n    }\n\n    if (out) {\n      setTimeout(() => {\n        m.receive(out!);\n      }, 100);\n    }\n    return Promise.resolve();\n  }\n\n  private createBroadcastResponse(i: BroadcastRequest): BroadcastResponse {\n    const channel = i.payload.channelId;\n    const context = i.payload.context;\n    this.contextHistory[channel] = this.contextHistory[channel] ?? [];\n    this.contextHistory[channel].unshift(context);\n\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'broadcastResponse',\n      payload: {},\n    };\n  }\n\n  private createJoinResponse(i: JoinUserChannelRequest): JoinUserChannelResponse {\n    if (i.payload.channelId == 'nonexistent') {\n      return {\n        meta: createResponseMeta(i.meta),\n        type: 'joinUserChannelResponse',\n        payload: {\n          error: 'NoChannelFound',\n        },\n      };\n    } else {\n      this.channelId = i.payload.channelId;\n      return {\n        meta: createResponseMeta(i.meta),\n        type: 'joinUserChannelResponse',\n        payload: {},\n      };\n    }\n  }\n\n  private createGetContextResponse(input: GetCurrentContextRequest): GetCurrentContextResponse {\n    const ch = input.payload.channelId;\n    let last: Context | undefined;\n    const contexts = this.contextHistory[ch] ?? [];\n    if (input.payload.contextType) {\n      last = contexts.find(c => c.type == input.payload.contextType);\n    } else {\n      last = contexts.length > 0 ? contexts[0] : undefined;\n    }\n    return {\n      meta: createResponseMeta(input.meta),\n      type: 'getCurrentContextResponse',\n      payload: {\n        context: last ?? null,\n      },\n    };\n  }\n\n  private createLeaveResponse(i: LeaveCurrentChannelRequest): LeaveCurrentChannelResponse {\n    this.channelId = null;\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'leaveCurrentChannelResponse',\n      payload: {},\n    };\n  }\n\n  private createAddListenerResponse(i: AddContextListenerRequest): AddContextListenerResponse {\n    const id = uuidv4();\n\n    if (this.channelId) {\n      const list = this.listeners[this.channelId] ?? [];\n      list.push(id);\n      this.listeners[this.channelId] = list;\n    }\n\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'addContextListenerResponse',\n      payload: {\n        listenerUUID: id,\n      },\n    };\n  }\n\n  private createUnsubscribeResponse(i: ContextListenerUnsubscribeRequest): ContextListenerUnsubscribeResponse {\n    const id = i.payload.listenerUUID;\n    Object.keys(this.listeners).forEach(k => {\n      this.listeners[k] = this.listeners[k].filter(v => v != id);\n    });\n\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'contextListenerUnsubscribeResponse',\n      payload: {},\n    };\n  }\n\n  private createGetChannelResponse(i: GetCurrentChannelRequest): GetCurrentChannelResponse {\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'getCurrentChannelResponse',\n      payload: {\n        channel: this.channelId\n          ? {\n              id: this.channelId,\n              type: 'user',\n              displayMetadata: {\n                name: 'The ' + this.channelId + ' channel',\n                color: 'red',\n                glyph: 'triangle',\n              },\n            }\n          : null,\n      },\n    } as GetCurrentChannelResponse;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/CreatePrivateChannel.ts",
    "content": "import {\n  CreatePrivateChannelRequest,\n  CreatePrivateChannelResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport class CreatePrivateChannel implements AutomaticResponse {\n  count: number = 0;\n\n  filter(t: string) {\n    return t == 'createPrivateChannelRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createResponse(input as CreatePrivateChannelRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: CreatePrivateChannelRequest): CreatePrivateChannelResponse {\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'createPrivateChannelResponse',\n      payload: {\n        privateChannel: {\n          id: uuidv4(),\n          type: 'private',\n          displayMetadata: {\n            name: 'Private Channel' + this.count++,\n            color: 'blue',\n            glyph: 'circle',\n          },\n        },\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/DisconnectPrivateChannel.ts",
    "content": "import { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\nimport {\n  PrivateChannelDisconnectRequest,\n  PrivateChannelDisconnectResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class DisconnectPrivateChannel implements AutomaticResponse {\n  count: number = 0;\n\n  filter(t: string) {\n    return t == 'privateChannelDisconnectRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createResponse(input as PrivateChannelDisconnectRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: PrivateChannelDisconnectRequest): PrivateChannelDisconnectResponse {\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'privateChannelDisconnectResponse',\n      payload: {},\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/FindInstances.ts",
    "content": "import { FindInstancesRequest, FindInstancesResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\n\nexport class FindInstances implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'findInstancesRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createFindInstancesResponse(input as FindInstancesRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createFindInstancesResponse(m: FindInstancesRequest): FindInstancesResponse {\n    return {\n      meta: createResponseMeta(m.meta),\n      type: 'findInstancesResponse',\n      payload: {\n        appIdentifiers: [\n          { appId: 'One', instanceId: '1' },\n          { appId: 'Two', instanceId: '2' },\n          { appId: 'Three', instanceId: '3' },\n        ],\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/FindIntent.ts",
    "content": "import { AppMetadata } from '@finos/fdc3-standard';\nimport { AutomaticResponse, IntentDetail, TestMessaging, intentDetailMatches } from '../TestMessaging.js';\nimport {\n  AppRequestMessage,\n  FindIntentRequest,\n  FindIntentResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { createResponseMeta } from './support.js';\n\nexport class FindIntent implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'findIntentRequest';\n  }\n\n  action(input: AppRequestMessage, m: TestMessaging) {\n    const intentRequest = input as FindIntentRequest;\n    const payload = intentRequest.payload;\n    const intent = payload.intent;\n    const context = payload.context?.type;\n    const resultType = payload.resultType;\n    const template: IntentDetail = {\n      intent,\n      context,\n      resultType,\n    };\n\n    const relevant = m.intentDetails.filter(id => intentDetailMatches(id, template, false));\n    const response = this.createFindIntentResponseMessage(intentRequest, relevant);\n    //TODO: annotate why this timeout is needed\n    setTimeout(() => {\n      m.receive(response);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createFindIntentResponseMessage(m: FindIntentRequest, relevant: IntentDetail[]): FindIntentResponse {\n    return {\n      meta: createResponseMeta(m.meta),\n      type: 'findIntentResponse',\n      payload: {\n        appIntent: {\n          apps: relevant.reduce<AppMetadata[]>((filtered: AppMetadata[], r) => {\n            if (r?.app?.appId) {\n              filtered.push({\n                appId: r.app?.appId,\n                instanceId: r.app?.instanceId,\n              });\n            }\n            return filtered;\n          }, []),\n          intent: {\n            displayName: m.payload.intent,\n            name: m.payload.intent,\n          },\n        },\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/FindIntentByContext.ts",
    "content": "import {\n  FindIntentsByContextRequest,\n  FindIntentsByContextResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, IntentDetail, TestMessaging, intentDetailMatches } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\n\nexport class FindIntentByContext implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'findIntentsByContextRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const intentRequest = input as FindIntentsByContextRequest;\n    const payload = intentRequest.payload;\n    const context = payload?.context?.type;\n    const template: IntentDetail = {\n      context,\n    };\n\n    const relevant = m.intentDetails.filter(id => intentDetailMatches(id, template, true));\n    const request = this.createFindIntentsByContextResponseMessage(intentRequest, relevant);\n    setTimeout(() => {\n      m.receive(request);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createFindIntentsByContextResponseMessage(\n    m: FindIntentsByContextRequest,\n    relevant: IntentDetail[]\n  ): FindIntentsByContextResponse {\n    //get unique intent names\n    const relevantIntents = [\n      ...new Set<string>(\n        relevant.reduce<string[]>((filtered: string[], r) => {\n          if (r.intent) {\n            filtered.push(r.intent);\n          }\n          return filtered;\n        }, [])\n      ),\n    ];\n\n    return {\n      meta: createResponseMeta(m.meta),\n      type: 'findIntentsByContextResponse',\n      payload: {\n        appIntents: relevantIntents.map(i => {\n          return {\n            intent: { name: i, displayName: i },\n            apps: relevant.filter(r => r.intent === i && r.app).map(r => r.app!),\n          };\n        }),\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/GetAppMetadata.ts",
    "content": "import { GetAppMetadataRequest, GetAppMetadataResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\n\nexport class GetAppMetadata implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getAppMetadataRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createMetadataResponseMessage(input as GetAppMetadataRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createMetadataResponseMessage(m: GetAppMetadataRequest): GetAppMetadataResponse {\n    return {\n      meta: createResponseMeta(m.meta),\n      type: 'getAppMetadataResponse',\n      payload: {\n        appMetadata: {\n          appId: m.payload.app.appId,\n          name: 'Metadata Name',\n          description: 'Metadata Description',\n        },\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/GetInfo.ts",
    "content": "import { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\nimport { GetInfoRequest, GetInfoResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class GetInfo implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getInfoRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createInfoResponseMessage(input as GetInfoRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createInfoResponseMessage(m: GetInfoRequest): GetInfoResponse {\n    return {\n      meta: createResponseMeta(m.meta),\n      type: 'getInfoResponse',\n      payload: {\n        implementationMetadata: {\n          appMetadata: {\n            appId: 'cucumber-app',\n            instanceId: 'cucumber-instance',\n          },\n          fdc3Version: '2.0',\n          optionalFeatures: {\n            DesktopAgentBridging: false,\n            OriginatingAppMetadata: true,\n            UserChannelMembershipAPIs: true,\n          },\n          provider: 'cucumber-provider',\n          providerVersion: 'test',\n        },\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/GetOrCreateChannel.ts",
    "content": "import { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { ChannelError } from '@finos/fdc3-standard';\nimport { createResponseMeta } from './support.js';\nimport {\n  AppRequestMessage,\n  GetOrCreateChannelRequest,\n  GetOrCreateChannelResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype ChannelType = { [channelId: string]: 'user' | 'app' | 'private' };\n\nexport class GetOrCreateChannel implements AutomaticResponse {\n  private type: ChannelType = {};\n\n  filter(t: string) {\n    return t == 'getOrCreateChannelRequest';\n  }\n\n  action(input: AppRequestMessage, m: TestMessaging) {\n    const out = this.registerChannel(input as GetOrCreateChannelRequest);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  registerChannel(r: GetOrCreateChannelRequest): GetOrCreateChannelResponse {\n    const id = r.payload.channelId;\n    const type = 'app';\n\n    const existingType = this.type[id];\n\n    if (existingType && existingType != type) {\n      // channel already exists\n      return {\n        type: 'getOrCreateChannelResponse',\n        meta: createResponseMeta(r.meta),\n        payload: {\n          error: ChannelError.AccessDenied,\n        },\n      };\n    } else {\n      this.type[id] = type;\n      return {\n        type: 'getOrCreateChannelResponse',\n        meta: createResponseMeta(r.meta),\n        payload: {\n          channel: {\n            id,\n            type,\n            displayMetadata: {\n              name: 'The ' + id + ' Channel',\n              color: 'cerulean blue',\n              glyph: 'triangle',\n            },\n          },\n        },\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/GetUserChannels.ts",
    "content": "import {\n  Channel,\n  GetUserChannelsRequest,\n  GetUserChannelsResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\n\nexport class GetUserChannels implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getUserChannelsRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createResponse(input as GetUserChannelsRequest, m);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: GetUserChannelsRequest, m: TestMessaging): GetUserChannelsResponse {\n    const userChannels: Channel[] = Object.keys(m.channelState).map(c => {\n      const aChannel: Channel = {\n        id: c,\n        type: 'user',\n        displayMetadata: {\n          name: 'The ' + c + ' channel',\n          color: 'red',\n          glyph: 'triangle',\n        },\n      };\n      return aChannel;\n    });\n\n    return {\n      meta: createResponseMeta(i.meta),\n      type: 'getUserChannelsResponse',\n      payload: {\n        userChannels,\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/IntentResult.ts",
    "content": "import { IntentResultRequest, IntentResultResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\n\nexport class IntentResult implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'intentResultRequest';\n  }\n\n  createIntentResultResponseMessage(intentRequest: IntentResultRequest, m: TestMessaging): IntentResultResponse {\n    const out: IntentResultResponse = {\n      meta: {\n        ...intentRequest.meta,\n        responseUuid: m.createUUID(),\n      },\n      payload: {},\n      type: 'intentResultResponse',\n    };\n\n    return out;\n  }\n\n  action(input: object, m: TestMessaging) {\n    const intentRequest = input as IntentResultRequest;\n    const payload = intentRequest.payload;\n\n    m.setIntentResult(payload.intentResult);\n\n    // next, send the result response\n    const out2 = this.createIntentResultResponseMessage(intentRequest, m);\n    setTimeout(() => {\n      m.receive(out2);\n    }, 100);\n    return Promise.resolve();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/Open.ts",
    "content": "import { OpenRequest, OpenResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\n\nexport class Open implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'openRequest';\n  }\n\n  action(input: object, m: TestMessaging) {\n    const out = this.createOpenResponse(input as OpenRequest, m);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createOpenResponse(m: OpenRequest, tm: TestMessaging): OpenResponse {\n    const found = tm.intentDetails.find(id => id.app?.appId == m.payload.app.appId);\n\n    if (found && found.app) {\n      return {\n        meta: createResponseMeta(m.meta),\n        type: 'openResponse',\n        payload: {\n          appIdentifier: {\n            appId: found.app.appId,\n            instanceId: 'abc123',\n          },\n        },\n      } as OpenResponse;\n    } else {\n      return {\n        meta: createResponseMeta(m.meta),\n        type: 'openResponse',\n        payload: {\n          error: 'AppNotFound',\n        },\n      } as OpenResponse;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/RaiseIntent.ts",
    "content": "import {\n  RaiseIntentRequest,\n  RaiseIntentResponse,\n  RaiseIntentResultResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, IntentDetail, intentDetailMatches, TestMessaging } from '../TestMessaging.js';\nimport { AppMetadata, ResolveError } from '@finos/fdc3-standard';\nimport { createResponseMeta } from './support.js';\n\nexport class RaiseIntent implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'raiseIntentRequest';\n  }\n\n  createCannedRaiseIntentResponseMessage(intentRequest: RaiseIntentRequest, m: TestMessaging): RaiseIntentResponse {\n    const result = m.getIntentResult();\n\n    if (result && result.error) {\n      const out: RaiseIntentResponse = {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        payload: {\n          error: result.error,\n        },\n        type: 'raiseIntentResponse',\n      };\n\n      return out;\n    } else if (result) {\n      const out: RaiseIntentResponse = {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        payload: {\n          intentResolution: {\n            intent: intentRequest.payload.intent,\n            source: {\n              appId: 'some-app',\n              instanceId: 'abc123',\n            },\n          },\n        },\n        type: 'raiseIntentResponse',\n      };\n\n      return out;\n    } else {\n      throw new Error('TestMessaging did not return an IntentResult');\n    }\n  }\n\n  private createRaiseIntentResponseMessage(\n    intentRequest: RaiseIntentRequest,\n    relevant: IntentDetail[],\n    m: TestMessaging\n  ): RaiseIntentResponse {\n    if (relevant.length == 0) {\n      return {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        type: 'raiseIntentResponse',\n        payload: {\n          error: ResolveError.NoAppsFound,\n        },\n      };\n    } else if (relevant.length == 1 && relevant[0].intent && relevant[0].app) {\n      return {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        type: 'raiseIntentResponse',\n        payload: {\n          intentResolution: {\n            intent: relevant[0].intent,\n            source: relevant[0].app,\n          },\n        },\n      };\n    } else if (relevant.length > 0) {\n      return {\n        meta: createResponseMeta(intentRequest.meta),\n        type: 'raiseIntentResponse',\n        payload: {\n          appIntent: {\n            apps: relevant.reduce<AppMetadata[]>((filtered, r) => {\n              if (r.app?.appId) {\n                filtered.push({\n                  appId: r.app.appId,\n                  instanceId: r.app.instanceId,\n                });\n              }\n              return filtered;\n            }, []),\n            intent: {\n              displayName: intentRequest.payload.intent,\n              name: intentRequest.payload.intent,\n            },\n          },\n        },\n      };\n    } else {\n      throw new Error('createRaiseIntentResponseMessage did not produce a valid result!');\n    }\n  }\n\n  createRaiseIntentResultResponseMessage(\n    intentRequest: RaiseIntentRequest,\n    m: TestMessaging\n  ): RaiseIntentResultResponse | undefined {\n    const result = m.getIntentResult();\n    if (result?.error) {\n      return undefined;\n    } else if (result) {\n      const out: RaiseIntentResultResponse = {\n        meta: createResponseMeta(intentRequest.meta),\n        payload: {\n          intentResult: result,\n        },\n        type: 'raiseIntentResultResponse',\n      };\n\n      return out;\n    } else {\n      return;\n    }\n  }\n\n  action(input: object, m: TestMessaging) {\n    const intentRequest = input as RaiseIntentRequest;\n    const payload = intentRequest.payload;\n    const intent = payload.intent;\n    const context = payload?.context?.type;\n\n    if (m.getIntentResult() == undefined) {\n      // we're going to figure out the right response based on the app details (a la FindIntent)\n      const app = payload?.app;\n      const using: IntentDetail = {\n        intent,\n        context,\n        app,\n      };\n\n      const relevant = m.intentDetails.filter(id => intentDetailMatches(id, using, false));\n      const request = this.createRaiseIntentResponseMessage(intentRequest, relevant, m);\n      setTimeout(() => {\n        m.receive(request);\n      }, 100);\n    } else if (!m.getIntentResult()?.timeout) {\n      // this sends out the pre-set intent resolution\n      const out1 = this.createCannedRaiseIntentResponseMessage(intentRequest, m);\n      setTimeout(() => {\n        m.receive(out1);\n      }, 100);\n\n      // next, send the result response\n      const out2 = this.createRaiseIntentResultResponseMessage(intentRequest, m);\n      if (out2) {\n        setTimeout(() => {\n          m.receive(out2);\n        }, 300);\n      }\n    }\n    return Promise.resolve();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/RaiseIntentForContext.ts",
    "content": "import {\n  RaiseIntentForContextRequest,\n  RaiseIntentForContextResponse,\n  RaiseIntentResultResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, IntentDetail, intentDetailMatches, TestMessaging } from '../TestMessaging.js';\nimport { AppIdentifier, AppIntent, ResolveError } from '@finos/fdc3-standard';\nimport { createResponseMeta } from './support.js';\n\nexport class RaiseIntentForContext implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'raiseIntentForContextRequest';\n  }\n\n  createCannedRaiseIntentForContextResponseMessage(\n    intentRequest: RaiseIntentForContextRequest,\n    m: TestMessaging\n  ): RaiseIntentForContextResponse {\n    const result = m.getIntentResult();\n    if (result && result.error) {\n      const out: RaiseIntentForContextResponse = {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        payload: {\n          error: result.error,\n        },\n        type: 'raiseIntentForContextResponse',\n      };\n\n      return out;\n    } else {\n      const out: RaiseIntentForContextResponse = {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        payload: {\n          intentResolution: {\n            intent: 'some-canned-intent',\n            source: {\n              appId: 'some-app',\n              instanceId: 'abc123',\n            },\n          },\n        },\n        type: 'raiseIntentForContextResponse',\n      };\n\n      return out;\n    }\n  }\n\n  private createRaiseIntentForContextResponseMessage(\n    intentRequest: RaiseIntentForContextRequest,\n    relevant: IntentDetail[],\n    m: TestMessaging\n  ): RaiseIntentForContextResponse {\n    if (relevant.length == 0) {\n      return {\n        meta: createResponseMeta(intentRequest.meta),\n        type: 'raiseIntentForContextResponse',\n        payload: {\n          error: ResolveError.NoAppsFound,\n        },\n      };\n    } else if (relevant.length == 1 && relevant[0].intent && relevant[0].app) {\n      return {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        type: 'raiseIntentForContextResponse',\n        payload: {\n          intentResolution: {\n            intent: relevant[0].intent,\n            source: relevant[0].app,\n          },\n        },\n      };\n    } else if (relevant.length > 0) {\n      //get unique intent names\n      const relevantIntents = [\n        ...new Set<string>(\n          relevant.reduce<string[]>((filtered: string[], r) => {\n            if (r.intent) {\n              filtered.push(r.intent);\n            }\n            return filtered;\n          }, [])\n        ),\n      ];\n      const appIntents = relevantIntents.map<AppIntent>(i => {\n        return {\n          intent: { name: i, displayName: i },\n          apps: relevant.reduce<AppIdentifier[]>((filtered: AppIdentifier[], r) => {\n            if (r.intent === i && r.app) {\n              filtered.push(r.app);\n            }\n            return filtered;\n          }, []),\n        };\n      });\n\n      return {\n        meta: createResponseMeta(intentRequest.meta),\n        type: 'raiseIntentForContextResponse',\n        payload: {\n          appIntents: appIntents,\n        },\n      };\n    } else {\n      throw new Error('createRaiseIntentForContextResponseMessage did not produce a valid result!');\n    }\n  }\n\n  createRaiseIntentResultResponseMessage(\n    intentRequest: RaiseIntentForContextRequest,\n    m: TestMessaging\n  ): RaiseIntentResultResponse | undefined {\n    const result = m.getIntentResult();\n    if (result && result.error) {\n      return undefined;\n    } else if (result) {\n      const out: RaiseIntentResultResponse = {\n        meta: {\n          ...intentRequest.meta,\n          responseUuid: m.createUUID(),\n        },\n        payload: {\n          intentResult: result,\n        },\n        type: 'raiseIntentResultResponse',\n      };\n\n      return out;\n    } else {\n      throw new Error('');\n    }\n  }\n\n  action(input: object, m: TestMessaging) {\n    const intentRequest = input as RaiseIntentForContextRequest;\n    const payload = intentRequest.payload;\n    const context = payload?.context?.type;\n\n    if (m.getIntentResult() == undefined) {\n      // we're going to figure out the right response based on the app details (a la FindIntent)\n      const app = payload?.app;\n      const using: IntentDetail = {\n        context,\n        app,\n      };\n\n      const relevant = m.intentDetails.filter(id => intentDetailMatches(id, using, false));\n      const request = this.createRaiseIntentForContextResponseMessage(intentRequest, relevant, m);\n      setTimeout(() => {\n        m.receive(request);\n      }, 100);\n    } else if (!m.getIntentResult()?.timeout) {\n      // this sends out the pre-set intent resolution\n      const out1 = this.createCannedRaiseIntentForContextResponseMessage(intentRequest, m);\n      setTimeout(() => {\n        m.receive(out1);\n      }, 100);\n\n      // next, send the result response\n      const out2 = this.createRaiseIntentResultResponseMessage(intentRequest, m);\n      if (out2) {\n        setTimeout(() => {\n          m.receive(out2);\n        }, 300);\n      }\n    }\n\n    return Promise.resolve();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/RegisterListeners.ts",
    "content": "import {\n  AddContextListenerRequest,\n  AddContextListenerResponse,\n  AddEventListenerRequest,\n  AddEventListenerResponse,\n  AddIntentListenerRequest,\n  AddIntentListenerResponse,\n  AppRequestMessage,\n  PrivateChannelAddEventListenerRequest,\n  PrivateChannelAddEventListenerResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\nimport { v4 as uuidv4 } from 'uuid';\n\ntype Requests =\n  | AddContextListenerRequest\n  | AddIntentListenerRequest\n  | AddEventListenerRequest\n  | PrivateChannelAddEventListenerRequest;\ntype Responses =\n  | AddContextListenerResponse\n  | AddIntentListenerResponse\n  | AddEventListenerResponse\n  | PrivateChannelAddEventListenerResponse;\n\nexport class RegisterListeners implements AutomaticResponse {\n  filter(t: string) {\n    return (\n      t == 'addContextListenerRequest' ||\n      t == 'addIntentListenerRequest' ||\n      t == 'addEventListenerRequest' ||\n      t == 'privateChannelAddEventListenerRequest'\n    );\n  }\n\n  action(input: AppRequestMessage, m: TestMessaging) {\n    const out = this.createResponse(input as Requests);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: Requests): Responses {\n    return {\n      meta: createResponseMeta(i.meta),\n      //TODO: use a typesafe method of creating response messages\n      type: i.type.replace('Request', 'Response') as Responses['type'],\n      payload: {\n        listenerUUID: uuidv4(),\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/UnsubscribeListeners.ts",
    "content": "import {\n  AppRequestMessage,\n  ContextListenerUnsubscribeRequest,\n  ContextListenerUnsubscribeResponse,\n  EventListenerUnsubscribeRequest,\n  IntentListenerUnsubscribeRequest,\n  IntentListenerUnsubscribeResponse,\n  PrivateChannelUnsubscribeEventListenerRequest,\n  PrivateChannelUnsubscribeEventListenerResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AutomaticResponse, TestMessaging } from '../TestMessaging.js';\nimport { createResponseMeta } from './support.js';\nimport { EventListenerUnsubscribeResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype Requests =\n  | IntentListenerUnsubscribeRequest\n  | PrivateChannelUnsubscribeEventListenerRequest\n  | ContextListenerUnsubscribeRequest\n  | EventListenerUnsubscribeRequest;\ntype Responses =\n  | IntentListenerUnsubscribeResponse\n  | PrivateChannelUnsubscribeEventListenerResponse\n  | ContextListenerUnsubscribeResponse\n  | EventListenerUnsubscribeResponse;\n\nexport class UnsubscribeListeners implements AutomaticResponse {\n  filter(t: string) {\n    return (\n      t == 'intentListenerUnsubscribeRequest' ||\n      t == 'privateChannelUnsubscribeEventListenerRequest' ||\n      t == 'contextListenerUnsubscribeRequest' ||\n      t == 'eventListenerUnsubscribeRequest'\n    );\n  }\n\n  action(input: AppRequestMessage, m: TestMessaging) {\n    const out = this.createResponse(input as Requests);\n\n    setTimeout(() => {\n      m.receive(out);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: Requests): Responses {\n    return {\n      meta: createResponseMeta(i.meta),\n      type: i.type.replace('Request', 'Response') as Responses['type'],\n      payload: {},\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/support/responses/support.ts",
    "content": "import { AppRequestMessageMeta, AgentResponseMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport function createResponseMeta(m: AppRequestMessageMeta): AgentResponseMessage['meta'] {\n  const meta: AgentResponseMessage['meta'] = {\n    requestUuid: m.requestUuid,\n    responseUuid: uuidv4(),\n    source: m.source,\n    timestamp: new Date(),\n  };\n  return meta;\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/test/world/index.ts",
    "content": "import { TestMessaging } from '../support/TestMessaging.js';\nimport { QuickPickleWorld, QuickPickleWorldInterface } from 'quickpickle';\n\nexport interface CustomWorldInterface extends QuickPickleWorldInterface {\n  props: Record<string, any>;\n  messaging: TestMessaging | null;\n  log: (message: string) => void;\n}\n\nexport class CustomWorld extends QuickPickleWorld implements CustomWorldInterface {\n  props: Record<string, any> = {};\n  messaging: TestMessaging | null = null;\n\n  log(message: string): void {\n    console.log(message);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-agent-proxy/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.root.json\",\n  \"compilerOptions\": {\n    \"rootDirs\": [\n      \"src\",\n      \"test\"\n    ],\n    \"outDir\": \"dist\",\n  },\n  \"include\": [\n    \"src\"\n  ],\n  \"exclude\": [\n    \"test/**\",\n    \"dist/**\"\n  ],\n  \"references\": [\n    {\n      \"path\": \"../fdc3-standard\"\n    },\n    {\n      \"path\": \"../fdc3-schema\"\n    },\n    {\n      \"path\": \"../fdc3-context\"\n    },\n    {\n      \"path\": \"../testing\"\n    },\n    {\n      \"path\": \"../fdc3-context\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-agent-proxy/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\nimport { quickpickle } from 'quickpickle';\n\nexport default defineConfig({\n  plugins: [\n    quickpickle({\n      stepTimeout: 15000,\n    }),\n  ],\n  test: {\n    include: ['test/features/**/*.feature'],\n    setupFiles: ['test/steps.ts'],\n    testTimeout: 30000,\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n    coverage: {\n      enabled: true,\n      provider: 'v8',\n      reporter: ['text', 'lcov', 'json'],\n      reportsDirectory: './coverage',\n      include: ['src/**/*.ts'],\n      exclude: ['src/**/*.d.ts', 'src/**/*.test.ts', 'src/**/*.spec.ts'],\n    },\n  },\n});\n"
  },
  {
    "path": "packages/fdc3-commonjs/README.md",
    "content": "# FDC3 CommonJS Module\n\nThis is the CommonJS module version of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) javascript API. \n\n## Warning\n\nCommonJS is no longer the recommended module system for JavaScript. We recommend using the FDC3 ES6 module at `@finos/fdc3` instead. The FDC3 CommonJS module is provided for compatibility with older projects that use CommonJS.\n\n## Installation\n\nTo install the FDC3 CommonJS module, use npm:\n\n```bash\nnpm install @finos/fdc3-commonjs\n```\n\n## Usage\n\nTo use the FDC3 CommonJS module in your project, require it as follows:\n\n```javascript\nconst fdc3CommonJs = require('@finos/fdc3-commonjs');\n\n// getAgent() returns the FDC3 Desktop Agent\nconst fdc3 = fdc3CommonJs.getAgent();\n\n// Example usage\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n};\n\nfdc3.raiseIntent('ViewProfile', contact);\n```\n\n## Documentation\n\nFor detailed documentation and API reference, please visit the [official FDC3 documentation](https://fdc3.finos.org/docs/api/overview).\n\n## Contributing\n\nWe welcome contributions to the FDC3 project. Please see our [contributing guidelines](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for more information.\n\n## License\n\nThis project is licensed under the [Apache 2.0 License](LICENSE).\n\n## Contact\n\nFor any questions or support, please reach out to the FDC3 community on our [Slack channel](https://finos-lf.slack.com/archives/CJ8Q8H4Q1) or [mailing list](mailto:fdc3@finos.org).\n\n## Further Details\n - https://github.com/finos/FDC3\n - [FDC3 Specification](https://fdc3.finos.org/)\n - Main FDC3 module: https://www.npmjs.com/package/@finos/fdc3\n"
  },
  {
    "path": "packages/fdc3-commonjs/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-commonjs\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"require\": \"./dist/index.cjs\",\n    \"import\": \"./dist/index.cjs\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"clean\": \"npx rimraf dist\",\n    \"build\": \"npx rollup -c rollup.config.mjs\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3\": \"2.2.2\"\n  },\n  \"devDependencies\": {\n    \"@rollup/plugin-commonjs\": \"^28.0.1\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^15.3.0\",\n    \"@rollup/plugin-typescript\": \"^12.1.1\",\n    \"rollup\": \"^4.59.0\",\n    \"rollup-plugin-dts\": \"^6.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-commonjs/rollup.config.mjs",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport json from '@rollup/plugin-json';\nimport { dts } from 'rollup-plugin-dts';\n\nexport default [\n  {\n    input: 'src/index.ts',\n\n    // Property inherited from TSDX. To understand what this is doing, see comments:\n    // https://github.com/jaredpalmer/tsdx/blob/master/src/createRollupConfig.ts#L77\n    treeshake: {\n      propertyReadSideEffects: false,\n    },\n\n    output: {\n      file: 'dist/index.cjs',\n      format: 'cjs',\n      freeze: false,\n      esModule: false,\n      sourcemap: true,\n      exports: 'named',\n    },\n\n    plugins: [\n      nodeResolve(),\n      commonjs({\n        // use a regex to make sure to include eventual hoisted packages (RM:  what is this?)\n        include: /\\/regenerator-runtime\\//,\n      }),\n      json(),\n    ],\n  },\n  {\n    input: './src/index.ts',\n    output: [{ file: 'dist/index.d.ts', format: 'es' }],\n    plugins: [dts({ respectExternal: true })],\n  },\n];\n"
  },
  {
    "path": "packages/fdc3-commonjs/src/index.ts",
    "content": "export * from '@finos/fdc3';\n"
  },
  {
    "path": "packages/fdc3-context/README.md",
    "content": "# Context types generation README\n\nThis folder contains Typescript interfaces, in ContextTypes.ts generated from the context JSONSchema (https://json-schema.org/) files via quicktype (https://quicktype.io/).\n\nPlease note that these definitions are provided to help developers working in TypeScript to produce valid context objects - but should not be considered the 'source of truth' for context definitions (instead look to the schemas and documentation). Source files may also be generated for us in other languages supported by quicktype.\n\nIt is not always possible to perfectly replicate a type/interface defined in JSONSchema via TypeScript. Hence, in the event of any disagreement between the definitions, the JSONSchema should be assumed to be correct, rather than the Typescript. For example, JSONSchema may define optional fields on an object + a restriction on the type of additional properties (via `\"additionalProperties\": { \"type\": \"string\"}`), which will result in an index signature `[property: string]: string;` in generated TypeScript. That signature, is incompatible with with an optional properties (including string properties) as they have type `string | undefined`. A similar problem may occur in JSON Schema if the schema is used to create a subtype via composition as `additionalProperties` is not aware of teh subschema's definitions. Both issues can be worked around by using `unevaluatedProperties` in the schema, which will defer to the declared type of the optional property in the subschema, but is also currently ignored by quicktype - resulting in a type that will compile, but doesn't restrict the type of optional property values as defined in the schema.\n\nFurther, quicktype doesn't always perfectly replicate polymorphic fields specified with `oneOf` in JSONSchema as it will usually merge the different objects into a single type (where fields not in one of the constituent schemas become optional) rather than creating a union type. In such situations, the type produced is usable (has all the necessary fields) but may allow the construction of invalid instances which are missing required properties or include properties from the multiple schemas combined, which are not possible/valid according to JSONSchema.\n\nHence, the Types provided here can be used to provide valid Context objects and to read/write their JSON encodings, but may not detect or prevent a limited set of invalid objects that would be identified by JSONSchema.\n\nPlease also note that quicktype will generate types or interfaces representing subunits of the schema, which are then referenced in the main interface definition. These often do not have unique names (e.g. fields of the `id` object in the Context schema, defined for a specific context type such as fdc3.instrument). Quicktype will generate a random name for such an interface, to use to reference it, and as it is randomly generated it may appear oddly named (e.g. `PurpleId`, `FluffyMarket`, `TentacledIdentifier` etc.). Please ignore such names as these types/interfaces will not normally be used outside of the composition of the main type, e.g.:\n\n```TypeScript\nexport interface Instrument {\n  id: StickyId;\n  market?: FluffyMarket;\n  type: string;\n  name?: string;\n  [property: string]: any;\n}\n\nexport interface StickyId {\n  BBG?: string;\n  CUSIP?: string;\n  FDS_ID?: string;\n  FIGI?: string;\n  ISIN?: string;\n  PERMID?: string;\n  RIC?: string;\n  SEDOL?: string;\n  ticker?: string;\n  [property: string]: any;\n}\n\nexport interface FluffyMarket {\n  BBG?: string;\n  COUNTRY_ISOALPHA2?: string;\n  MIC?: string;\n  name?: string;\n  [property: string]: any;\n}\n```\n\nand should not be considered a planned part of the type structure (which should not be replicated in any derivative work). When applied, the naming of these sub-units is not used, rather they are replaced with their contents. It is hoped that we will be to generate better names of these sub-units in future.\n\nFinally, please note that the latest version of quicktype (at the time of writing `23.0.19`) has a number of bugs that must be worked around:\n\n- Using a directory or .schema.json files as a source will cause the input type argument `-s schema` to be ignored, causing the files to be interpreted as JSON rather than JSON Schema.\n  - A utility is provided in this repository (_../../quicktypeUtil.js_) to work around this bug by listing directories and constructing a call to quicktype where each file is provided as an individual source.\n- Setting the `--nice-property-names` TypeScript output option will crash the generator and can't be used.\n\n\nFurther details:\n - https://github.com/finos/FDC3\n - [FDC3 Specification](https://fdc3.finos.org/)\n - Main FDC3 module: https://www.npmjs.com/package/@finos/fdc3"
  },
  {
    "path": "packages/fdc3-context/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n  {\n    rules: {\n      'no-empty': 'off',\n      'no-prototype-builtins': 'off',\n      '@typescript-eslint/adjacent-overload-signatures': 'warn',\n      '@typescript-eslint/no-empty-function': 'warn',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          argsIgnorePattern: '^_',\n          caughtErrorsIgnorePattern: '^_',\n        },\n      ],\n    },\n  },\n];\n"
  },
  {
    "path": "packages/fdc3-context/generated/context/ContextTypes.ts",
    "content": "// To parse this data:\n//\n//   import { Convert, Action, Chart, ChatInitSettings, ChatMessage, ChatRoom, ChatSearchCriteria, Contact, ContactList, Context, Country, Currency, Email, FileAttachment, Instrument, InstrumentList, Interaction, Message, Nothing, Order, OrderList, Organization, Portfolio, Position, Product, TimeRange, Trade, TradeList, TransactionResult, Valuation } from \"./file\";\n//\n//   const action = Convert.toAction(json);\n//   const chart = Convert.toChart(json);\n//   const chatInitSettings = Convert.toChatInitSettings(json);\n//   const chatMessage = Convert.toChatMessage(json);\n//   const chatRoom = Convert.toChatRoom(json);\n//   const chatSearchCriteria = Convert.toChatSearchCriteria(json);\n//   const contact = Convert.toContact(json);\n//   const contactList = Convert.toContactList(json);\n//   const context = Convert.toContext(json);\n//   const country = Convert.toCountry(json);\n//   const currency = Convert.toCurrency(json);\n//   const email = Convert.toEmail(json);\n//   const fileAttachment = Convert.toFileAttachment(json);\n//   const instrument = Convert.toInstrument(json);\n//   const instrumentList = Convert.toInstrumentList(json);\n//   const interaction = Convert.toInteraction(json);\n//   const message = Convert.toMessage(json);\n//   const nothing = Convert.toNothing(json);\n//   const order = Convert.toOrder(json);\n//   const orderList = Convert.toOrderList(json);\n//   const organization = Convert.toOrganization(json);\n//   const portfolio = Convert.toPortfolio(json);\n//   const position = Convert.toPosition(json);\n//   const product = Convert.toProduct(json);\n//   const timeRange = Convert.toTimeRange(json);\n//   const trade = Convert.toTrade(json);\n//   const tradeList = Convert.toTradeList(json);\n//   const transactionResult = Convert.toTransactionResult(json);\n//   const valuation = Convert.toValuation(json);\n//\n// These functions will throw an error if the JSON doesn't\n// match the expected interface, even if the JSON is valid.\n\n/**\n * A representation of an FDC3 Action (specified via a Context or Context & Intent) that can\n * be inserted inside another object, for example a chat message.\n *\n * The action may be completed by calling:\n * - `fdc3.raiseIntent()` with the specified Intent and Context\n * - `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent\n * will resolve by presenting the user with a list of available Intents for the Context).\n * - `channel.broadcast()` with the specified Context, if the `broadcast` action has been\n * defined.\n *\n * Accepts an optional `app` parameter in order to specify a specific app.\n */\nexport interface Action {\n  /**\n   * The **action** field indicates the type of action:\n   * - **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent`\n   * or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if\n   * given).\n   * - **broadcast** : If `broadcast` and a `channelId` are specified then\n   * `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the\n   * context to it with `channel.broadcast(context)`. If no `channelId` has been specified,\n   * the context should be broadcast to the current channel (`fdc3.broadcast()`)\n   */\n  action?: ActionType;\n  /**\n   * An optional target application identifier that should perform the action. The `app`\n   * property is ignored unless the action is raiseIntent.\n   */\n  app?: AppIdentifier;\n  /**\n   * Optional channel on which to broadcast the context. The `channelId` property is ignored\n   * unless the `action` is broadcast.\n   */\n  channelId?: string;\n  /**\n   * A context object with which the action will be performed\n   */\n  context: ContextElement;\n  /**\n   * Optional Intent to raise to perform the actions. Should reference an intent type name,\n   * such as those defined in the FDC3 Standard. If intent is not set then\n   * `fdc3.raiseIntentForContext` should be used to perform the action as this will usually\n   * allow the user to choose the intent to raise.\n   */\n  intent?: string;\n  /**\n   * A human readable display name for the action\n   */\n  title: string;\n  type: 'fdc3.action';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * The **action** field indicates the type of action:\n * - **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent`\n * or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if\n * given).\n * - **broadcast** : If `broadcast` and a `channelId` are specified then\n * `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the\n * context to it with `channel.broadcast(context)`. If no `channelId` has been specified,\n * the context should be broadcast to the current channel (`fdc3.broadcast()`)\n */\nexport type ActionType = 'broadcast' | 'raiseIntent';\n\n/**\n * An optional target application identifier that should perform the action. The `app`\n * property is ignored unless the action is raiseIntent.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n */\nexport interface AppIdentifier {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * A context object with which the action will be performed\n *\n * A context object returned by the transaction, possibly with updated data.\n *\n * The `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by\n * FDC3 operations. As such, it is not really meant to be used on its own, but is imported\n * by more specific type definitions (standardized or custom) to provide the structure and\n * properties shared by all FDC3 context data types.\n *\n * The key element of FDC3 context types is their mandatory `type` property, which is used\n * to identify what type of data the object represents, and what shape it has.\n *\n * The FDC3 context type, and all derived types, define the minimum set of fields a context\n * data object of a particular type can be expected to have, but this can always be extended\n * with custom fields as appropriate.\n */\nexport interface ContextElement {\n  /**\n   * Context data objects may include a set of equivalent key-value pairs that can be used to\n   * help applications identify and look up the context type they receive in their own domain.\n   * The idea behind this design is that applications can provide as many equivalent\n   * identifiers to a target application as possible, e.g. an instrument may be represented by\n   * an ISIN, CUSIP or Bloomberg identifier.\n   *\n   * Identifiers do not make sense for all types of data, so the `id` property is therefore\n   * optional, but some derived types may choose to require at least one identifier.\n   * Identifier values SHOULD always be of type string.\n   */\n  id?: { [key: string]: any };\n  /**\n   * Context data objects may include a name property that can be used for more information,\n   * or display purposes. Some derived types may require the name object as mandatory,\n   * depending on use case.\n   */\n  name?: string;\n  /**\n   * The type property is the only _required_ part of the FDC3 context data schema. The FDC3\n   * [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present\n   * to route shared context data appropriately.\n   *\n   * FDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data\n   * types they support in an FDC3 [App\n   * Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery\n   * and routing.\n   *\n   * Standardized FDC3 context types have well-known `type` properties prefixed with the\n   * `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and\n   * used by a particular organization, the convention is to prefix them with an\n   * organization-specific namespace, e.g. `blackrock.fund`.\n   *\n   * See the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more\n   * information about context data types.\n   */\n  type: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A context type representing details of a Chart, which may be used to request plotting of\n * a particular chart or to otherwise share details of its composition, such as:\n *\n * - A list of instruments for comparison\n * - The time period to plot the chart over\n * - The style of chart (line, bar, mountain, candle etc.)\n * - Other settings such as indicators to calculate, or data representing drawings and\n * annotations.\n *\n * In addition to handling requests to plot charts, a charting application may use this type\n * to output a representation of what it is currently displaying so that it can be recorded\n * by another application.\n */\nexport interface Chart {\n  /**\n   * An array of instrument contexts whose data should be plotted.\n   */\n  instruments: InstrumentElement[];\n  /**\n   * It is common for charts to support other configuration, such as indicators, annotations\n   * etc., which do not have standardized formats, but may be included in the `otherConfig`\n   * array as context objects.\n   */\n  otherConfig?: ContextElement[];\n  /**\n   * The time range that should be plotted\n   */\n  range?: TimeRangeObject;\n  /**\n   * The type of chart that should be plotted\n   */\n  style?: ChartStyle;\n  type: 'fdc3.chart';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * A financial instrument that relates to the definition of this product\n *\n *\n *\n * A financial instrument from any asset class.\n */\nexport interface InstrumentElement {\n  /**\n   * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n   * for a better match. Not all applications will use the same instrument identifiers, which\n   * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n   * application can provide, the easier it will be to achieve interoperability.\n   *\n   * It is valid to include extra properties and metadata as part of the instrument payload,\n   * but the minimum requirement is for at least one instrument identifier to be provided.\n   *\n   * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n   * for tickers as used by an exchange.\n   * If the identifier you want to share is not a ticker or one of the other standardized\n   * fields, define a property that makes it clear what the value represents. Doing so will\n   * make interpretation easier for the developers of target applications.\n   */\n  id: PurpleInstrumentIdentifiers;\n  /**\n   * The `market` map can be used to further specify the instrument and help achieve\n   * interoperability between disparate data sources. This is especially useful when using an\n   * `id` field that is not globally unique.\n   */\n  market?: OrganizationMarket;\n  /**\n   * An optional human-readable name for the instrument\n   */\n  name?: string;\n  type: 'fdc3.instrument';\n  [property: string]: any;\n}\n\n/**\n * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n * for a better match. Not all applications will use the same instrument identifiers, which\n * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n * application can provide, the easier it will be to achieve interoperability.\n *\n * It is valid to include extra properties and metadata as part of the instrument payload,\n * but the minimum requirement is for at least one instrument identifier to be provided.\n *\n * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n * for tickers as used by an exchange.\n * If the identifier you want to share is not a ticker or one of the other standardized\n * fields, define a property that makes it clear what the value represents. Doing so will\n * make interpretation easier for the developers of target applications.\n */\nexport interface PurpleInstrumentIdentifiers {\n  /**\n   * https://www.bloomberg.com/\n   */\n  BBG?: string;\n  /**\n   * https://www.cusip.com/\n   */\n  CUSIP?: string;\n  /**\n   * https://www.factset.com/\n   */\n  FDS_ID?: string;\n  /**\n   * https://www.openfigi.com/\n   */\n  FIGI?: string;\n  /**\n   * https://www.isin.org/\n   */\n  ISIN?: string;\n  /**\n   * https://permid.org/\n   */\n  PERMID?: string;\n  /**\n   * https://www.refinitiv.com/\n   */\n  RIC?: string;\n  /**\n   * https://www.lseg.com/sedol\n   */\n  SEDOL?: string;\n  /**\n   * Unstandardized stock tickers\n   */\n  ticker?: string;\n  [property: string]: any;\n}\n\n/**\n * The `market` map can be used to further specify the instrument and help achieve\n * interoperability between disparate data sources. This is especially useful when using an\n * `id` field that is not globally unique.\n */\nexport interface OrganizationMarket {\n  /**\n   * https://www.bloomberg.com/\n   */\n  BBG?: string;\n  /**\n   * https://www.iso.org/iso-3166-country-codes.html\n   */\n  COUNTRY_ISOALPHA2?: string;\n  /**\n   * https://en.wikipedia.org/wiki/Market_Identifier_Code\n   */\n  MIC?: string;\n  /**\n   * Human readable market name\n   */\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * The time range that should be plotted\n *\n * The time range over which the interaction occurred\n *\n * A context representing a period of time. Any user interfaces that represent or visualize\n * events or activity over time can be filtered or focused on a particular time period,\n * e.g.:\n *\n * - A pricing chart\n * - A trade blotter\n * - A record of client contact/activity in a CRM\n *\n * Example use cases:\n *\n * - User may want to view pricing/trades/customer activity for a security over a particular\n * time period, the time range might be specified as the context for the `ViewChart` intent\n * OR it might be embedded in another context (e.g. a context representing a chart to plot).\n * - User filters a visualization (e.g. a pricing chart) to show a particular period, the\n * `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by\n * instrument, or industry sector etc.) receive it and filter themselves to show data over\n * the same range.\n *\n * Notes:\n *\n * - A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open\n * (i.e. only one of `startTime` or `endTime` is known).\n * - Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified\n * using times as this prevents issues with timezone conversions and inclusive/exclusive\n * date ranges.\n * - String fields representing times are encoded according to [ISO\n * 8601-1:2019](https://www.iso.org/standard/70907.html).\n * - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or\n * `\"2022-05-12T16:18:03+01:00\"`\n * - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n */\nexport interface TimeRangeObject {\n  /**\n   * The end time of the range, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n   */\n  endTime?: Date;\n  /**\n   * The start time of the range, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n   */\n  startTime?: Date;\n  type: 'fdc3.timeRange';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * The type of chart that should be plotted\n */\nexport type ChartStyle =\n  | 'line'\n  | 'bar'\n  | 'stacked-bar'\n  | 'mountain'\n  | 'candle'\n  | 'pie'\n  | 'scatter'\n  | 'histogram'\n  | 'heatmap'\n  | 'custom';\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A collection of settings to start a new chat conversation\n */\nexport interface ChatInitSettings {\n  /**\n   * Name to apply to the chat created\n   */\n  chatName?: string;\n  /**\n   * Contacts to add to the chat\n   */\n  members?: ContactListObject;\n  /**\n   * An initial message to post in the chat when created.\n   */\n  message?: MessageObject | string;\n  /**\n   * Option settings that affect the creation of the chat\n   */\n  options?: ChatOptions;\n  type: 'fdc3.chat.initSettings';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Contacts to add to the chat\n *\n * A list of contacts involved in the interaction\n *\n * A collection of contacts, e.g. for chatting to or calling multiple contacts.\n *\n * The contact list schema does not explicitly include identifiers in the `id` section, as\n * there is not a common standard for such identifiers. Applications can, however, populate\n * this part of the contract with custom identifiers if so desired.\n */\nexport interface ContactListObject {\n  /**\n   * An array of contact contexts that forms the list.\n   */\n  contacts: ContactElement[];\n  /**\n   * One or more identifiers that refer to the contact list in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An optional human-readable summary of the contact list\n   */\n  name?: string;\n  type: 'fdc3.contactList';\n  [property: string]: any;\n}\n\n/**\n * The contact that initiated the interaction\n *\n * A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n */\nexport interface ContactElement {\n  /**\n   * Identifiers that relate to the Contact represented by this context\n   */\n  id: PurpleContactIdentifiers;\n  /**\n   * An optional human-readable name for the contact\n   */\n  name?: string;\n  type: 'fdc3.contact';\n  [property: string]: any;\n}\n\n/**\n * Identifiers that relate to the Contact represented by this context\n */\nexport interface PurpleContactIdentifiers {\n  /**\n   * The email address for the contact\n   */\n  email?: string;\n  /**\n   * FactSet Permanent Identifier representing the contact\n   */\n  FDS_ID?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A chat message to be sent through an instant messaging application. Can contain one or\n * several text bodies (organized by mime-type, plaintext or markdown), as well as attached\n * entities (either arbitrary file attachments or FDC3 actions to be embedded in the\n * message). To be put inside a ChatInitSettings object.\n */\nexport interface MessageObject {\n  /**\n   * A map of string IDs to entities that should be attached to the message, such as an action\n   * to perform, a file attachment, or other FDC3 context object.\n   */\n  entities?: { [key: string]: EntityValue };\n  /**\n   * A map of string mime-type to string content\n   */\n  text?: PurpleMessageText;\n  type: 'fdc3.message';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * A representation of an FDC3 Action (specified via a Context or Context & Intent) that can\n * be inserted inside another object, for example a chat message.\n *\n * The action may be completed by calling:\n * - `fdc3.raiseIntent()` with the specified Intent and Context\n * - `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent\n * will resolve by presenting the user with a list of available Intents for the Context).\n * - `channel.broadcast()` with the specified Context, if the `broadcast` action has been\n * defined.\n *\n * Accepts an optional `app` parameter in order to specify a specific app.\n *\n * A File attachment encoded in the form of a data URI. Can be added to a Message.\n */\nexport interface EntityValue {\n  /**\n   * The **action** field indicates the type of action:\n   * - **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent`\n   * or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if\n   * given).\n   * - **broadcast** : If `broadcast` and a `channelId` are specified then\n   * `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the\n   * context to it with `channel.broadcast(context)`. If no `channelId` has been specified,\n   * the context should be broadcast to the current channel (`fdc3.broadcast()`)\n   */\n  action?: ActionType;\n  /**\n   * An optional target application identifier that should perform the action. The `app`\n   * property is ignored unless the action is raiseIntent.\n   */\n  app?: AppIdentifier;\n  /**\n   * Optional channel on which to broadcast the context. The `channelId` property is ignored\n   * unless the `action` is broadcast.\n   */\n  channelId?: string;\n  /**\n   * A context object with which the action will be performed\n   */\n  context?: ContextElement;\n  /**\n   * Optional Intent to raise to perform the actions. Should reference an intent type name,\n   * such as those defined in the FDC3 Standard. If intent is not set then\n   * `fdc3.raiseIntentForContext` should be used to perform the action as this will usually\n   * allow the user to choose the intent to raise.\n   */\n  intent?: string;\n  /**\n   * A human readable display name for the action\n   */\n  title?: string;\n  type: EntityType;\n  id?: { [key: string]: any };\n  name?: string;\n  data?: EntityData;\n  [property: string]: any;\n}\n\nexport interface EntityData {\n  /**\n   * A data URI encoding the content of the file to be attached\n   */\n  dataUri: string;\n  /**\n   * The name of the attached file\n   */\n  name: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\nexport type EntityType = 'fdc3.action' | 'fdc3.fileAttachment';\n\n/**\n * A map of string mime-type to string content\n */\nexport interface PurpleMessageText {\n  /**\n   * Markdown encoded content\n   */\n  'text/markdown'?: string;\n  /**\n   * Plain text encoded content.\n   */\n  'text/plain'?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Option settings that affect the creation of the chat\n */\nexport interface ChatOptions {\n  /**\n   * if true members will be allowed to add other members to the chat\n   */\n  allowAddUser?: boolean;\n  /**\n   * if true members will be allowed to browse past messages\n   */\n  allowHistoryBrowsing?: boolean;\n  /**\n   * if true members will be allowed to copy/paste messages\n   */\n  allowMessageCopy?: boolean;\n  /**\n   * if false a separate chat will be created for each member\n   */\n  groupRecipients?: boolean;\n  /**\n   * if true the room will be visible to everyone in the chat application\n   */\n  isPublic?: boolean;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A context representing a chat message. Typically used to send the message or to\n * pre-populate a message for sending.\n */\nexport interface ChatMessage {\n  chatRoom: ChatRoomObject;\n  message: MessageObject;\n  type: 'fdc3.chat.message';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Reference to the chat room which could be used to send a message to the room\n */\nexport interface ChatRoomObject {\n  /**\n   * Identifier(s) for the chat - currently unstandardized\n   */\n  id: { [key: string]: string };\n  /**\n   * Display name for the chat room\n   */\n  name?: string;\n  /**\n   * The name of the service that hosts the chat\n   */\n  providerName: string;\n  type: 'fdc3.chat.room';\n  /**\n   * Universal url to access to the room. It could be opened from a browser, a mobile app,\n   * etc...\n   */\n  url?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Reference to the chat room which could be used to send a message to the room\n */\nexport interface ChatRoom {\n  /**\n   * Identifier(s) for the chat - currently unstandardized\n   */\n  id: { [key: string]: string };\n  /**\n   * Display name for the chat room\n   */\n  name?: string;\n  /**\n   * The name of the service that hosts the chat\n   */\n  providerName: string;\n  type: 'fdc3.chat.room';\n  /**\n   * Universal url to access to the room. It could be opened from a browser, a mobile app,\n   * etc...\n   */\n  url?: string;\n  [property: string]: any;\n}\n\n/**\n * A context type that represents a simple search criterion, based on a list of other\n * context objects, that can be used to search or filter messages in a chat application.\n */\nexport interface ChatSearchCriteria {\n  /**\n   * An array of criteria that should match chats returned from by a search.\n   *\n   * ⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the\n   * application that processes the FDC3 Intent to choose and apply the operators between the\n   * criteria.\n   *\n   * Empty search criteria can be supported to allow resetting of filters.\n   */\n  criteria: Array<OrganizationObject | string>;\n  type: 'fdc3.chat.searchCriteria';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * A financial instrument that relates to the definition of this product\n *\n *\n *\n * A financial instrument from any asset class.\n *\n * An entity that can be used when referencing private companies and other organizations\n * where a specific instrument is not available or desired e.g. CRM and News workflows.\n *\n * It is valid to include extra properties and metadata as part of the organization payload,\n * but the minimum requirement is for at least one specified identifier to be provided.\n *\n * The contact that initiated the interaction\n *\n * A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n */\nexport interface OrganizationObject {\n  /**\n   * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n   * for a better match. Not all applications will use the same instrument identifiers, which\n   * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n   * application can provide, the easier it will be to achieve interoperability.\n   *\n   * It is valid to include extra properties and metadata as part of the instrument payload,\n   * but the minimum requirement is for at least one instrument identifier to be provided.\n   *\n   * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n   * for tickers as used by an exchange.\n   * If the identifier you want to share is not a ticker or one of the other standardized\n   * fields, define a property that makes it clear what the value represents. Doing so will\n   * make interpretation easier for the developers of target applications.\n   *\n   * Identifiers for the organization, at least one must be provided.\n   *\n   * Identifiers that relate to the Contact represented by this context\n   */\n  id: Identifiers;\n  /**\n   * The `market` map can be used to further specify the instrument and help achieve\n   * interoperability between disparate data sources. This is especially useful when using an\n   * `id` field that is not globally unique.\n   */\n  market?: OrganizationMarket;\n  /**\n   * An optional human-readable name for the instrument\n   *\n   * An optional human-readable name of the organization\n   *\n   * An optional human-readable name for the contact\n   */\n  name?: string;\n  type: TentacledInteractionType;\n  [property: string]: any;\n}\n\n/**\n * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n * for a better match. Not all applications will use the same instrument identifiers, which\n * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n * application can provide, the easier it will be to achieve interoperability.\n *\n * It is valid to include extra properties and metadata as part of the instrument payload,\n * but the minimum requirement is for at least one instrument identifier to be provided.\n *\n * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n * for tickers as used by an exchange.\n * If the identifier you want to share is not a ticker or one of the other standardized\n * fields, define a property that makes it clear what the value represents. Doing so will\n * make interpretation easier for the developers of target applications.\n *\n * Identifiers for the organization, at least one must be provided.\n *\n * Identifiers that relate to the Contact represented by this context\n */\nexport interface Identifiers {\n  /**\n   * https://www.bloomberg.com/\n   */\n  BBG?: string;\n  /**\n   * https://www.cusip.com/\n   */\n  CUSIP?: string;\n  /**\n   * https://www.factset.com/\n   *\n   * FactSet Permanent Identifier representing the organization\n   *\n   * FactSet Permanent Identifier representing the contact\n   */\n  FDS_ID?: string;\n  /**\n   * https://www.openfigi.com/\n   */\n  FIGI?: string;\n  /**\n   * https://www.isin.org/\n   */\n  ISIN?: string;\n  /**\n   * https://permid.org/\n   *\n   * Refinitiv Permanent Identifiers, or PermID for the organization\n   */\n  PERMID?: string;\n  /**\n   * https://www.refinitiv.com/\n   */\n  RIC?: string;\n  /**\n   * https://www.lseg.com/sedol\n   */\n  SEDOL?: string;\n  /**\n   * Unstandardized stock tickers\n   */\n  ticker?: string;\n  /**\n   * The Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO\n   * 17442 standard developed by the International Organization for Standardization (ISO). It\n   * connects to key reference information that enables clear and unique identification of\n   * legal entities participating in financial transactions.\n   */\n  LEI?: string;\n  /**\n   * The email address for the contact\n   */\n  email?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\nexport type TentacledInteractionType = 'fdc3.instrument' | 'fdc3.organization' | 'fdc3.contact';\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n */\nexport interface Contact {\n  /**\n   * Identifiers that relate to the Contact represented by this context\n   */\n  id: FluffyContactIdentifiers;\n  /**\n   * An optional human-readable name for the contact\n   */\n  name?: string;\n  type: 'fdc3.contact';\n  [property: string]: any;\n}\n\n/**\n * Identifiers that relate to the Contact represented by this context\n */\nexport interface FluffyContactIdentifiers {\n  /**\n   * The email address for the contact\n   */\n  email?: string;\n  /**\n   * FactSet Permanent Identifier representing the contact\n   */\n  FDS_ID?: string;\n  [property: string]: any;\n}\n\n/**\n * A collection of contacts, e.g. for chatting to or calling multiple contacts.\n *\n * The contact list schema does not explicitly include identifiers in the `id` section, as\n * there is not a common standard for such identifiers. Applications can, however, populate\n * this part of the contract with custom identifiers if so desired.\n */\nexport interface ContactList {\n  /**\n   * An array of contact contexts that forms the list.\n   */\n  contacts: ContactElement[];\n  /**\n   * One or more identifiers that refer to the contact list in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An optional human-readable summary of the contact list\n   */\n  name?: string;\n  type: 'fdc3.contactList';\n  [property: string]: any;\n}\n\n/**\n * The `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by\n * FDC3 operations. As such, it is not really meant to be used on its own, but is imported\n * by more specific type definitions (standardized or custom) to provide the structure and\n * properties shared by all FDC3 context data types.\n *\n * The key element of FDC3 context types is their mandatory `type` property, which is used\n * to identify what type of data the object represents, and what shape it has.\n *\n * The FDC3 context type, and all derived types, define the minimum set of fields a context\n * data object of a particular type can be expected to have, but this can always be extended\n * with custom fields as appropriate.\n */\nexport interface Context {\n  /**\n   * Context data objects may include a set of equivalent key-value pairs that can be used to\n   * help applications identify and look up the context type they receive in their own domain.\n   * The idea behind this design is that applications can provide as many equivalent\n   * identifiers to a target application as possible, e.g. an instrument may be represented by\n   * an ISIN, CUSIP or Bloomberg identifier.\n   *\n   * Identifiers do not make sense for all types of data, so the `id` property is therefore\n   * optional, but some derived types may choose to require at least one identifier.\n   * Identifier values SHOULD always be of type string.\n   */\n  id?: { [key: string]: any };\n  /**\n   * Context data objects may include a name property that can be used for more information,\n   * or display purposes. Some derived types may require the name object as mandatory,\n   * depending on use case.\n   */\n  name?: string;\n  /**\n   * The type property is the only _required_ part of the FDC3 context data schema. The FDC3\n   * [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present\n   * to route shared context data appropriately.\n   *\n   * FDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data\n   * types they support in an FDC3 [App\n   * Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery\n   * and routing.\n   *\n   * Standardized FDC3 context types have well-known `type` properties prefixed with the\n   * `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and\n   * used by a particular organization, the convention is to prefix them with an\n   * organization-specific namespace, e.g. `blackrock.fund`.\n   *\n   * See the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more\n   * information about context data types.\n   */\n  type: string;\n  [property: string]: any;\n}\n\n/**\n * A country entity.\n *\n * Notes:\n *\n * - It is valid to include extra properties and metadata as part of the country payload,\n * but the minimum requirement is for at least one standardized identifier to be provided\n *\n * - `COUNTRY_ISOALPHA2` SHOULD be preferred.\n *\n * - Try to only use country identifiers as intended and specified in the [ISO\n * standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2`\n * property must be a recognized value and not a proprietary two-letter code. If the\n * identifier you want to share is not a standardized and recognized one, rather define a\n * property that makes it clear what value it is. This makes it easier for target\n * applications.\n */\nexport interface Country {\n  id: CountryID;\n  /**\n   * An optional human-readable name for the country\n   */\n  name?: string;\n  type: 'fdc3.country';\n  [property: string]: any;\n}\n\nexport interface CountryID {\n  /**\n   * Two-letter ISO country code\n   */\n  COUNTRY_ISOALPHA2?: string;\n  /**\n   * Three-letter ISO country code\n   */\n  COUNTRY_ISOALPHA3?: string;\n  /**\n   * Two-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed\n   * with `COUNTRY_`.\n   */\n  ISOALPHA2?: string;\n  /**\n   * Three-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed\n   * with `COUNTRY_`.\n   */\n  ISOALPHA3?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A context representing an individual Currency.\n */\nexport interface Currency {\n  id: CurrencyID;\n  /**\n   * The name of the currency for display purposes\n   */\n  name?: string;\n  type: 'fdc3.currency';\n  [property: string]: any;\n}\n\nexport interface CurrencyID {\n  /**\n   * The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO\n   * 4217](https://www.iso.org/iso-4217-currency-codes.html)\n   */\n  CURRENCY_ISOCODE?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A collection of information to be used to initiate an email with a Contact or ContactList.\n */\nexport interface Email {\n  /**\n   * One or more recipients for the email.\n   */\n  recipients: EmailRecipients;\n  /**\n   * Subject line for the email.\n   */\n  subject?: string;\n  /**\n   * Body content for the email.\n   */\n  textBody?: string;\n  type: 'fdc3.email';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * One or more recipients for the email.\n *\n * The contact that initiated the interaction\n *\n * A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n *\n * Contacts to add to the chat\n *\n * A list of contacts involved in the interaction\n *\n * A collection of contacts, e.g. for chatting to or calling multiple contacts.\n *\n * The contact list schema does not explicitly include identifiers in the `id` section, as\n * there is not a common standard for such identifiers. Applications can, however, populate\n * this part of the contract with custom identifiers if so desired.\n */\nexport interface EmailRecipients {\n  /**\n   * Identifiers that relate to the Contact represented by this context\n   *\n   * One or more identifiers that refer to the contact list in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: ContactTIdentifiers;\n  /**\n   * An optional human-readable name for the contact\n   *\n   * An optional human-readable summary of the contact list\n   */\n  name?: string;\n  type: EmailRecipientsType;\n  /**\n   * An array of contact contexts that forms the list.\n   */\n  contacts?: ContactElement[];\n  [property: string]: any;\n}\n\n/**\n * Identifiers that relate to the Contact represented by this context\n *\n * One or more identifiers that refer to the contact list in an OMS, EMS or related system.\n * Specific key names for systems are expected to be standardized in future.\n */\nexport interface ContactTIdentifiers {\n  /**\n   * The email address for the contact\n   */\n  email?: string;\n  /**\n   * FactSet Permanent Identifier representing the contact\n   */\n  FDS_ID?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\nexport type EmailRecipientsType = 'fdc3.contact' | 'fdc3.contactList';\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A File attachment encoded in the form of a data URI. Can be added to a Message.\n */\nexport interface FileAttachment {\n  data: FileAttachmentData;\n  type: 'fdc3.fileAttachment';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\nexport interface FileAttachmentData {\n  /**\n   * A data URI encoding the content of the file to be attached\n   */\n  dataUri: string;\n  /**\n   * The name of the attached file\n   */\n  name: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A financial instrument from any asset class.\n */\nexport interface Instrument {\n  /**\n   * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n   * for a better match. Not all applications will use the same instrument identifiers, which\n   * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n   * application can provide, the easier it will be to achieve interoperability.\n   *\n   * It is valid to include extra properties and metadata as part of the instrument payload,\n   * but the minimum requirement is for at least one instrument identifier to be provided.\n   *\n   * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n   * for tickers as used by an exchange.\n   * If the identifier you want to share is not a ticker or one of the other standardized\n   * fields, define a property that makes it clear what the value represents. Doing so will\n   * make interpretation easier for the developers of target applications.\n   */\n  id: FluffyInstrumentIdentifiers;\n  /**\n   * The `market` map can be used to further specify the instrument and help achieve\n   * interoperability between disparate data sources. This is especially useful when using an\n   * `id` field that is not globally unique.\n   */\n  market?: PurpleMarket;\n  /**\n   * An optional human-readable name for the instrument\n   */\n  name?: string;\n  type: 'fdc3.instrument';\n  [property: string]: any;\n}\n\n/**\n * Any combination of instrument identifiers can be used together to resolve ambiguity, or\n * for a better match. Not all applications will use the same instrument identifiers, which\n * is why FDC3 allows for multiple to be specified. In general, the more identifiers an\n * application can provide, the easier it will be to achieve interoperability.\n *\n * It is valid to include extra properties and metadata as part of the instrument payload,\n * but the minimum requirement is for at least one instrument identifier to be provided.\n *\n * Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant\n * for tickers as used by an exchange.\n * If the identifier you want to share is not a ticker or one of the other standardized\n * fields, define a property that makes it clear what the value represents. Doing so will\n * make interpretation easier for the developers of target applications.\n */\nexport interface FluffyInstrumentIdentifiers {\n  /**\n   * https://www.bloomberg.com/\n   */\n  BBG?: string;\n  /**\n   * https://www.cusip.com/\n   */\n  CUSIP?: string;\n  /**\n   * https://www.factset.com/\n   */\n  FDS_ID?: string;\n  /**\n   * https://www.openfigi.com/\n   */\n  FIGI?: string;\n  /**\n   * https://www.isin.org/\n   */\n  ISIN?: string;\n  /**\n   * https://permid.org/\n   */\n  PERMID?: string;\n  /**\n   * https://www.refinitiv.com/\n   */\n  RIC?: string;\n  /**\n   * https://www.lseg.com/sedol\n   */\n  SEDOL?: string;\n  /**\n   * Unstandardized stock tickers\n   */\n  ticker?: string;\n  [property: string]: any;\n}\n\n/**\n * The `market` map can be used to further specify the instrument and help achieve\n * interoperability between disparate data sources. This is especially useful when using an\n * `id` field that is not globally unique.\n */\nexport interface PurpleMarket {\n  /**\n   * https://www.bloomberg.com/\n   */\n  BBG?: string;\n  /**\n   * https://www.iso.org/iso-3166-country-codes.html\n   */\n  COUNTRY_ISOALPHA2?: string;\n  /**\n   * https://en.wikipedia.org/wiki/Market_Identifier_Code\n   */\n  MIC?: string;\n  /**\n   * Human readable market name\n   */\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * A collection of instruments. Use this type for use cases that require not just a single\n * instrument, but multiple (e.g. to populate a watchlist). However, when holding\n * information for each instrument is required, it is recommended to use the\n * [Portfolio](Portfolio) type.\n *\n * The instrument list schema does not explicitly include identifiers in the `id` section,\n * as there is not a common standard for such identifiers. Applications can, however,\n * populate this part of the contract with custom identifiers if so desired.\n */\nexport interface InstrumentList {\n  /**\n   * One or more identifiers that refer to the instrument list in an OMS, EMS or related\n   * system. Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An array of instrument contexts that forms the list.\n   */\n  instruments: InstrumentElement[];\n  /**\n   * An optional human-readable summary of the instrument list\n   */\n  name?: string;\n  type: 'fdc3.instrumentList';\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * An `Interaction` is a significant direct exchange of ideas or information between a\n * number of participants, e.g. a Sell Side party and one or more Buy Side parties. An\n * `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation\n * of some specialist data, such as financial data for a given company or sector.\n */\nexport interface Interaction {\n  /**\n   * A human-readable description of the interaction\n   */\n  description: string;\n  /**\n   * Can be used by a target application to pass an identifier back to the originating\n   * application after an interaction record has been created, updated or deleted. An\n   * interaction ID does not need to be populated by the originating application, however the\n   * target application could store it for future reference and SHOULD return it in a\n   * `TransactionResult`.\n   */\n  id?: InteractionID;\n  /**\n   * The contact that initiated the interaction\n   */\n  initiator?: ContactElement;\n  /**\n   * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n   * `'Meeting'` although other string values are permitted.\n   */\n  interactionType: string;\n  /**\n   * Used to represent the application or service that the interaction was created from to aid\n   * in tracing the source of an interaction.\n   */\n  origin?: string;\n  /**\n   * A list of contacts involved in the interaction\n   */\n  participants: ContactListObject;\n  /**\n   * The time range over which the interaction occurred\n   */\n  timeRange: TimeRangeObject;\n  type: 'fdc3.interaction';\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Can be used by a target application to pass an identifier back to the originating\n * application after an interaction record has been created, updated or deleted. An\n * interaction ID does not need to be populated by the originating application, however the\n * target application could store it for future reference and SHOULD return it in a\n * `TransactionResult`.\n */\nexport interface InteractionID {\n  /**\n   * Interactions ID in Salesforce\n   */\n  SALESFORCE?: string;\n  /**\n   * Interaction ID in SingleTrack\n   */\n  SINGLETRACK?: string;\n  /**\n   * Can be used by a target application to pass a record's link back to the originating\n   * application. This offers the originating application a way to open the record for a user\n   * to view.\n   */\n  URI?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A chat message to be sent through an instant messaging application. Can contain one or\n * several text bodies (organized by mime-type, plaintext or markdown), as well as attached\n * entities (either arbitrary file attachments or FDC3 actions to be embedded in the\n * message). To be put inside a ChatInitSettings object.\n */\nexport interface Message {\n  /**\n   * A map of string IDs to entities that should be attached to the message, such as an action\n   * to perform, a file attachment, or other FDC3 context object.\n   */\n  entities?: { [key: string]: EntityValue };\n  /**\n   * A map of string mime-type to string content\n   */\n  text?: FluffyMessageText;\n  type: 'fdc3.message';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * A map of string mime-type to string content\n */\nexport interface FluffyMessageText {\n  /**\n   * Markdown encoded content\n   */\n  'text/markdown'?: string;\n  /**\n   * Plain text encoded content.\n   */\n  'text/plain'?: string;\n  [property: string]: any;\n}\n\n/**\n * A type that explicitly represents a lack of context.\n *\n * Notes:\n *\n * - Intended to be used in situations where no context is desired.\n * - For example:\n * - Raising an intent without context (e.g. opening a blank order form, or chat interface\n * without a contact selected).\n * - Resetting context on a channel (e.g. when context is used to set a filter in other\n * applications a null context might release the filter).\n * - An explicit representation of a Null or empty context allows apps to declare support\n * for a lack of context, for example in their intent metadata in an app directory.\n */\nexport interface Nothing {\n  type: 'fdc3.nothing';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * @experimental context type representing an order. To be used with OMS and EMS systems.\n *\n * This type currently only defines a required `id` field, which should provide a reference\n * to the order in one or more systems, an optional human readable `name` field to be used\n * to summarize the order and an optional `details` field that may be used to provide\n * additional detail about the order, including a context representing a `product`, which\n * may be extended with arbitrary properties. The `details.product` field is currently typed\n * as a unspecified Context type, but both `details` and `details.product` are expected to\n * be standardized in future.\n */\nexport interface Order {\n  /**\n   * Optional additional details about the order, which may include a product element that is\n   * an, as yet undefined but extensible, Context\n   */\n  details?: PurpleOrderDetails;\n  /**\n   * One or more identifiers that refer to the order in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * An optional human-readable summary of the order.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the order.\n   */\n  notes?: string;\n  type: 'fdc3.order';\n  [property: string]: any;\n}\n\n/**\n * Optional additional details about the order, which may include a product element that is\n * an, as yet undefined but extensible, Context\n */\nexport interface PurpleOrderDetails {\n  product?: ProductObject;\n  [property: string]: any;\n}\n\n/**\n * A product that is the subject of the trade.\n *\n * @experimental context type representing a tradable product. To be used with OMS and EMS\n * systems.\n *\n * This type is currently only loosely defined as an extensible context object, with an\n * optional instrument field.\n *\n * The Product schema does not explicitly include identifiers in the id section, as there is\n * not a common standard for such identifiers. Applications can, however, populate this part\n * of the contract with custom identifiers if so desired.\n */\nexport interface ProductObject {\n  /**\n   * One or more identifiers that refer to the product. Specific key names for systems are\n   * expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * A financial instrument that relates to the definition of this product\n   */\n  instrument?: InstrumentElement;\n  /**\n   * A human-readable summary of the product.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the product.\n   */\n  notes?: string;\n  type: 'fdc3.product';\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * @experimental A list of orders. Use this type for use cases that require not just a\n * single order, but multiple.\n *\n * The OrderList schema does not explicitly include identifiers in the id section, as there\n * is not a common standard for such identifiers. Applications can, however, populate this\n * part of the contract with custom identifiers if so desired.\n */\nexport interface OrderList {\n  /**\n   * One or more identifiers that refer to the order list in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An optional human-readable summary of the order list\n   */\n  name?: string;\n  /**\n   * An array of order contexts that forms the list.\n   */\n  orders: OrderElement[];\n  type: 'fdc3.orderList';\n  [property: string]: any;\n}\n\n/**\n * @experimental context type representing an order. To be used with OMS and EMS systems.\n *\n * This type currently only defines a required `id` field, which should provide a reference\n * to the order in one or more systems, an optional human readable `name` field to be used\n * to summarize the order and an optional `details` field that may be used to provide\n * additional detail about the order, including a context representing a `product`, which\n * may be extended with arbitrary properties. The `details.product` field is currently typed\n * as a unspecified Context type, but both `details` and `details.product` are expected to\n * be standardized in future.\n */\nexport interface OrderElement {\n  /**\n   * Optional additional details about the order, which may include a product element that is\n   * an, as yet undefined but extensible, Context\n   */\n  details?: FluffyOrderDetails;\n  /**\n   * One or more identifiers that refer to the order in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * An optional human-readable summary of the order.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the order.\n   */\n  notes?: string;\n  type: 'fdc3.order';\n  [property: string]: any;\n}\n\n/**\n * Optional additional details about the order, which may include a product element that is\n * an, as yet undefined but extensible, Context\n */\nexport interface FluffyOrderDetails {\n  product?: ProductObject;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * An entity that can be used when referencing private companies and other organizations\n * where a specific instrument is not available or desired e.g. CRM and News workflows.\n *\n * It is valid to include extra properties and metadata as part of the organization payload,\n * but the minimum requirement is for at least one specified identifier to be provided.\n */\nexport interface Organization {\n  /**\n   * Identifiers for the organization, at least one must be provided.\n   */\n  id: OrganizationIdentifiers;\n  /**\n   * An optional human-readable name of the organization\n   */\n  name?: string;\n  type: 'fdc3.organization';\n  [property: string]: any;\n}\n\n/**\n * Identifiers for the organization, at least one must be provided.\n */\nexport interface OrganizationIdentifiers {\n  /**\n   * FactSet Permanent Identifier representing the organization\n   */\n  FDS_ID?: string;\n  /**\n   * The Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO\n   * 17442 standard developed by the International Organization for Standardization (ISO). It\n   * connects to key reference information that enables clear and unique identification of\n   * legal entities participating in financial transactions.\n   */\n  LEI?: string;\n  /**\n   * Refinitiv Permanent Identifiers, or PermID for the organization\n   */\n  PERMID?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A financial portfolio made up of multiple positions (holdings) in several instruments.\n * Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list\n * of instruments.\n *\n * This is a good example of how types can be composed and extended with extra properties to\n * define more complex types.\n *\n * The Portfolio type consists of an array of [Position](Position) types, each of which\n * refers to a single [Instrument](Instrument) and a holding amount for that instrument.\n *\n * The portfolio schema does not explicitly include identifiers in the `id` section, as\n * there bis not a common standard for such identifiers. Applications can, however, populate\n * this part of the contract with custom identifiers if so desired.\n */\nexport interface Portfolio {\n  /**\n   * One or more identifiers that refer to the portfolio in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An optional human-readable name for the portfolio\n   */\n  name?: string;\n  /**\n   * The List of Positions which make up the Portfolio\n   */\n  positions: PositionElement[];\n  type: 'fdc3.portfolio';\n  [property: string]: any;\n}\n\n/**\n * A financial position made up of an instrument and a holding in that instrument. This type\n * is a good example of how new context types can be composed from existing types.\n *\n * In this case, the instrument and the holding amount for that instrument are required\n * values.\n *\n * The [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type,\n * which represents multiple holdings in a combination of instruments.\n *\n * The position schema does not explicitly include identifiers in the `id` section, as there\n * is not a common standard for such identifiers. Applications can, however, populate this\n * part of the contract with custom identifiers if so desired.\n */\nexport interface PositionElement {\n  /**\n   * The amount of the holding, e.g. a number of shares\n   */\n  holding: number;\n  /**\n   * One or more identifiers that refer to the position in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  instrument: InstrumentElement;\n  /**\n   * An optional human-readable name for the position\n   */\n  name?: string;\n  type: 'fdc3.position';\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A financial position made up of an instrument and a holding in that instrument. This type\n * is a good example of how new context types can be composed from existing types.\n *\n * In this case, the instrument and the holding amount for that instrument are required\n * values.\n *\n * The [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type,\n * which represents multiple holdings in a combination of instruments.\n *\n * The position schema does not explicitly include identifiers in the `id` section, as there\n * is not a common standard for such identifiers. Applications can, however, populate this\n * part of the contract with custom identifiers if so desired.\n */\nexport interface Position {\n  /**\n   * The amount of the holding, e.g. a number of shares\n   */\n  holding: number;\n  /**\n   * One or more identifiers that refer to the position in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  instrument: InstrumentElement;\n  /**\n   * An optional human-readable name for the position\n   */\n  name?: string;\n  type: 'fdc3.position';\n  [property: string]: any;\n}\n\n/**\n * @experimental context type representing a tradable product. To be used with OMS and EMS\n * systems.\n *\n * This type is currently only loosely defined as an extensible context object, with an\n * optional instrument field.\n *\n * The Product schema does not explicitly include identifiers in the id section, as there is\n * not a common standard for such identifiers. Applications can, however, populate this part\n * of the contract with custom identifiers if so desired.\n */\nexport interface Product {\n  /**\n   * One or more identifiers that refer to the product. Specific key names for systems are\n   * expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * A financial instrument that relates to the definition of this product\n   */\n  instrument?: InstrumentElement;\n  /**\n   * A human-readable summary of the product.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the product.\n   */\n  notes?: string;\n  type: 'fdc3.product';\n  [property: string]: any;\n}\n\n/**\n * A context representing a period of time. Any user interfaces that represent or visualize\n * events or activity over time can be filtered or focused on a particular time period,\n * e.g.:\n *\n * - A pricing chart\n * - A trade blotter\n * - A record of client contact/activity in a CRM\n *\n * Example use cases:\n *\n * - User may want to view pricing/trades/customer activity for a security over a particular\n * time period, the time range might be specified as the context for the `ViewChart` intent\n * OR it might be embedded in another context (e.g. a context representing a chart to plot).\n * - User filters a visualization (e.g. a pricing chart) to show a particular period, the\n * `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by\n * instrument, or industry sector etc.) receive it and filter themselves to show data over\n * the same range.\n *\n * Notes:\n *\n * - A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open\n * (i.e. only one of `startTime` or `endTime` is known).\n * - Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified\n * using times as this prevents issues with timezone conversions and inclusive/exclusive\n * date ranges.\n * - String fields representing times are encoded according to [ISO\n * 8601-1:2019](https://www.iso.org/standard/70907.html).\n * - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or\n * `\"2022-05-12T16:18:03+01:00\"`\n * - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n */\nexport interface TimeRange {\n  /**\n   * The end time of the range, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n   */\n  endTime?: Date;\n  /**\n   * The start time of the range, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n   */\n  startTime?: Date;\n  type: 'fdc3.timeRange';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * @experimental context type representing a trade. To be used with execution systems.\n *\n * This type currently only defines a required `id` field, which should provide a reference\n * to the trade in one or more systems, an optional human readable `name` field to be used\n * to summarize the trade and a required `product` field that may be used to provide\n * additional detail about the trade, which is currently typed as a unspecified Context\n * type, but `product` is expected to be standardized in future.\n *\n * The Trade schema does not explicitly include identifiers in the id section, as there is\n * not a common standard for such identifiers. Applications can, however, populate this part\n * of the contract with custom identifiers if so desired.\n */\nexport interface Trade {\n  /**\n   * One or more identifiers that refer to the trade in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * A human-readable summary of the trade.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the trade.\n   */\n  notes?: string;\n  /**\n   * A product that is the subject of the trade.\n   */\n  product: ProductObject;\n  type: 'fdc3.trade';\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * @experimental A list of trades. Use this type for use cases that require not just a\n * single trade, but multiple.\n *\n * The TradeList schema does not explicitly include identifiers in the id section, as there\n * is not a common standard for such identifiers. Applications can, however, populate this\n * part of the contract with custom identifiers if so desired.\n */\nexport interface TradeList {\n  /**\n   * One or more identifiers that refer to the trade list in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id?: { [key: string]: string };\n  /**\n   * An optional human-readable name for the trade list\n   */\n  name?: string;\n  /**\n   * An array of trade contexts that forms the list.\n   */\n  trades: TradeElement[];\n  type: 'fdc3.tradeList';\n  [property: string]: any;\n}\n\n/**\n * @experimental context type representing a trade. To be used with execution systems.\n *\n * This type currently only defines a required `id` field, which should provide a reference\n * to the trade in one or more systems, an optional human readable `name` field to be used\n * to summarize the trade and a required `product` field that may be used to provide\n * additional detail about the trade, which is currently typed as a unspecified Context\n * type, but `product` is expected to be standardized in future.\n *\n * The Trade schema does not explicitly include identifiers in the id section, as there is\n * not a common standard for such identifiers. Applications can, however, populate this part\n * of the contract with custom identifiers if so desired.\n */\nexport interface TradeElement {\n  /**\n   * One or more identifiers that refer to the trade in an OMS, EMS or related system.\n   * Specific key names for systems are expected to be standardized in future.\n   */\n  id: { [key: string]: string };\n  /**\n   * A human-readable summary of the trade.\n   */\n  name?: string;\n  /**\n   * Additional notes or comments about the trade.\n   */\n  notes?: string;\n  /**\n   * A product that is the subject of the trade.\n   */\n  product: ProductObject;\n  type: 'fdc3.trade';\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A context type representing the result of a transaction initiated via FDC3, which SHOULD\n * be returned as an `IntentResult` by intents that create, retrieve, update or delete\n * content or records in another application. Its purpose is to provide a status and message\n * (where needed) for the transaction and MAY wrap a returned context object.\n */\nexport interface TransactionResult {\n  /**\n   * A context object returned by the transaction, possibly with updated data.\n   */\n  context?: ContextElement;\n  /**\n   * A human readable message describing the outcome of the transaction.\n   */\n  message?: string;\n  /**\n   * The status of the transaction being reported.\n   */\n  status: TransactionStatus;\n  type: 'fdc3.transactionResult';\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * The status of the transaction being reported.\n */\nexport type TransactionStatus = 'Created' | 'Deleted' | 'Updated' | 'Failed';\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n/**\n * A context type representing the price and value of a holding.\n */\nexport interface Valuation {\n  /**\n   * The valuation currency, which should conform to 3 character alphabetic codes defined in\n   * [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\n   */\n  CURRENCY_ISOCODE: string;\n  /**\n   * The time at which this valuation expires, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n   */\n  expiryTime?: Date;\n  /**\n   * The price per unit the the valuation is based on.\n   */\n  price?: number;\n  type: 'fdc3.valuation';\n  /**\n   * The time at which the valuation was performed, encoded according to [ISO\n   * 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n   */\n  valuationTime?: Date;\n  /**\n   * The value of the holding, expresses in the nominated currency.\n   */\n  value: number;\n  id?: { [key: string]: any };\n  name?: string;\n  [property: string]: any;\n}\n\n/**\n * Free text to be used for a keyword search\n *\n * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or\n * `'Meeting'` although other string values are permitted.\n */\n\n// Converts JSON strings to/from your types\n// and asserts the results of JSON.parse at runtime\nexport class Convert {\n  public static toAction(json: string): Action {\n    return cast(JSON.parse(json), r('Action'));\n  }\n\n  public static actionToJson(value: Action): string {\n    return JSON.stringify(uncast(value, r('Action')), null, 2);\n  }\n\n  public static toChart(json: string): Chart {\n    return cast(JSON.parse(json), r('Chart'));\n  }\n\n  public static chartToJson(value: Chart): string {\n    return JSON.stringify(uncast(value, r('Chart')), null, 2);\n  }\n\n  public static toChatInitSettings(json: string): ChatInitSettings {\n    return cast(JSON.parse(json), r('ChatInitSettings'));\n  }\n\n  public static chatInitSettingsToJson(value: ChatInitSettings): string {\n    return JSON.stringify(uncast(value, r('ChatInitSettings')), null, 2);\n  }\n\n  public static toChatMessage(json: string): ChatMessage {\n    return cast(JSON.parse(json), r('ChatMessage'));\n  }\n\n  public static chatMessageToJson(value: ChatMessage): string {\n    return JSON.stringify(uncast(value, r('ChatMessage')), null, 2);\n  }\n\n  public static toChatRoom(json: string): ChatRoom {\n    return cast(JSON.parse(json), r('ChatRoom'));\n  }\n\n  public static chatRoomToJson(value: ChatRoom): string {\n    return JSON.stringify(uncast(value, r('ChatRoom')), null, 2);\n  }\n\n  public static toChatSearchCriteria(json: string): ChatSearchCriteria {\n    return cast(JSON.parse(json), r('ChatSearchCriteria'));\n  }\n\n  public static chatSearchCriteriaToJson(value: ChatSearchCriteria): string {\n    return JSON.stringify(uncast(value, r('ChatSearchCriteria')), null, 2);\n  }\n\n  public static toContact(json: string): Contact {\n    return cast(JSON.parse(json), r('Contact'));\n  }\n\n  public static contactToJson(value: Contact): string {\n    return JSON.stringify(uncast(value, r('Contact')), null, 2);\n  }\n\n  public static toContactList(json: string): ContactList {\n    return cast(JSON.parse(json), r('ContactList'));\n  }\n\n  public static contactListToJson(value: ContactList): string {\n    return JSON.stringify(uncast(value, r('ContactList')), null, 2);\n  }\n\n  public static toContext(json: string): Context {\n    return cast(JSON.parse(json), r('Context'));\n  }\n\n  public static contextToJson(value: Context): string {\n    return JSON.stringify(uncast(value, r('Context')), null, 2);\n  }\n\n  public static toCountry(json: string): Country {\n    return cast(JSON.parse(json), r('Country'));\n  }\n\n  public static countryToJson(value: Country): string {\n    return JSON.stringify(uncast(value, r('Country')), null, 2);\n  }\n\n  public static toCurrency(json: string): Currency {\n    return cast(JSON.parse(json), r('Currency'));\n  }\n\n  public static currencyToJson(value: Currency): string {\n    return JSON.stringify(uncast(value, r('Currency')), null, 2);\n  }\n\n  public static toEmail(json: string): Email {\n    return cast(JSON.parse(json), r('Email'));\n  }\n\n  public static emailToJson(value: Email): string {\n    return JSON.stringify(uncast(value, r('Email')), null, 2);\n  }\n\n  public static toFileAttachment(json: string): FileAttachment {\n    return cast(JSON.parse(json), r('FileAttachment'));\n  }\n\n  public static fileAttachmentToJson(value: FileAttachment): string {\n    return JSON.stringify(uncast(value, r('FileAttachment')), null, 2);\n  }\n\n  public static toInstrument(json: string): Instrument {\n    return cast(JSON.parse(json), r('Instrument'));\n  }\n\n  public static instrumentToJson(value: Instrument): string {\n    return JSON.stringify(uncast(value, r('Instrument')), null, 2);\n  }\n\n  public static toInstrumentList(json: string): InstrumentList {\n    return cast(JSON.parse(json), r('InstrumentList'));\n  }\n\n  public static instrumentListToJson(value: InstrumentList): string {\n    return JSON.stringify(uncast(value, r('InstrumentList')), null, 2);\n  }\n\n  public static toInteraction(json: string): Interaction {\n    return cast(JSON.parse(json), r('Interaction'));\n  }\n\n  public static interactionToJson(value: Interaction): string {\n    return JSON.stringify(uncast(value, r('Interaction')), null, 2);\n  }\n\n  public static toMessage(json: string): Message {\n    return cast(JSON.parse(json), r('Message'));\n  }\n\n  public static messageToJson(value: Message): string {\n    return JSON.stringify(uncast(value, r('Message')), null, 2);\n  }\n\n  public static toNothing(json: string): Nothing {\n    return cast(JSON.parse(json), r('Nothing'));\n  }\n\n  public static nothingToJson(value: Nothing): string {\n    return JSON.stringify(uncast(value, r('Nothing')), null, 2);\n  }\n\n  public static toOrder(json: string): Order {\n    return cast(JSON.parse(json), r('Order'));\n  }\n\n  public static orderToJson(value: Order): string {\n    return JSON.stringify(uncast(value, r('Order')), null, 2);\n  }\n\n  public static toOrderList(json: string): OrderList {\n    return cast(JSON.parse(json), r('OrderList'));\n  }\n\n  public static orderListToJson(value: OrderList): string {\n    return JSON.stringify(uncast(value, r('OrderList')), null, 2);\n  }\n\n  public static toOrganization(json: string): Organization {\n    return cast(JSON.parse(json), r('Organization'));\n  }\n\n  public static organizationToJson(value: Organization): string {\n    return JSON.stringify(uncast(value, r('Organization')), null, 2);\n  }\n\n  public static toPortfolio(json: string): Portfolio {\n    return cast(JSON.parse(json), r('Portfolio'));\n  }\n\n  public static portfolioToJson(value: Portfolio): string {\n    return JSON.stringify(uncast(value, r('Portfolio')), null, 2);\n  }\n\n  public static toPosition(json: string): Position {\n    return cast(JSON.parse(json), r('Position'));\n  }\n\n  public static positionToJson(value: Position): string {\n    return JSON.stringify(uncast(value, r('Position')), null, 2);\n  }\n\n  public static toProduct(json: string): Product {\n    return cast(JSON.parse(json), r('Product'));\n  }\n\n  public static productToJson(value: Product): string {\n    return JSON.stringify(uncast(value, r('Product')), null, 2);\n  }\n\n  public static toTimeRange(json: string): TimeRange {\n    return cast(JSON.parse(json), r('TimeRange'));\n  }\n\n  public static timeRangeToJson(value: TimeRange): string {\n    return JSON.stringify(uncast(value, r('TimeRange')), null, 2);\n  }\n\n  public static toTrade(json: string): Trade {\n    return cast(JSON.parse(json), r('Trade'));\n  }\n\n  public static tradeToJson(value: Trade): string {\n    return JSON.stringify(uncast(value, r('Trade')), null, 2);\n  }\n\n  public static toTradeList(json: string): TradeList {\n    return cast(JSON.parse(json), r('TradeList'));\n  }\n\n  public static tradeListToJson(value: TradeList): string {\n    return JSON.stringify(uncast(value, r('TradeList')), null, 2);\n  }\n\n  public static toTransactionResult(json: string): TransactionResult {\n    return cast(JSON.parse(json), r('TransactionResult'));\n  }\n\n  public static transactionResultToJson(value: TransactionResult): string {\n    return JSON.stringify(uncast(value, r('TransactionResult')), null, 2);\n  }\n\n  public static toValuation(json: string): Valuation {\n    return cast(JSON.parse(json), r('Valuation'));\n  }\n\n  public static valuationToJson(value: Valuation): string {\n    return JSON.stringify(uncast(value, r('Valuation')), null, 2);\n  }\n}\n\nfunction invalidValue(typ: any, val: any, key: any, parent: any = ''): never {\n  const prettyTyp = prettyTypeName(typ);\n  const parentText = parent ? ` on ${parent}` : '';\n  const keyText = key ? ` for key \"${key}\"` : '';\n  throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);\n}\n\nfunction prettyTypeName(typ: any): string {\n  if (Array.isArray(typ)) {\n    if (typ.length === 2 && typ[0] === undefined) {\n      return `an optional ${prettyTypeName(typ[1])}`;\n    } else {\n      return `one of [${typ\n        .map(a => {\n          return prettyTypeName(a);\n        })\n        .join(', ')}]`;\n    }\n  } else if (typeof typ === 'object' && typ.literal !== undefined) {\n    return typ.literal;\n  } else {\n    return typeof typ;\n  }\n}\n\nfunction jsonToJSProps(typ: any): any {\n  if (typ.jsonToJS === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.json] = { key: p.js, typ: p.typ }));\n    typ.jsonToJS = map;\n  }\n  return typ.jsonToJS;\n}\n\nfunction jsToJSONProps(typ: any): any {\n  if (typ.jsToJSON === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.js] = { key: p.json, typ: p.typ }));\n    typ.jsToJSON = map;\n  }\n  return typ.jsToJSON;\n}\n\nfunction transform(val: any, typ: any, getProps: any, key: any = '', parent: any = ''): any {\n  function transformPrimitive(typ: string, val: any): any {\n    if (typeof typ === typeof val) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n\n  function transformUnion(typs: any[], val: any): any {\n    // val must validate against one typ in typs\n    const l = typs.length;\n    for (let i = 0; i < l; i++) {\n      const typ = typs[i];\n      try {\n        return transform(val, typ, getProps);\n      } catch (_) {}\n    }\n    return invalidValue(typs, val, key, parent);\n  }\n\n  function transformEnum(cases: string[], val: any): any {\n    if (cases.indexOf(val) !== -1) return val;\n    return invalidValue(\n      cases.map(a => {\n        return l(a);\n      }),\n      val,\n      key,\n      parent\n    );\n  }\n\n  function transformArray(typ: any, val: any): any {\n    // val must be an array with no invalid elements\n    if (!Array.isArray(val)) return invalidValue(l('array'), val, key, parent);\n    return val.map(el => transform(el, typ, getProps));\n  }\n\n  function transformDate(val: any): any {\n    if (val === null) {\n      return null;\n    }\n    const d = new Date(val);\n    if (isNaN(d.valueOf())) {\n      return invalidValue(l('Date'), val, key, parent);\n    }\n    return d;\n  }\n\n  function transformObject(props: { [k: string]: any }, additional: any, val: any): any {\n    if (val === null || typeof val !== 'object' || Array.isArray(val)) {\n      return invalidValue(l(ref || 'object'), val, key, parent);\n    }\n    const result: any = {};\n    Object.getOwnPropertyNames(props).forEach(key => {\n      const prop = props[key];\n      const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;\n      result[prop.key] = transform(v, prop.typ, getProps, key, ref);\n    });\n    Object.getOwnPropertyNames(val).forEach(key => {\n      if (!Object.prototype.hasOwnProperty.call(props, key)) {\n        result[key] = transform(val[key], additional, getProps, key, ref);\n      }\n    });\n    return result;\n  }\n\n  if (typ === 'any') return val;\n  if (typ === null) {\n    if (val === null) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n  if (typ === false) return invalidValue(typ, val, key, parent);\n  let ref: any = undefined;\n  while (typeof typ === 'object' && typ.ref !== undefined) {\n    ref = typ.ref;\n    typ = typeMap[typ.ref];\n  }\n  if (Array.isArray(typ)) return transformEnum(typ, val);\n  if (typeof typ === 'object') {\n    return typ.hasOwnProperty('unionMembers')\n      ? transformUnion(typ.unionMembers, val)\n      : typ.hasOwnProperty('arrayItems')\n        ? transformArray(typ.arrayItems, val)\n        : typ.hasOwnProperty('props')\n          ? transformObject(getProps(typ), typ.additional, val)\n          : invalidValue(typ, val, key, parent);\n  }\n  // Numbers can be parsed by Date but shouldn't be.\n  if (typ === Date && typeof val !== 'number') return transformDate(val);\n  return transformPrimitive(typ, val);\n}\n\nfunction cast<T>(val: any, typ: any): T {\n  return transform(val, typ, jsonToJSProps);\n}\n\nfunction uncast<T>(val: T, typ: any): any {\n  return transform(val, typ, jsToJSONProps);\n}\n\nfunction l(typ: any) {\n  return { literal: typ };\n}\n\nfunction a(typ: any) {\n  return { arrayItems: typ };\n}\n\nfunction u(...typs: any[]) {\n  return { unionMembers: typs };\n}\n\nfunction o(props: any[], additional: any) {\n  return { props, additional };\n}\n\nfunction m(additional: any) {\n  return { props: [], additional };\n}\n\nfunction r(name: string) {\n  return { ref: name };\n}\n\nconst typeMap: any = {\n  Action: o(\n    [\n      { json: 'action', js: 'action', typ: u(undefined, r('ActionType')) },\n      { json: 'app', js: 'app', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'channelId', js: 'channelId', typ: u(undefined, '') },\n      { json: 'context', js: 'context', typ: r('ContextElement') },\n      { json: 'intent', js: 'intent', typ: u(undefined, '') },\n      { json: 'title', js: 'title', typ: '' },\n      { json: 'type', js: 'type', typ: r('ActionTypeEnum') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  AppIdentifier: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ContextElement: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    'any'\n  ),\n  Chart: o(\n    [\n      { json: 'instruments', js: 'instruments', typ: a(r('InstrumentElement')) },\n      { json: 'otherConfig', js: 'otherConfig', typ: u(undefined, a(r('ContextElement'))) },\n      { json: 'range', js: 'range', typ: u(undefined, r('TimeRangeObject')) },\n      { json: 'style', js: 'style', typ: u(undefined, r('ChartStyle')) },\n      { json: 'type', js: 'type', typ: r('ChartType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  InstrumentElement: o(\n    [\n      { json: 'id', js: 'id', typ: r('PurpleInstrumentIdentifiers') },\n      { json: 'market', js: 'market', typ: u(undefined, r('OrganizationMarket')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('PurpleInteractionType') },\n    ],\n    'any'\n  ),\n  PurpleInstrumentIdentifiers: o(\n    [\n      { json: 'BBG', js: 'BBG', typ: u(undefined, '') },\n      { json: 'CUSIP', js: 'CUSIP', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n      { json: 'FIGI', js: 'FIGI', typ: u(undefined, '') },\n      { json: 'ISIN', js: 'ISIN', typ: u(undefined, '') },\n      { json: 'PERMID', js: 'PERMID', typ: u(undefined, '') },\n      { json: 'RIC', js: 'RIC', typ: u(undefined, '') },\n      { json: 'SEDOL', js: 'SEDOL', typ: u(undefined, '') },\n      { json: 'ticker', js: 'ticker', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  OrganizationMarket: o(\n    [\n      { json: 'BBG', js: 'BBG', typ: u(undefined, '') },\n      { json: 'COUNTRY_ISOALPHA2', js: 'COUNTRY_ISOALPHA2', typ: u(undefined, '') },\n      { json: 'MIC', js: 'MIC', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  TimeRangeObject: o(\n    [\n      { json: 'endTime', js: 'endTime', typ: u(undefined, Date) },\n      { json: 'startTime', js: 'startTime', typ: u(undefined, Date) },\n      { json: 'type', js: 'type', typ: r('TimeRangeType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ChatInitSettings: o(\n    [\n      { json: 'chatName', js: 'chatName', typ: u(undefined, '') },\n      { json: 'members', js: 'members', typ: u(undefined, r('ContactListObject')) },\n      { json: 'message', js: 'message', typ: u(undefined, u(r('MessageObject'), '')) },\n      { json: 'options', js: 'options', typ: u(undefined, r('ChatOptions')) },\n      { json: 'type', js: 'type', typ: r('ChatInitSettingsType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ContactListObject: o(\n    [\n      { json: 'contacts', js: 'contacts', typ: a(r('ContactElement')) },\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('ContactListType') },\n    ],\n    'any'\n  ),\n  ContactElement: o(\n    [\n      { json: 'id', js: 'id', typ: r('PurpleContactIdentifiers') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('FluffyInteractionType') },\n    ],\n    'any'\n  ),\n  PurpleContactIdentifiers: o(\n    [\n      { json: 'email', js: 'email', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  MessageObject: o(\n    [\n      { json: 'entities', js: 'entities', typ: u(undefined, m(r('EntityValue'))) },\n      { json: 'text', js: 'text', typ: u(undefined, r('PurpleMessageText')) },\n      { json: 'type', js: 'type', typ: r('MessageType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  EntityValue: o(\n    [\n      { json: 'action', js: 'action', typ: u(undefined, r('ActionType')) },\n      { json: 'app', js: 'app', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'channelId', js: 'channelId', typ: u(undefined, '') },\n      { json: 'context', js: 'context', typ: u(undefined, r('ContextElement')) },\n      { json: 'intent', js: 'intent', typ: u(undefined, '') },\n      { json: 'title', js: 'title', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('EntityType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'data', js: 'data', typ: u(undefined, r('EntityData')) },\n    ],\n    'any'\n  ),\n  EntityData: o(\n    [\n      { json: 'dataUri', js: 'dataUri', typ: '' },\n      { json: 'name', js: 'name', typ: '' },\n    ],\n    'any'\n  ),\n  PurpleMessageText: o(\n    [\n      { json: 'text/markdown', js: 'text/markdown', typ: u(undefined, '') },\n      { json: 'text/plain', js: 'text/plain', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ChatOptions: o(\n    [\n      { json: 'allowAddUser', js: 'allowAddUser', typ: u(undefined, true) },\n      { json: 'allowHistoryBrowsing', js: 'allowHistoryBrowsing', typ: u(undefined, true) },\n      { json: 'allowMessageCopy', js: 'allowMessageCopy', typ: u(undefined, true) },\n      { json: 'groupRecipients', js: 'groupRecipients', typ: u(undefined, true) },\n      { json: 'isPublic', js: 'isPublic', typ: u(undefined, true) },\n    ],\n    'any'\n  ),\n  ChatMessage: o(\n    [\n      { json: 'chatRoom', js: 'chatRoom', typ: r('ChatRoomObject') },\n      { json: 'message', js: 'message', typ: r('MessageObject') },\n      { json: 'type', js: 'type', typ: r('ChatMessageType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ChatRoomObject: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'providerName', js: 'providerName', typ: '' },\n      { json: 'type', js: 'type', typ: r('ChatRoomType') },\n      { json: 'url', js: 'url', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ChatRoom: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'providerName', js: 'providerName', typ: '' },\n      { json: 'type', js: 'type', typ: r('ChatRoomType') },\n      { json: 'url', js: 'url', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ChatSearchCriteria: o(\n    [\n      { json: 'criteria', js: 'criteria', typ: a(u(r('OrganizationObject'), '')) },\n      { json: 'type', js: 'type', typ: r('ChatSearchCriteriaType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  OrganizationObject: o(\n    [\n      { json: 'id', js: 'id', typ: r('Identifiers') },\n      { json: 'market', js: 'market', typ: u(undefined, r('OrganizationMarket')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('TentacledInteractionType') },\n    ],\n    'any'\n  ),\n  Identifiers: o(\n    [\n      { json: 'BBG', js: 'BBG', typ: u(undefined, '') },\n      { json: 'CUSIP', js: 'CUSIP', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n      { json: 'FIGI', js: 'FIGI', typ: u(undefined, '') },\n      { json: 'ISIN', js: 'ISIN', typ: u(undefined, '') },\n      { json: 'PERMID', js: 'PERMID', typ: u(undefined, '') },\n      { json: 'RIC', js: 'RIC', typ: u(undefined, '') },\n      { json: 'SEDOL', js: 'SEDOL', typ: u(undefined, '') },\n      { json: 'ticker', js: 'ticker', typ: u(undefined, '') },\n      { json: 'LEI', js: 'LEI', typ: u(undefined, '') },\n      { json: 'email', js: 'email', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Contact: o(\n    [\n      { json: 'id', js: 'id', typ: r('FluffyContactIdentifiers') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('FluffyInteractionType') },\n    ],\n    'any'\n  ),\n  FluffyContactIdentifiers: o(\n    [\n      { json: 'email', js: 'email', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ContactList: o(\n    [\n      { json: 'contacts', js: 'contacts', typ: a(r('ContactElement')) },\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('ContactListType') },\n    ],\n    'any'\n  ),\n  Context: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    'any'\n  ),\n  Country: o(\n    [\n      { json: 'id', js: 'id', typ: r('CountryID') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('CountryType') },\n    ],\n    'any'\n  ),\n  CountryID: o(\n    [\n      { json: 'COUNTRY_ISOALPHA2', js: 'COUNTRY_ISOALPHA2', typ: u(undefined, '') },\n      { json: 'COUNTRY_ISOALPHA3', js: 'COUNTRY_ISOALPHA3', typ: u(undefined, '') },\n      { json: 'ISOALPHA2', js: 'ISOALPHA2', typ: u(undefined, '') },\n      { json: 'ISOALPHA3', js: 'ISOALPHA3', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Currency: o(\n    [\n      { json: 'id', js: 'id', typ: r('CurrencyID') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('CurrencyType') },\n    ],\n    'any'\n  ),\n  CurrencyID: o([{ json: 'CURRENCY_ISOCODE', js: 'CURRENCY_ISOCODE', typ: u(undefined, '') }], 'any'),\n  Email: o(\n    [\n      { json: 'recipients', js: 'recipients', typ: r('EmailRecipients') },\n      { json: 'subject', js: 'subject', typ: u(undefined, '') },\n      { json: 'textBody', js: 'textBody', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('EmailType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  EmailRecipients: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, r('ContactTIdentifiers')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('EmailRecipientsType') },\n      { json: 'contacts', js: 'contacts', typ: u(undefined, a(r('ContactElement'))) },\n    ],\n    'any'\n  ),\n  ContactTIdentifiers: o(\n    [\n      { json: 'email', js: 'email', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FileAttachment: o(\n    [\n      { json: 'data', js: 'data', typ: r('FileAttachmentData') },\n      { json: 'type', js: 'type', typ: r('FileAttachmentType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FileAttachmentData: o(\n    [\n      { json: 'dataUri', js: 'dataUri', typ: '' },\n      { json: 'name', js: 'name', typ: '' },\n    ],\n    'any'\n  ),\n  Instrument: o(\n    [\n      { json: 'id', js: 'id', typ: r('FluffyInstrumentIdentifiers') },\n      { json: 'market', js: 'market', typ: u(undefined, r('PurpleMarket')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('PurpleInteractionType') },\n    ],\n    'any'\n  ),\n  FluffyInstrumentIdentifiers: o(\n    [\n      { json: 'BBG', js: 'BBG', typ: u(undefined, '') },\n      { json: 'CUSIP', js: 'CUSIP', typ: u(undefined, '') },\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n      { json: 'FIGI', js: 'FIGI', typ: u(undefined, '') },\n      { json: 'ISIN', js: 'ISIN', typ: u(undefined, '') },\n      { json: 'PERMID', js: 'PERMID', typ: u(undefined, '') },\n      { json: 'RIC', js: 'RIC', typ: u(undefined, '') },\n      { json: 'SEDOL', js: 'SEDOL', typ: u(undefined, '') },\n      { json: 'ticker', js: 'ticker', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  PurpleMarket: o(\n    [\n      { json: 'BBG', js: 'BBG', typ: u(undefined, '') },\n      { json: 'COUNTRY_ISOALPHA2', js: 'COUNTRY_ISOALPHA2', typ: u(undefined, '') },\n      { json: 'MIC', js: 'MIC', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  InstrumentList: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'instruments', js: 'instruments', typ: a(r('InstrumentElement')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('InstrumentListType') },\n    ],\n    'any'\n  ),\n  Interaction: o(\n    [\n      { json: 'description', js: 'description', typ: '' },\n      { json: 'id', js: 'id', typ: u(undefined, r('InteractionID')) },\n      { json: 'initiator', js: 'initiator', typ: u(undefined, r('ContactElement')) },\n      { json: 'interactionType', js: 'interactionType', typ: '' },\n      { json: 'origin', js: 'origin', typ: u(undefined, '') },\n      { json: 'participants', js: 'participants', typ: r('ContactListObject') },\n      { json: 'timeRange', js: 'timeRange', typ: r('TimeRangeObject') },\n      { json: 'type', js: 'type', typ: r('InteractionType') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  InteractionID: o(\n    [\n      { json: 'SALESFORCE', js: 'SALESFORCE', typ: u(undefined, '') },\n      { json: 'SINGLETRACK', js: 'SINGLETRACK', typ: u(undefined, '') },\n      { json: 'URI', js: 'URI', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Message: o(\n    [\n      { json: 'entities', js: 'entities', typ: u(undefined, m(r('EntityValue'))) },\n      { json: 'text', js: 'text', typ: u(undefined, r('FluffyMessageText')) },\n      { json: 'type', js: 'type', typ: r('MessageType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FluffyMessageText: o(\n    [\n      { json: 'text/markdown', js: 'text/markdown', typ: u(undefined, '') },\n      { json: 'text/plain', js: 'text/plain', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Nothing: o(\n    [\n      { json: 'type', js: 'type', typ: r('NothingType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Order: o(\n    [\n      { json: 'details', js: 'details', typ: u(undefined, r('PurpleOrderDetails')) },\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('OrderType') },\n    ],\n    'any'\n  ),\n  PurpleOrderDetails: o([{ json: 'product', js: 'product', typ: u(undefined, r('ProductObject')) }], 'any'),\n  ProductObject: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'instrument', js: 'instrument', typ: u(undefined, r('InstrumentElement')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('ProductType') },\n    ],\n    'any'\n  ),\n  OrderList: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'orders', js: 'orders', typ: a(r('OrderElement')) },\n      { json: 'type', js: 'type', typ: r('OrderListType') },\n    ],\n    'any'\n  ),\n  OrderElement: o(\n    [\n      { json: 'details', js: 'details', typ: u(undefined, r('FluffyOrderDetails')) },\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('OrderType') },\n    ],\n    'any'\n  ),\n  FluffyOrderDetails: o([{ json: 'product', js: 'product', typ: u(undefined, r('ProductObject')) }], 'any'),\n  Organization: o(\n    [\n      { json: 'id', js: 'id', typ: r('OrganizationIdentifiers') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('StickyInteractionType') },\n    ],\n    'any'\n  ),\n  OrganizationIdentifiers: o(\n    [\n      { json: 'FDS_ID', js: 'FDS_ID', typ: u(undefined, '') },\n      { json: 'LEI', js: 'LEI', typ: u(undefined, '') },\n      { json: 'PERMID', js: 'PERMID', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Portfolio: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'positions', js: 'positions', typ: a(r('PositionElement')) },\n      { json: 'type', js: 'type', typ: r('PortfolioType') },\n    ],\n    'any'\n  ),\n  PositionElement: o(\n    [\n      { json: 'holding', js: 'holding', typ: 3.14 },\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'instrument', js: 'instrument', typ: r('InstrumentElement') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('PositionType') },\n    ],\n    'any'\n  ),\n  Position: o(\n    [\n      { json: 'holding', js: 'holding', typ: 3.14 },\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'instrument', js: 'instrument', typ: r('InstrumentElement') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('PositionType') },\n    ],\n    'any'\n  ),\n  Product: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'instrument', js: 'instrument', typ: u(undefined, r('InstrumentElement')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: r('ProductType') },\n    ],\n    'any'\n  ),\n  TimeRange: o(\n    [\n      { json: 'endTime', js: 'endTime', typ: u(undefined, Date) },\n      { json: 'startTime', js: 'startTime', typ: u(undefined, Date) },\n      { json: 'type', js: 'type', typ: r('TimeRangeType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Trade: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'product', js: 'product', typ: r('ProductObject') },\n      { json: 'type', js: 'type', typ: r('TradeType') },\n    ],\n    'any'\n  ),\n  TradeList: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'trades', js: 'trades', typ: a(r('TradeElement')) },\n      { json: 'type', js: 'type', typ: r('TradeListType') },\n    ],\n    'any'\n  ),\n  TradeElement: o(\n    [\n      { json: 'id', js: 'id', typ: m('') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'notes', js: 'notes', typ: u(undefined, '') },\n      { json: 'product', js: 'product', typ: r('ProductObject') },\n      { json: 'type', js: 'type', typ: r('TradeType') },\n    ],\n    'any'\n  ),\n  TransactionResult: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('ContextElement')) },\n      { json: 'message', js: 'message', typ: u(undefined, '') },\n      { json: 'status', js: 'status', typ: r('TransactionStatus') },\n      { json: 'type', js: 'type', typ: r('TransactionResultType') },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Valuation: o(\n    [\n      { json: 'CURRENCY_ISOCODE', js: 'CURRENCY_ISOCODE', typ: '' },\n      { json: 'expiryTime', js: 'expiryTime', typ: u(undefined, Date) },\n      { json: 'price', js: 'price', typ: u(undefined, 3.14) },\n      { json: 'type', js: 'type', typ: r('ValuationType') },\n      { json: 'valuationTime', js: 'valuationTime', typ: u(undefined, Date) },\n      { json: 'value', js: 'value', typ: 3.14 },\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  ActionType: ['broadcast', 'raiseIntent'],\n  ActionTypeEnum: ['fdc3.action'],\n  PurpleInteractionType: ['fdc3.instrument'],\n  TimeRangeType: ['fdc3.timeRange'],\n  ChartStyle: ['bar', 'candle', 'custom', 'heatmap', 'histogram', 'line', 'mountain', 'pie', 'scatter', 'stacked-bar'],\n  ChartType: ['fdc3.chart'],\n  FluffyInteractionType: ['fdc3.contact'],\n  ContactListType: ['fdc3.contactList'],\n  EntityType: ['fdc3.action', 'fdc3.fileAttachment'],\n  MessageType: ['fdc3.message'],\n  ChatInitSettingsType: ['fdc3.chat.initSettings'],\n  ChatRoomType: ['fdc3.chat.room'],\n  ChatMessageType: ['fdc3.chat.message'],\n  TentacledInteractionType: ['fdc3.contact', 'fdc3.instrument', 'fdc3.organization'],\n  ChatSearchCriteriaType: ['fdc3.chat.searchCriteria'],\n  CountryType: ['fdc3.country'],\n  CurrencyType: ['fdc3.currency'],\n  EmailRecipientsType: ['fdc3.contact', 'fdc3.contactList'],\n  EmailType: ['fdc3.email'],\n  FileAttachmentType: ['fdc3.fileAttachment'],\n  InstrumentListType: ['fdc3.instrumentList'],\n  InteractionType: ['fdc3.interaction'],\n  NothingType: ['fdc3.nothing'],\n  ProductType: ['fdc3.product'],\n  OrderType: ['fdc3.order'],\n  OrderListType: ['fdc3.orderList'],\n  StickyInteractionType: ['fdc3.organization'],\n  PositionType: ['fdc3.position'],\n  PortfolioType: ['fdc3.portfolio'],\n  TradeType: ['fdc3.trade'],\n  TradeListType: ['fdc3.tradeList'],\n  TransactionStatus: ['Created', 'Deleted', 'Failed', 'Updated'],\n  TransactionResultType: ['fdc3.transactionResult'],\n  ValuationType: ['fdc3.valuation'],\n};\n"
  },
  {
    "path": "packages/fdc3-context/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-context\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"type\": \"module\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/src/index.d.ts\",\n      \"import\": \"./dist/src/index.js\",\n      \"require\": \"./dist/src/index.js\"\n    }\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"clean\": \"rimraf dist generated coverage\",\n    \"mkdirs\": \"npx mkdirp generated/context\",\n    \"generate\": \"npm run mkdirs && npm run typegen && npm run lint\",\n    \"build\": \"npm run generate && tsc\",\n    \"lint\": \"eslint generated/ --fix && npx prettier generated/ --write\",\n    \"test\": \"npm run generate && tsc && vitest run\",\n    \"test:watch\": \"vitest\",\n    \"typegen\": \"cd schemas && node ../s2tQuicktypeUtil.cjs context ../generated/context/ContextTypes.ts\"\n  },\n  \"devDependencies\": {\n    \"ajv\": \"^8.18.0\",\n    \"ajv-formats\": \"^3.0.1\",\n    \"mkdirp\": \"^3.0.1\",\n    \"quicktype\": \"23.0.78\",\n    \"tslib\": \"^2.7.0\"\n  },\n  \"overrides\": {\n    \"ajv-formats\": {\n      \"ajv\": \"8.18.0\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-context/s2tQuicktypeUtil.cjs",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/** Utility for preparing arguments to quicktype, which workaround a specific\n * quicktype bug in command line argument handling (where a directory is used\n * as input the source language argument is ignored which causes our schemas\n * to be interpreted as JSON input, rather than JSONSchema).\n *\n * Individual file arguments will be interpreted as 'additional' schema files\n * that will be referenced from the other schemas and will not have top-level output\n * schemas generated, while folders will be listed and the schema files they contain\n * added as inputs and will have top-level types generated.\n *\n *  */\n\nconst path = require('path');\nconst fs = require('fs');\nconst { forEachChild } = require('typescript');\nconst exec = require('child_process').exec;\n\nconst args = process.argv.slice(2);\nconst outputFile = args.pop();\nconst inputs = args;\nconst toProcess = [];\n\nconsole.log('Inputs schema files: ' + inputs.join(' | '));\nconsole.log('Output file argument: ' + outputFile);\n\nlet sources = '';\nlet additionalSchemaFiles = '';\n\n//skip duplicate paths (we might want to specify some files to go first, and might duplicate them)\nconst allPaths = new Set();\n\nconst addAPath = (aPath, paths, sources, type) => {\n  if (!paths.has(aPath)) {\n    paths.add(aPath);\n    return sources + ` ${type} ${aPath}`;\n  } else {\n    console.log(`skipping duplicate path ${aPath}`);\n    return sources;\n  }\n};\n\n//process the content of folders to produce code for top-level types\nlet inputIndex = 0;\nwhile (inputIndex < inputs.length) {\n  if (inputs[inputIndex].endsWith('.schema.json')) {\n    //add individual files with -S as additional schema files used in references (rather than ones that need a top-level output)\n    additionalSchemaFiles = addAPath(path.join(inputs[inputIndex]), allPaths, additionalSchemaFiles, '-S');\n  } else {\n    fs.readdirSync(inputs[inputIndex], { withFileTypes: true }).forEach(file => {\n      if (file.isDirectory()) {\n        inputs.push(path.join(inputs[inputIndex], file.name));\n      } else if (file.name.endsWith('.schema.json')) {\n        sources = addAPath(path.join(inputs[inputIndex], file.name), allPaths, sources, '--src');\n      }\n    });\n  }\n  inputIndex++;\n}\n\n// Normalise path to local quicktype executable.\n//const quicktypeExec = \"node \" + [\"..\",\"quicktype\",\"dist\",\"index.js\"].join(path.sep);\nconst quicktypeExec = ['..', '..', '..', 'node_modules', '.bin', 'quicktype'].join(path.sep);\n\nconst command = `${quicktypeExec} --prefer-const-values --prefer-unions -s schema -o ${outputFile} ${additionalSchemaFiles} ${sources}`;\nconsole.log('command to run: ' + command);\n\nexec(command, function (error, stdout, stderr) {\n  if (stdout) {\n    console.log(stdout);\n  }\n  if (stderr) {\n    console.log(stderr);\n  }\n});\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/action.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/action.schema.json\",\n  \"title\": \"Action\",\n  \"description\": \"A representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\\n\\nThe action may be completed by calling:\\n- `fdc3.raiseIntent()` with the specified Intent and Context\\n- `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\\n- `channel.broadcast()` with the specified Context, if the `broadcast` action has been defined.\\n\\nAccepts an optional `app` parameter in order to specify a specific app.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.action\" },\n        \"action\": {\n          \"title\": \"Action Type\",\n          \"description\": \"The **action** field indicates the type of action:\\n- **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent` or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if given).\\n- **broadcast** : If `broadcast` and a `channelId` are specified then `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the context to it with `channel.broadcast(context)`. If no `channelId` has been specified, the context should be broadcast to the current channel (`fdc3.broadcast()`)\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"broadcast\",\n            \"raiseIntent\"\n          ]\n        },\n        \"title\": {\n          \"title\": \"Action Title\",\n          \"description\": \"A human readable display name for the action\",\n          \"type\": \"string\"\n        },\n        \"intent\": {\n          \"title\": \"Action Intent\",\n          \"description\": \"Optional Intent to raise to perform the actions. Should reference an intent type name, such as those defined in the FDC3 Standard. If intent is not set then `fdc3.raiseIntentForContext` should be used to perform the action as this will usually allow the user to choose the intent to raise.\",\n          \"type\": \"string\"\n        },\n        \"context\": {\n          \"title\": \"Action Context\",\n          \"description\": \"A context object with which the action will be performed\",\n          \"$ref\": \"context.schema.json#\"\n        },\n        \"channelId\": {\n          \"title\": \"Channel ID\",\n          \"description\": \"Optional channel on which to broadcast the context. The `channelId` property is ignored unless the `action` is broadcast.\",\n          \"type\": \"string\"\n        },\n        \"app\": {\n          \"title\": \"Action Target App\",\n          \"description\": \"An optional target application identifier that should perform the action. The `app` property is ignored unless the action is raiseIntent.\",\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\n        \"title\", \"context\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.action\",\n      \"action\": \"raiseIntent\",\n      \"title\": \"Click to view Chart\",\n      \"intent\": \"ViewChart\",\n      \"context\": {\n          \"type\": \"fdc3.chart\",\n          \"instruments\": [\n              {\n                  \"type\": \"fdc3.instrument\",\n                  \"id\": {\n                      \"ticker\": \"EURUSD\"\n                  }\n              }\n          ],\n          \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n          },\n          \"style\": \"candle\"\n      },\n      \"app\" :{\n          \"appId\": \"MyChartViewingApp\",\n          \"instanceId\": \"instance1\"\n      }\n    },\n    {\n      \"type\": \"fdc3.action\",\n      \"action\": \"broadcast\",\n      \"channelId\": \"Channel 1\",\n      \"title\": \"Click to view Chart\",\n      \"context\": {\n          \"type\": \"fdc3.chart\",\n          \"instruments\": [\n              {\n                  \"type\": \"fdc3.instrument\",\n                  \"id\": {\n                      \"ticker\": \"EURUSD\"\n                  }\n              }\n          ],\n          \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n          },\n          \"style\": \"candle\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/chart.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/chart.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chart\",\n  \"description\": \"A context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\\n\\n- A list of instruments for comparison\\n- The time period to plot the chart over\\n- The style of chart (line, bar, mountain, candle etc.)\\n- Other settings such as indicators to calculate, or data representing drawings and annotations.\\n\\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chart\" },\n        \"instruments\": {\n          \"title\": \"Instruments to plot\",\n          \"description\": \"An array of instrument contexts whose data should be plotted.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        },\n        \"range\": {\n          \"title\": \"Time Range\",\n          \"description\": \"The time range that should be plotted\",\n          \"$ref\": \"timeRange.schema.json#\"\n        },\n        \"style\": {\n          \"title\": \"Chart style\",\n          \"description\": \"The type of chart that should be plotted\",\n          \"type\": \"string\",\n          \"enum\": [\t\"line\", \"bar\", \"stacked-bar\", \"mountain\", \"candle\", \"pie\", \"scatter\", \"histogram\", \"heatmap\", \"custom\"]\n        },\n        \"otherConfig\": {\n          \"title\": \"Other configuration\",\n          \"description\": \"It is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"context.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\"instruments\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chart\",\n      \"instruments\": [\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"AAPL\"\n              }\n          },\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"GOOG\"\n              }\n          }\n      ],\n      \"range\": {\n          \"type\": \"fdc3.timeRange\",\n          \"startTime\": \"2020-09-01T08:00:00.000Z\",\n          \"endTime\": \"2020-10-31T08:00:00.000Z\"\n      },\n      \"style\": \"line\",\n      \"otherConfig\": [\n          {\n              \"type\": \"somevendor.someproduct.indicator\",\n              \"name\": \"stddev\",\n              \"parameters\": {\n                  \"period\": 10,\n                  \"matype\": \"exponential\"\n              }\n          },\n          {\n              \"type\": \"someothervendor.someotherproduct.formula\",\n              \"formula\": \"standard-deviation\",\n              \"fields\": {\n                  \"lookback\": 10,\n                  \"type\": \"ema\"\n              }\n          }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/chatInitSettings.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/chatInitSettings.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatInitSettings\",\n  \"description\": \"A collection of settings to start a new chat conversation\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.initSettings\" },\n        \"chatName\": {\n          \"title\": \"Chat name\",\n          \"description\": \"Name to apply to the chat created\",\n          \"type\": \"string\"\n        },\n        \"members\": {\n          \"title\": \"Chat members\",\n          \"description\": \"Contacts to add to the chat\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"message\": {\n          \"title\": \"Initial chat message\",\n          \"description\": \"An initial message to post in the chat when created.\",\n          \"oneOf\": [\n            {\n              \"type\": \"string\"\n            },\n            {\n              \"$ref\": \"message.schema.json#\"\n            }\n          ]\n        },\n        \"options\": {\n          \"title\": \"Chat options\",\n          \"description\": \"Option settings that affect the creation of the chat\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"groupRecipients\": {\n              \"title\": \"Group recipients option\",\n              \"description\": \"if false a separate chat will be created for each member\",\n              \"type\": \"boolean\"\n            },\n            \"isPublic\": {\n              \"title\": \"Public chat option\",\n              \"description\": \"if true the room will be visible to everyone in the chat application\",\n              \"type\": \"boolean\"\n            },\n            \"allowHistoryBrowsing\":  {\n              \"title\": \"Allow history browsing option\",\n              \"description\": \"if true members will be allowed to browse past messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowMessageCopy\":  {\n              \"title\": \"Allow message copy option\",\n              \"description\": \"if true members will be allowed to copy/paste messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowAddUser\":  {\n              \"title\": \"All adding users option\",\n              \"description\": \"if true members will be allowed to add other members to the chat\",\n              \"type\": \"boolean\"\n            }\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.initSettings\",\n      \"chatName\": \"Chat ABCD\",\n      \"members\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john@mail.com\"\n            }\n          }\n        ]\n      },\n      \"options\": {\n        \"groupRecipients\": true,\n        \"isPublic\": false,\n        \"allowHistoryBrowsing\": true,\n        \"allowMessageCopy\": true\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n          \"0\": {\n            \"type\": \"fdc3.fileAttachment\",\n            \"data\": {\n              \"name\": \"myImage.png\",\n              \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n            }\n          }\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/chatMessage.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/chatMessage.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatMessage\",\n  \"description\": \"A context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.message\" },\n        \"chatRoom\": { \"$ref\": \"chatRoom.schema.json#\" },\n        \"message\": { \"$ref\": \"message.schema.json#\" }\n      },\n      \"required\": [\"type\", \"chatRoom\", \"message\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [{\n      \"type\": \"fdc3.chat.message\",\n      \"chatRoom\": {\n          \"type\": \"fdc3.chat.room\",\n          \"providerName\": \"Symphony\",\n          \"id\": {\n              \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n          }\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n           \"0\": {\n               \"type\": \"fdc3.fileAttachment\",\n                \"data\": {\n                \"name\": \"myImage.png\",\n                      \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n                }\n            }\n        }\n      }\n  }]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/chatRoom.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/chatRoom.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatRoom\",\n  \"description\": \"Reference to the chat room which could be used to send a message to the room\",\n  \"allOf\": [{\n    \"type\": \"object\",\n    \"properties\": {      \n      \"type\": { \"const\": \"fdc3.chat.room\" },\n      \"providerName\": { \n        \"title\": \"Chat provider name\",\n        \"description\": \"The name of the service that hosts the chat\",\n        \"type\": \"string\"\n      },\n      \"id\": { \n        \"title\": \"Chat room id\",\n        \"description\": \"Identifier(s) for the chat - currently unstandardized\",\n        \"type\": \"object\",\n        \"additionalProperties\": {\n          \"type\": \"string\"\n        }\n      },\n      \"url\": { \n        \"title\": \"Chat URL\",\n        \"description\": \"Universal url to access to the room. It could be opened from a browser, a mobile app, etc...\",\n        \"type\": \"string\",\n        \"format\": \"uri\"\n      },\n      \"name\": {\n        \"title\": \"Chat name\",\n        \"description\": \"Display name for the chat room\",\n        \"type\": \"string\"\n      }\n    },\n    \"required\": [\"providerName\", \"id\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.room\",\n      \"providerName\": \"Symphony\",\n      \"id\": {\n          \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n      },\n      \"url\": \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n      \"name\": \"My new room\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/chatSearchCriteria.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/chatSearchCriteria.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatSearchCriteria\",\n  \"description\": \"A context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.chat.searchCriteria\"\n        },\n        \"criteria\": {\n          \"title\": \"Search Criteria array\",\n          \"description\": \"An array of criteria that should match chats returned from by a search.\\n\\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\\n\\nEmpty search criteria can be supported to allow resetting of filters.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/$defs/SearchCriteria\"\n          }\n        }\n      },\n      \"required\": [\n        \"criteria\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"$defs\": {\n    \"SearchCriteria\": {\n      \"title\": \"Search Criteria\",\n      \"description\": \"An individual criteria against which to match chat messages, based on an FDC3 context or free-text string.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"instrument.schema.json#\"\n        },\n        {\n          \"$ref\": \"organization.schema.json#\"\n        },\n        {\n          \"$ref\": \"contact.schema.json#\"\n        },\n        {\n          \"type\": \"string\",\n          \"title\": \"Free text\",\n          \"description\": \"Free text to be used for a keyword search\"\n        }\n      ]\n    }\n  },\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.searchCriteria\",\n      \"criteria\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"TSLA\"\n          },\n          \"name\": \"Tesla, inc.\"\n        },\n        \"annual return\"\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"description\": \"A person contact that can be engaged with through email, calling, messaging, CMS, etc.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contact\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Contact Identifiers\",\n          \"description\": \"Identifiers that relate to the Contact represented by this context\",\n          \"properties\": {\n            \"email\": {\n              \"type\": \"string\",\n              \"format\": \"email\",\n              \"title\": \"Email address\",\n              \"description\": \"The email address for the contact\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FDS ID\",\n              \"description\": \"FactSet Permanent Identifier representing the contact\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the contact\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"description\": \"A collection of contacts, e.g. for chatting to or calling multiple contacts.\\n\\nThe contact list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contactList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Contact List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the contact list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the contact list\"\n        },\n        \"contacts\": {\n          \"type\": \"array\",\n          \"title\": \"List of Contacts\",\n          \"description\": \"An array of contact contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"contact.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"contacts\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contactList\",\n      \"contacts\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"John Doe\",\n          \"id\": {\n            \"email\": \"john.doe@mail.com\"\n          }\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"description\": \"The `fdc3.context` type defines the basic contract or \\\"shape\\\" for all data exchanged by FDC3 operations. As such, it is not really meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\\n\\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the object represents, and what shape it has.\\n\\nThe FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/definitions/DocumentedContext\"\n    },\n    {\n      \"$ref\": \"#/definitions/BaseContext\"\n    }\n  ],\n  \"definitions\": {\n    \"BaseContext\": {\n      \"$comment\": \"Base definition for the Context object WITHOUT documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\"\n        },\n        \"name\": {\n          \"type\": \"string\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"unevaluatedProperties\": {\"type\": \"string\" }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    },\n    \"DocumentedContext\": {\n      \"$comment\": \"Base definition for the Context object WITH documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"Type\",\n          \"description\": \"The type property is the only _required_ part of the FDC3 context data schema. The FDC3 [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present to route shared context data appropriately.\\n\\nFDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data types they support in an FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery and routing.\\n\\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an organization-specific namespace, e.g. `blackrock.fund`.\\n\\nSee the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more information about context data types.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"Context data objects may include a name property that can be used for more information, or display purposes. Some derived types may require the name object as mandatory, depending on use case.\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Id\",\n          \"description\": \"Context data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\\n\\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier. Identifier values SHOULD always be of type string.\",\n          \"unevaluatedProperties\": {\"type\": \"string\" }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"description\": \"A country entity.\\n\\nNotes:\\n\\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement is for at least one standardized identifier to be provided\\n\\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\\n\\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.country\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code\"\n            },\n            \"COUNTRY_ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code\"\n            },\n            \"ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            },\n            \"ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the country\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.country\",\n      \"name\": \"Sweden\",\n      \"id\": {\n        \"COUNTRY_ISOALPHA2\": \"SE\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/currency.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/currency.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Currency\",\n  \"description\": \"A context representing an individual Currency.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.currency\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Currency name\",\n          \"description\": \"The name of the currency for display purposes\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"CURRENCY_ISOCODE\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[A-Z]{3}$\",\n              \"title\": \"CURRENCY_ISOCODE\",\n              \"description\": \"The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.currency\",\n      \"name\": \"US Dollar\",\n      \"id\": {\n        \"CURRENCY_ISOCODE\": \"USD\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/email.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/email.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Email\",\n  \"description\": \"A collection of information to be used to initiate an email with a Contact or ContactList.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.email\"\n        },\n        \"recipients\": {\n          \"title\": \"Email Recipients\",\n          \"description\": \"One or more recipients for the email.\",\n          \"oneOf\": [\n            {\n              \"$ref\": \"contact.schema.json#\"\n            },\n            {\n              \"$ref\": \"contactList.schema.json#\"\n            }\n          ]\n        },\n        \"subject\": {\n          \"title\": \"Email Subject\",\n          \"description\": \"Subject line for the email.\",\n          \"type\": \"string\"\n        },\n        \"textBody\": {\n          \"title\": \"Email Body\",\n          \"description\": \"Body content for the email.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"recipients\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.email\",\n      \"recipients\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@example.com\"\n        }\n      },\n      \"subject\": \"The information you requested\",\n      \"textBody\": \"Blah, blah, blah ...\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/fileAttachment.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/fileAttachment.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"File Attachment\",\n  \"description\": \"A File attachment encoded in the form of a data URI. Can be added to a Message.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.fileAttachment\"\n        },\n        \"data\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"name\": {\n              \"type\": \"string\",\n              \"title\": \"File name\",\n              \"description\": \"The name of the attached file\"\n            },\n            \"dataUri\": {\n              \"type\": \"string\",\n              \"format\": \"uri\",\n              \"title\": \"\",\n              \"description\": \"A data URI encoding the content of the file to be attached\"\n            }\n          },\n          \"required\": [\n            \"name\",\n            \"dataUri\"\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"data\"\n      ]\n    },\n    {\n      \"$ref\": \"context.schema.json#/definitions/BaseContext\"\n    }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.fileAttachment\",\n      \"data\": {\n        \"name\": \"myImage.png\",\n        \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"description\": \"A financial instrument from any asset class.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrument\"\n        },\n        \"id\": {\n          \"title\": \"Instrument identifiers\",\n          \"description\": \"Any combination of instrument identifiers can be used together to resolve ambiguity, or for a better match. Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified. In general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\\n\\nIt is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement is for at least one instrument identifier to be provided.\\n\\nTry to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define a property that makes it clear what the value represents. Doing so will make interpretation easier for the developers of target applications.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg security\",\n              \"description\": \"https://www.bloomberg.com/\"\n            },\n            \"CUSIP\": {\n              \"type\": \"string\",\n              \"title\": \"CUSIP\",\n              \"description\": \"https://www.cusip.com/\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FactSet Permanent Security Identifier\",\n              \"description\": \"https://www.factset.com/\"\n            },\n            \"FIGI\": {\n              \"type\": \"string\",\n              \"title\": \"Open FIGI\",\n              \"description\": \"https://www.openfigi.com/\"\n            },\n            \"ISIN\": {\n              \"type\": \"string\",\n              \"title\": \"ISIN\",\n              \"description\": \"https://www.isin.org/\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv PERMID\",\n              \"description\": \"https://permid.org/\"\n            },\n            \"RIC\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv Identification Code\",\n              \"description\": \"https://www.refinitiv.com/\"\n            },\n            \"SEDOL\": {\n              \"type\": \"string\",\n              \"title\": \"SEDOL\",\n              \"description\": \"https://www.lseg.com/sedol\"\n            },\n            \"ticker\": {\n              \"type\": \"string\",\n              \"title\": \"Stock ticker\",\n              \"description\": \"Unstandardized stock tickers\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the instrument\"\n        },\n        \"market\": {\n          \"description\": \"The `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"MIC\": {\n              \"type\": \"string\",\n              \"title\": \"Market Identifier Code\",\n              \"description\": \"https://en.wikipedia.org/wiki/Market_Identifier_Code\"\n            },\n            \"name\": {\n              \"type\": \"string\",\n              \"title\": \"Market Name\",\n              \"description\": \"Human readable market name\"\n            },\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"Country ISO Code\",\n              \"description\": \"https://www.iso.org/iso-3166-country-codes.html\"\n            },\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg Market Identifier\",\n              \"description\": \"https://www.bloomberg.com/\"\n            }\n          },\n          \"unevaluatedProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"required\": [\n        \"type\",\"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"name\": \"Microsoft\",\n      \"id\": {\n          \"ticker\": \"MSFT\",\n          \"RIC\": \"MSFT.OQ\",\n          \"ISIN\": \"US5949181045\"\n      },\n      \"market\": {\n          \"MIC\": \"XNAS\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"description\": \"A collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist). However, when holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type.\\n\\nThe instrument list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrumentList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Instrument List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the instrument list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the instrument list\"\n        },\n        \"instruments\": {\n          \"type\": \"array\",\n          \"title\": \"List of instruments\",\n          \"description\": \"An array of instrument contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"instruments\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrumentList\",\n      \"instruments\": [\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"AAPL\"\n          },\n          \"market\": {\n            \"MIC\": \"XNAS\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ISIN\": \"US5949181045\"\n          }\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/interaction.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/interaction.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Interaction\",\n  \"description\": \"An `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.interaction\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Interaction Id\",\n          \"description\": \"Can be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted. An interaction ID does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\",\n          \"properties\": {\n            \"URI\": {\n              \"type\": \"string\",\n              \"title\": \"Interaction URI\",\n              \"description\": \"Can be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\"\n            },\n            \"SALESFORCE\": {\n              \"type\": \"string\",\n              \"title\": \"Salesforce ID\",\n              \"description\": \"Interactions ID in Salesforce\"\n            },\n            \"SINGLETRACK\": {\n              \"type\": \"string\",\n              \"title\": \"SingleTrack ID\",\n              \"description\": \"Interaction ID in SingleTrack\"\n            }\n          }\n        },\n        \"participants\": {\n          \"title\": \"Interaction Participants\",\n          \"description\": \"A list of contacts involved in the interaction\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"timeRange\": {\n          \"title\": \"Interaction Time range\",\n          \"description\": \"The time range over which the interaction occurred\",\n          \"$ref\": \"timeRange.schema.json#\"\n        },\n        \"interactionType\": {\n          \"title\": \"Interaction Type\",\n          \"description\": \"`interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\",\n          \"anyOf\": [\n            {\n              \"type\": \"string\",\n              \"enum\": [\n                \"Instant Message\",\n                \"Email\",\n                \"Call\",\n                \"Meeting\"\n              ]\n            },\n            {\n              \"type\": \"string\"\n            }\n          ]\n        },\n        \"description\": {\n          \"title\": \"Interaction Description\",\n          \"description\": \"A human-readable description of the interaction\",\n          \"type\": \"string\"\n        },\n        \"initiator\": {\n          \"title\": \"Interaction Initiator\",\n          \"description\": \"The contact that initiated the interaction\",\n          \"$ref\": \"contact.schema.json#\"\n        },\n        \"origin\": {\n          \"title\": \"Interaction Origin\",\n          \"description\": \"Used to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"participants\",\n        \"timeRange\",\n        \"interactionType\",\n        \"description\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.interaction\",\n      \"participants\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane.doe@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john.doe@mail.com\"\n            }\n          }\n        ]\n      },\n      \"interactionType\": \"Instant Message\",\n      \"timeRange\": {\n        \"type\": \"fdc3.timeRange\",\n        \"startTime\": \"2022-02-10T15:12:00Z\"\n      },\n      \"description\": \"Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum\",\n      \"initiator\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"origin\": \"Outlook\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/message.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/message.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Message\",\n  \"description\": \"A chat message to be sent through an instant messaging application. Can contain one or several text bodies (organized by mime-type, plaintext or markdown), as well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.message\"\n        },\n        \"text\": {\n          \"type\": \"object\",\n          \"title\": \"Message text\",\n          \"description\": \"A map of string mime-type to string content\",\n          \"properties\": {\n            \"text/plain\": {\n              \"type\": \"string\",\n              \"title\": \"Plain text\",\n              \"description\": \"Plain text encoded content.\"\n            },\n            \"text/markdown\": {\n              \"title\": \"Markdown text\",\n              \"description\": \"Markdown encoded content\",\n              \"type\": \"string\"\n            }\n          }\n        },\n        \"entities\": {\n          \"type\": \"object\",\n          \"title\": \"Message entities\",\n          \"description\": \"A map of string IDs to entities that should be attached to the message, such as an action to perform, a file attachment, or other FDC3 context object.\",\n          \"additionalProperties\": {\n            \"oneOf\": [\n              {\n                \"$ref\": \"action.schema.json#\"\n              },\n              {\n                \"$ref\": \"fileAttachment.schema.json#\"\n              }\n            ]\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.message\",\n      \"text\": {\n        \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate\"\n      },\n      \"entities\": {\n        \"picture1\": {\n          \"type\": \"fdc3.fileAttachment\",\n          \"data\": {\n            \"name\": \"myImage.png\",\n            \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n          }\n        },\n        \"eurusd_action\": {\n          \"type\": \"fdc3.action\",\n          \"title\": \"Click to view Chart\",\n          \"intent\": \"ViewChart\",\n          \"context\": {\n            \"type\": \"fdc3.chart\",\n            \"instruments\": [\n              {\n                \"type\": \"fdc3.instrument\",\n                \"id\": {\n                  \"ticker\": \"EURUSD\"\n                }\n              }\n            ],\n            \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n            },\n            \"style\": \"candle\"\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/nothing.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/nothing.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Nothing\",\n  \"description\": \"A type that explicitly represents a lack of context.\\n\\nNotes:\\n\\n- Intended to be used in situations where no context is desired.\\n- For example:\\n  - Raising an intent without context (e.g. opening a blank order form, or chat interface without a contact selected).\\n  - Resetting context on a channel (e.g. when context is used to set a filter in other applications a null context might release the filter).\\n- An explicit representation of a Null or empty context allows apps to declare support for a lack of context, for example in their intent metadata in an app directory.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.nothing\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.nothing\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/order.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/order.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Order\",\n  \"description\": \"@experimental context type representing an order. To be used with OMS and EMS systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human readable `name` field to be used to summarize the order and an optional `details` field that may be used to provide additional detail about the order, including a context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as a unspecified Context type, but both `details` and `details.product` are expected to be standardized in future.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.order\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Order Identifiers\",\n          \"description\": \"One or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the order.\"\n        },\n        \"details\": {\n          \"type\": \"object\",\n          \"title\": \"Order Details\",\n          \"description\": \"Optional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context\",\n          \"properties\": {\n            \"product\": {\n              \"$ref\": \"product.schema.json\"\n            }\n          },\n          \"additionalProperties\": true\n        },\n        \"notes\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Order Notes\",\n\t\t\t\t\t\"description\": \"Additional notes or comments about the order.\"\n\t\t\t\t}\n      },\n      \"required\": [\n        \"type\",\n        \"id\"\n      ],\n      \"additionalProperties\": true\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.order\",\n      \"name\": \"...\",\n      \"notes\": \"...\",\n      \"id\": {\n        \"myOMS\": \"12345\"\n      },\n      \"details\": {\n        \"product\": {\n          \"type\": \"fdc3.product\",\n          \"id\": {\n            \"productId\": \"ABC123\"\n          },\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"ABC123\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/orderList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/orderList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"OrderList\",\n  \"description\": \"@experimental A list of orders. Use this type for use cases that require not just a single order, but multiple.\\n\\nThe OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.orderList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Order List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the order list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the order list\"\n        },\n        \"orders\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"order.schema.json#\"\n          },\n          \"title\": \"List of Orders\",\n          \"description\": \"An array of order contexts that forms the list.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"orders\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.orderList\",\n      \"orders\": [\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"ABC123\"\n          }\n        },\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"DEF456\"\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"description\": \"An entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\\n\\nIt is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement is for at least one specified identifier to be provided.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.organization\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Organization Identifiers\",\n          \"description\": \"Identifiers for the organization, at least one must be provided.\",\n          \"minProperties\": 1,\n          \"properties\": {\n            \"LEI\": {\n              \"type\": \"string\",\n              \"title\": \"Legal Entity Identifier\",\n              \"description\": \"The Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO 17442 standard developed by the International Organization for Standardization (ISO). It connects to key reference information that enables clear and unique identification of legal entities participating in financial transactions.\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"Refinitiv Permanent Identifiers, or PermID for the organization\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"FactSet Permanent Identifier representing the organization\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name of the organization\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.organization\",\n      \"name\": \"Cargill, Incorporated\",\n      \"id\": {\n        \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n        \"FDS_ID\": \"00161G-E\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"description\": \"A financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\\n\\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\\n\\nThe Portfolio type consists of an array of [Position](Position) types, each of which refers to a single [Instrument](Instrument) and a holding amount for that instrument.\\n\\nThe portfolio schema does not explicitly include identifiers in the `id` section, as there bis not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.portfolio\"\n        },\n        \"positions\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"position.schema.json#\"\n          },\n          \"title\": \"Portfolio positions\",\n          \"description\": \"The List of Positions which make up the Portfolio\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Portfolio Identifiers\",\n          \"description\": \"One or more identifiers that refer to the portfolio in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the portfolio\"\n        }\n      },\n      \"required\": [\n        \"positions\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.portfolio\",\n      \"positions\": [\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"AAPL\"\n            }\n          },\n          \"holding\": 2000000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          },\n          \"holding\": 1500000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"IBM\"\n            }\n          },\n          \"holding\": 3000000\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"description\": \"A financial position made up of an instrument and a holding in that instrument. This type is a good example of how new context types can be composed from existing types.\\n\\nIn this case, the instrument and the holding amount for that instrument are required values.\\n\\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents multiple holdings in a combination of instruments.\\n\\nThe position schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.position\"\n        },\n        \"instrument\": {\n          \"$ref\": \"instrument.schema.json#\",\n          \"title\": \"The financial instrument that this position relates to\",\n          \"description\": \"\"\n        },\n        \"holding\": {\n          \"type\": \"number\",\n          \"title\": \"The size of the holding represented by this position\",\n          \"description\": \"The amount of the holding, e.g. a number of shares\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Position Identifiers\",\n          \"description\": \"One or more identifiers that refer to the position in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the position\"\n        }\n      },\n      \"required\": [\n        \"instrument\",\n        \"holding\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"AAPL\"\n        }\n      },\n      \"holding\": 2000000\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/product.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/context/product.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Product\",\n\t\"description\": \"@experimental context type representing a tradable product. To be used with OMS and EMS systems.\\n\\nThis type is currently only loosely defined as an extensible context object, with an optional instrument field.\\n\\nThe Product schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.product\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Product Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Product Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the product.\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"$ref\": \"instrument.schema.json\",\n\t\t\t\t\t\"title\": \"Product Instrument\",\n\t\t\t\t\t\"description\": \"A financial instrument that relates to the definition of this product\"\n\t\t\t\t},\n\t\t\t\t\"notes\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Product Notes\",\n\t\t\t\t\t\"description\": \"Additional notes or comments about the product.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\",\n\t\t\t\t\"id\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\"notes\": \"...\",\n\t\t\t\"id\": {\n\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t},\n\t\t\t\"instrument\": {\n\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/timeRange.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/timeRange.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TimeRange\",\n  \"description\": \"A context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\\n\\n- A pricing chart\\n- A trade blotter\\n- A record of client contact/activity in a CRM\\n\\nExample use cases:\\n\\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\\n\\nNotes:\\n\\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\\n  - A timezone indicator should be specified, e.g. `\\\"2022-05-12T15:18:03Z\\\"` or `\\\"2022-05-12T16:18:03+01:00\\\"`\\n  - Times MAY be specified with millisecond precision, e.g. `\\\"2022-05-12T15:18:03.349Z\\\"`\",\n  \"allOf\": [\n    {\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.timeRange\"\n        },\n        \"startTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Start Time\",\n          \"description\": \"The start time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        },\n        \"endTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"End Time\",\n          \"description\": \"The end time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"anyOf\": [\n    {\n      \"required\": [\n        \"startTime\",\n        \"endTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"startTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"endTime\"\n      ]\n    }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44Z\",\n      \"endTime\": \"2022-04-30T23:59:59Z\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44+00:00\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"endTime\": \"2022-03-30T16:44:44.123Z\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/trade.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/context/trade.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Trade\",\n\t\"description\": \"@experimental context type representing a trade. To be used with execution systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as a unspecified Context type, but `product` is expected to be standardized in future.\\n\\n The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.trade\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Trade Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Trade Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the trade.\"\n\t\t\t\t},\n\t\t\t\t\"product\": {\n\t\t\t\t\t\"$ref\": \"product.schema.json\",\n\t\t\t\t\t\"title\": \"Traded product\",\n\t\t\t\t\t\"description\": \"A product that is the subject of the trade.\"\n\t\t\t\t},\n\t\t\t\t\"notes\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Trade Notes\",\n\t\t\t\t\t\"description\": \"Additional notes or comments about the trade.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\", \"id\", \"product\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.trade\",\n\t\t\t\"name\": \"...\",\n\t\t\t\"notes\": \"...\",\n\t\t\t\"id\": {\n\t\t\t\t\"myEMS\": \"12345\"\n\t\t\t},\n\t\t\t\"product\": {\n\t\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/fdc3-context/schemas/context/tradeList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/tradeList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TradeList\",\n  \"description\": \"@experimental A list of trades. Use this type for use cases that require not just a single trade, but multiple.\\n\\nThe TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.tradeList\"\n        },\n        \"trades\": {\n          \"title\": \"List of Trades\",\n          \"description\": \"An array of trade contexts that forms the list.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"trade.schema.json#\"\n          }\n        },\n        \"id\": {\n          \"title\": \"Trade List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the trade list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\",\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the trade list\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"trades\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.tradeList\",\n      \"trades\": [\n        {\n          \"type\": \"fdc3.trade\",\n          \"name\": \"...\",\n          \"id\": {\n            \"myEMS\": \"12345\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"ABC123\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"MSFT\"\n              }\n            }\n          }\n        },\n        {\n          \"type\": \"fdc3.trade\",\n          \"id\": {\n            \"myEMS\": \"67890\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"DEF456\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"TSLA\"\n              }\n            }\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/transactionresult.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/transactionresult.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TransactionResult\",\n  \"description\": \"A context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an `IntentResult` by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.transactionResult\"\n        },\n        \"status\": {\n          \"type\": \"string\",\n          \"enum\": [\n            \"Created\",\n            \"Deleted\",\n            \"Updated\",\n            \"Failed\"\n          ],\n          \"title\": \"Transaction Status\",\n          \"description\": \"The status of the transaction being reported.\"\n        },\n        \"context\": {\n          \"$ref\": \"context.schema.json#\",\n          \"title\": \"Transaction Result Context\",\n          \"description\": \"A context object returned by the transaction, possibly with updated data.\"\n        },\n        \"message\": {\n          \"type\": \"string\",\n          \"title\": \"Transaction Message\",\n          \"description\": \"A human readable message describing the outcome of the transaction.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"status\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.transactionResult\",\n      \"status\": \"Updated\",\n      \"context\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/schemas/context/valuation.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/context/valuation.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Valuation\",\n  \"description\": \"A context type representing the price and value of a holding.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.valuation\"\n        },\n        \"value\": {\n          \"type\": \"number\",\n          \"title\": \"Value\",\n          \"description\": \"The value of the holding, expresses in the nominated currency.\"\n        },\n        \"price\": {\n          \"type\": \"number\",\n          \"title\": \"Price per unit\",\n          \"description\": \"The price per unit the the valuation is based on.\"\n        },\n        \"CURRENCY_ISOCODE\": {\n          \"type\": \"string\",\n          \"pattern\": \"^[A-Z]{3}$\",\n          \"title\": \"Valuation Currency\",\n          \"description\": \"The valuation currency, which should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n        },\n        \"valuationTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Valuation time\",\n          \"description\": \"The time at which the valuation was performed, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        },\n        \"expiryTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Expiry Time\",\n          \"description\": \"The time at which this valuation expires, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        }\n      },\n      \"required\": [\n        \"value\",\n        \"CURRENCY_ISOCODE\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.valuation\",\n      \"value\": 500.0,\n      \"price\": 5.0,\n      \"CURRENCY_ISOCODE\": \"USD\",\n      \"expiryTime\": \"2022-05-13T16:16:24+01:00\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/fdc3-context/src/index.ts",
    "content": "export * from '../generated/context/ContextTypes.js';\n"
  },
  {
    "path": "packages/fdc3-context/test/validate-schema-examples.test.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n// This test validates that all examples in each JSON schema in schemas/context are valid according to their schema.\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { describe, test, expect } from 'vitest';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst sanitizeFilename = (filename: string) => filename.replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n\ndescribe('FDC3 Context Schema Example Validation', () => {\n  const schemasDir = path.join(__dirname, '../schemas/context');\n  const schemaFiles = fs.readdirSync(schemasDir).filter(f => f.endsWith('.schema.json'));\n  const ajv = new Ajv({ strict: false });\n  addFormats(ajv);\n\n  // Utility to recursively rewrite $ref values in a schema to use absolute $id URLs\n  // This is necessary because many of the schema use relative paths like `../api/api.schema.json`\n  // and we want to rewrite them to use the absolute $id URLs defined in the API schemas.\n  function rewriteRefs(schema: any, refMap: Record<string, string>) {\n    if (Array.isArray(schema)) {\n      schema.forEach(item => rewriteRefs(item, refMap));\n    } else if (typeof schema === 'object' && schema !== null) {\n      for (const key of Object.keys(schema)) {\n        if (key === '$ref' && typeof schema[key] === 'string') {\n          const ref = schema[key];\n          // Normalize path\n          const normRef = ref.replace(/\\\\/g, '/');\n          // Match ../api/api.schema.json or ..\\\\api\\\\api.schema.json\n          const match = normRef.match(/^\\.\\.\\/api\\/(.+\\.schema\\.json)(#.*)?$/i);\n          if (match) {\n            const file = match[1];\n            const fragment = match[2] || '';\n            if (refMap[file]) {\n              schema[key] = refMap[file] + fragment;\n            }\n          }\n        } else {\n          rewriteRefs(schema[key], refMap);\n        }\n      }\n    }\n  }\n\n  // Load and map all API schemas\n  // Use workspace root to resolve api schemas path\n  const workspaceRoot = path.resolve(__dirname, '../../../');\n  const apiSchemasDir = path.join(workspaceRoot, 'packages', 'fdc3-schema', 'schemas', 'api');\n  let apiSchemas: { schemaFile: string; schema: any }[] = [];\n  const refMap: Record<string, string> = {};\n  if (fs.existsSync(apiSchemasDir)) {\n    const apiSchemaFiles = fs.readdirSync(apiSchemasDir).filter(f => f.endsWith('.schema.json'));\n    apiSchemas = apiSchemaFiles.map(schemaFile => {\n      const schemaPath = path.join(apiSchemasDir, sanitizeFilename(schemaFile));\n      const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));\n      if (schema.$id) {\n        refMap[schemaFile] = schema.$id;\n      }\n      return { schemaFile, schema };\n    });\n  }\n\n  // Load and map all context schemas\n  const schemas = schemaFiles.map(schemaFile => {\n    const schemaPath = path.join(schemasDir, sanitizeFilename(schemaFile));\n    const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));\n    if (schema.$id) {\n      refMap[schemaFile] = schema.$id;\n    }\n    return { schemaFile, schema };\n  });\n\n  // Rewrite $ref in all schemas to remove relative paths and use absolute $id URLs\n  [...apiSchemas, ...schemas].forEach(({ schema }) => rewriteRefs(schema, refMap));\n\n  // Register all schemas with Ajv\n  [...apiSchemas, ...schemas].forEach(({ schemaFile, schema }) => {\n    ajv.addSchema(schema, schema.$id || schemaFile);\n  });\n\n  schemas.forEach(({ schemaFile, schema }) => {\n    const examples = schema.examples || (schema.example ? [schema.example] : []);\n    // Use getSchema if $id is present, otherwise compile\n    const validate = schema.$id ? ajv.getSchema(schema.$id) : ajv.compile(schema);\n\n    if (examples.length === 0 && schemaFile !== 'context.schema.json') {\n      // context.schema.json is the main schema and has no examples\n      test(`${schemaFile} has no examples`, () => {\n        expect.fail(`${schemaFile} has no examples to validate.`);\n      });\n      return;\n    }\n\n    if (!validate) {\n      test(`${schemaFile} validator could not be found`, () => {\n        expect.fail(`Validator for ${schemaFile} could not be found. Check if $id is set and schema was added to Ajv.`);\n      });\n      return;\n    }\n\n    examples.forEach((example: any, idx: number) => {\n      test(`${schemaFile} example #${idx + 1} should be valid`, () => {\n        const valid = validate(example);\n        if (!valid) {\n          console.error(validate.errors);\n        }\n        expect(valid).toBe(true);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-context/tsconfig.json",
    "content": "{\n    \"extends\": \"../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"rootDirs\": [\n            \"src\",\n            \"generated\"\n        ],\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src/**/*.ts\",\n        \"generated/**/*\",\n        \"schemas/**/*.json\",\n    ],\n    \"exclude\": [\n        \"dist/**\",\n        \"test/**\"\n    ],\n    \"references\": []\n}"
  },
  {
    "path": "packages/fdc3-context/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    include: ['test/**/*.test.ts'],\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n  },\n});\n"
  },
  {
    "path": "packages/fdc3-get-agent/README.md",
    "content": "# FDC3 Agent Proxy\n\nContains the main entry point for the Financial Desktop Connectivity and Collaboration Consortium (FDC3) JavaScript API, via the `getAgent` function.\n\n\n## Installation\n\nTo install the FDC3 module, use npm:\n\n```bash\nnpm install @finos/fdc3-get-agent\n```\n\n## Usage\n\nTo use the FDC3 module in your project, import it as follows:\n\n```javascript\nimport { getAgent } from '@finos/fdc3-get-agent';\n// getAgent() returns the FDC3 Desktop Agent\nconst fdc3 = await getAgent();\n\n// Example usage\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n};\n\nfdc3.raiseIntent('ViewProfile', contact);\n```\n\n## Documentation\n\nFor detailed documentation and API reference, please visit the [official FDC3 documentation](https://fdc3.finos.org/docs/api/spec).\n\n## Contributing\n\nWe welcome contributions to the FDC3 project. Please see our [contributing guidelines](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for more information.\n\n## License\n\nThis project is licensed under the [Apache 2.0 License](LICENSE).\n\n## Contact\n\nFor any questions or support, please reach out to the FDC3 community on our [Slack channel](https://finos-lf.slack.com/archives/CJ8Q8H4Q1) or [mailing list](mailto:fdc3@finos.org).\n\n## Further Details\n\nFurther details are avilable in the main [FDC3 Project README](https://github.com/finos/FDC3)\n"
  },
  {
    "path": "packages/fdc3-get-agent/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "packages/fdc3-get-agent/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-get-agent\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc && vitest run\",\n    \"test:watch\": \"vitest\",\n    \"test:coverage\": \"vitest run --coverage\",\n    \"clean\": \"rimraf dist coverage node_modules test-results.xml\",\n    \"lint\": \"eslint src/\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3-agent-proxy\": \"2.2.2\",\n    \"@finos/fdc3-context\": \"2.2.2\",\n    \"@finos/fdc3-schema\": \"2.2.2\",\n    \"@finos/fdc3-standard\": \"2.2.2\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"uuid\": \"^9.0.1\"\n  },\n  \"devDependencies\": {\n    \"@cucumber/cucumber\": \"10.3.1\",\n    \"@finos/fdc3-web-impl\": \"2.2.2\",\n    \"@finos/testing\": \"2.2.2\",\n    \"@types/wtfnode\": \"^0.7.3\",\n    \"ajv\": \"^8.17.1\",\n    \"ajv-formats\": \"^3.0.1\",\n    \"jsonpath-plus\": \"^10.1.0\",\n    \"quickpickle\": \"^1.6.1\",\n    \"wtfnode\": \"^0.9.3\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/Fdc3Version.ts",
    "content": "export const FDC3_VERSION = '2.2';\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/apps/NoopAppSupport.ts",
    "content": "import { AppIdentifier, AppMetadata } from '@finos/fdc3-standard';\nimport { Messaging } from '@finos/fdc3-agent-proxy';\nimport { DefaultAppSupport } from '@finos/fdc3-agent-proxy';\n\nexport class NoopAppSupport extends DefaultAppSupport {\n  constructor(messaging: Messaging, messageExchangeTimeout: number, appLaunchTimeout: number) {\n    super(messaging, messageExchangeTimeout, appLaunchTimeout);\n  }\n\n  async getAppMetadata(app: AppIdentifier): Promise<AppMetadata> {\n    return {\n      appId: app.appId,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/index.ts",
    "content": "import { DesktopAgent } from '@finos/fdc3-standard';\nimport { getAgent } from './strategies/getAgent.js';\nimport { AbstractUIComponent } from './ui/AbstractUIComponent.js';\nimport { DefaultDesktopAgentChannelSelector } from './ui/DefaultDesktopAgentChannelSelector.js';\nimport { DefaultDesktopAgentIntentResolver } from './ui/DefaultDesktopAgentIntentResolver.js';\nimport { NullChannelSelector } from './ui/NullChannelSelector.js';\nimport { NullIntentResolver } from './ui/NullIntentResolver.js';\n\nconst DEFAULT_WAIT_FOR_MS = 20000;\n\nexport {\n  getAgent,\n  AbstractUIComponent,\n  DefaultDesktopAgentChannelSelector,\n  DefaultDesktopAgentIntentResolver,\n  NullChannelSelector,\n  NullIntentResolver,\n};\n\n/**\n * Replaces the original fdc3Ready function from FDC3 2.0 with a new one that uses the new getAgent function.\n *\n * @param waitForMs Amount of time to wait before failing the promise (20 seconds is the default).\n * @returns A DesktopAgent promise.\n *\n * @deprecated This function is provided for backwards compatibility.  Use `const fdc3 = getAgent()` to retrieve (and\n * wait for) a reference to the FDC3 API instead.\n */\nexport function fdc3Ready(waitForMs = DEFAULT_WAIT_FOR_MS): Promise<DesktopAgent> {\n  return getAgent({\n    timeoutMs: waitForMs,\n    dontSetWindowFdc3: false,\n    channelSelector: true,\n    intentResolver: true,\n  });\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/messaging/MessagePortMessaging.ts",
    "content": "import { AbstractMessaging, RegisterableListener } from '@finos/fdc3-agent-proxy';\nimport { AppIdentifier, GetAgentParams, WebDesktopAgentType } from '@finos/fdc3-standard';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  AppRequestMessage,\n  WebConnectionProtocol3Handshake,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\n/**\n * Details needed to set up the Messaging instance and Desktop AgentDetails record\n */\nexport type ConnectionDetails = {\n  connectionAttemptUuid: string;\n  handshake: WebConnectionProtocol3Handshake;\n  messagePort: MessagePort;\n  actualUrl: string;\n  options: GetAgentParams;\n  agentType: WebDesktopAgentType;\n  agentUrl?: string;\n  messageExchangeTimeout: number;\n  appLaunchTimeout: number;\n};\nexport class MessagePortMessaging extends AbstractMessaging {\n  private readonly cd: ConnectionDetails;\n  private readonly listeners: Map<string, RegisterableListener> = new Map();\n\n  constructor(cd: ConnectionDetails, appIdentifier: AppIdentifier) {\n    super(appIdentifier);\n    this.cd = cd;\n\n    this.cd.messagePort.addEventListener('message', m => {\n      this.listeners.forEach(v => {\n        if (v.filter(m.data)) {\n          v.action(m.data);\n        }\n      });\n    });\n  }\n\n  createUUID(): string {\n    return uuidv4();\n  }\n\n  async post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void> {\n    this.cd.messagePort.postMessage(message);\n    return Promise.resolve();\n  }\n\n  register(l: RegisterableListener): void {\n    this.listeners.set(l.id!, l);\n  }\n\n  unregister(id: string): void {\n    this.listeners.delete(id);\n  }\n\n  createMeta(): AppRequestMessage['meta'] {\n    return {\n      requestUuid: this.createUUID(),\n      timestamp: new Date(),\n      source: super.getAppIdentifier(),\n    };\n  }\n\n  async disconnect(): Promise<void> {\n    const bye: WebConnectionProtocol6Goodbye = {\n      type: 'WCP6Goodbye',\n      meta: {\n        timestamp: new Date(),\n      },\n    };\n    await this.post(bye);\n\n    this.cd.messagePort.close();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/messaging/message-port.ts",
    "content": "import { AppIdentifier, DesktopAgent, LogLevel } from '@finos/fdc3-standard';\nimport {\n  DesktopAgentProxy,\n  DefaultChannelSupport,\n  DefaultAppSupport,\n  DefaultIntentSupport,\n  ChannelSupport,\n  DefaultHeartbeatSupport,\n} from '@finos/fdc3-agent-proxy';\nimport { ConnectionDetails, MessagePortMessaging } from './MessagePortMessaging.js';\nimport { DefaultDesktopAgentIntentResolver } from '../ui/DefaultDesktopAgentIntentResolver.js';\nimport { DefaultDesktopAgentChannelSelector } from '../ui/DefaultDesktopAgentChannelSelector.js';\nimport { NullIntentResolver } from '../ui/NullIntentResolver.js';\nimport { NullChannelSelector } from '../ui/NullChannelSelector.js';\nimport { ChannelSelector } from '@finos/fdc3-standard';\nimport { Logger } from '../util/Logger.js';\n\n/**\n * Given a message port, constructs a desktop agent to communicate via that.\n */\nexport async function createDesktopAgentAPI(\n  cd: ConnectionDetails,\n  appIdentifier: AppIdentifier,\n  logLevel: LogLevel | null\n): Promise<DesktopAgent> {\n  Logger.debug('message-port: Creating Desktop Agent...');\n\n  //Message port should have already been started for use in identity validation\n\n  function string(o: string | boolean): string | null {\n    if (o == true || o == false) {\n      return null;\n    } else {\n      return o;\n    }\n  }\n\n  const messaging = new MessagePortMessaging(cd, appIdentifier);\n\n  const useResolver = cd.handshake.payload.intentResolverUrl && cd.options.intentResolver;\n  const useSelector = cd.handshake.payload.channelSelectorUrl && cd.options.channelSelector;\n\n  const intentResolver = useResolver\n    ? new DefaultDesktopAgentIntentResolver(string(cd.handshake.payload.intentResolverUrl))\n    : new NullIntentResolver();\n\n  const channelSelector = useSelector\n    ? new DefaultDesktopAgentChannelSelector(string(cd.handshake.payload.channelSelectorUrl))\n    : new NullChannelSelector();\n\n  Logger.debug('message-port: Setting up support components...');\n\n  const hs = new DefaultHeartbeatSupport(messaging);\n  const cs = new DefaultChannelSupport(messaging, channelSelector, cd.messageExchangeTimeout);\n  const is = new DefaultIntentSupport(messaging, intentResolver, cd.messageExchangeTimeout, cd.appLaunchTimeout);\n  const as = new DefaultAppSupport(messaging, cd.messageExchangeTimeout, cd.appLaunchTimeout);\n  const da = new DesktopAgentProxy(hs, cs, is, as, [hs, cs, intentResolver, channelSelector], logLevel);\n\n  Logger.debug('message-port: Connecting components ...');\n\n  await da.connect();\n\n  Logger.debug('message-port: Populating channel selector...');\n\n  await populateChannelSelector(cs, channelSelector);\n\n  Logger.debug('message-port: Setting up disconnect handling...');\n\n  handleDisconnectOnPageHide(da, messaging);\n\n  Logger.debug('message-port: Returning...');\n\n  return da;\n}\n\nasync function populateChannelSelector(cs: ChannelSupport, channelSelector: ChannelSelector): Promise<void> {\n  const channel = await cs.getUserChannel();\n  const userChannels = await cs.getUserChannels();\n  channelSelector.updateChannel(channel?.id ?? null, userChannels);\n}\n\nfunction handleDisconnectOnPageHide(da: DesktopAgentProxy, messaging: MessagePortMessaging) {\n  globalThis.window.addEventListener('pagehide', async event => {\n    Logger.log(`Received pagehide event with persisted ${event.persisted}`);\n\n    //If persisted == true then the page is stored and might come back if the user hits back\n    //  In that case don't disconnect and let heartbeat handle that instead\n\n    //TODO: implement disconnect on any hide and reconnect if the page is shown again\n    //  Will have to happen inside the DesktopAgentProxy as the reference to the DA needs to remain the same\n    //  and any listeners need to be re-registered automatically etc.\n    if (!event.persisted) {\n      //the page is being destroyed, disconnect from the DA\n\n      //Notify the Desktop Agent implementation to disconnect\n      da.disconnect();\n\n      //disconnect the MessagePort - which should send WCP6Goodbye first\n      messaging.disconnect();\n    }\n  });\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/sessionStorage/DesktopAgentDetails.ts",
    "content": "import { DesktopAgentDetails, DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX } from '@finos/fdc3-standard';\nimport { Logger } from '../util/Logger.js';\nimport { createUUID } from '../util/Uuid.js';\n\n/**\n * Note that we also key by the window name as well, in case multiple iframes are using the same session storage.\n */\nexport function sessionKey(): string {\n  //If the window or frame is not named, create and apply a unique name to it\n  if (!globalThis.window.name) {\n    globalThis.window.name = createUUID();\n  }\n  const windowName = globalThis.window.name;\n  const keyName = DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-' + windowName;\n  return keyName;\n}\n\n/** Used to persist data on the connection, which can later be used to ensure\n *  reconnection to the same Desktop Agent and to request the same instanceId.\n */\nexport function storeDesktopAgentDetails(details: DesktopAgentDetails) {\n  Logger.debug(`DesktopAgentDetails: Storing Desktop Agent details:`, details);\n  //check if there are existing details in storage to update\n  let detailsToStore = retrieveAllDesktopAgentDetails();\n  if (!detailsToStore) {\n    detailsToStore = {};\n  }\n  detailsToStore[details.identityUrl] = details;\n  globalThis.sessionStorage.setItem(sessionKey(), JSON.stringify(detailsToStore));\n}\n\n/** Retrieves persisted data about previous connections. Used to ensure reconnection\n *  to the same agent and to request the same instanceId.\n */\nexport function retrieveAllDesktopAgentDetails(): Record<string, DesktopAgentDetails> | null {\n  const detailsStr = globalThis.sessionStorage.getItem(sessionKey());\n\n  if (detailsStr) {\n    try {\n      const theData: Record<string, DesktopAgentDetails> = JSON.parse(detailsStr) as Record<\n        string,\n        DesktopAgentDetails\n      >;\n      if (typeof theData !== 'object' || Array.isArray(theData)) {\n        throw new Error('Stored DesktopAgentDetails is not in the expected format!');\n      }\n      return theData;\n    } catch (e) {\n      Logger.warn(\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        `DesktopAgentDetails: FDC3 connection data couldn't be parsed\\nstorage key: ${sessionKey()}\\nvalue: ${detailsStr}\\nmessage: ${(e as any).message ?? e}`\n      );\n      return null;\n    }\n  } else {\n    return null;\n  }\n}\n\n/** Retrieves persisted data about previous connections for this specific app\n *  (identified by the identityUrl). Used to ensure reconnection to the same\n *  agent and to request the same instanceId.\n */\nexport function retrieveDesktopAgentDetails(identityUrl: string): DesktopAgentDetails | null {\n  const allDetails = retrieveAllDesktopAgentDetails();\n  Logger.debug(`DesktopAgentDetails: retrieveDesktopAgentDetails:`, allDetails);\n  if (allDetails) {\n    const theData: DesktopAgentDetails = allDetails[identityUrl];\n\n    if (theData) {\n      //check we got the minimum properties\n      if (\n        typeof theData.agentType === 'string' &&\n        theData.agentType && //TODO: check this is one of the enum values\n        typeof theData.appId === 'string' &&\n        theData.appId &&\n        typeof theData.instanceId === 'string' &&\n        theData.instanceId\n      ) {\n        return theData;\n      } else {\n        //ignore it and post a warning\n        Logger.warn(\n          `DesktopAgentDetails: Stored details do not meet minimum requirements and will be ignored:\\n${JSON.stringify(theData, null, 2)}`\n        );\n        return null;\n      }\n    }\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/DesktopAgentPreloadLoader.ts",
    "content": "import { AgentError, DesktopAgent, WebDesktopAgentType } from '@finos/fdc3-standard';\nimport { GetAgentParams } from '@finos/fdc3-standard';\nimport { DesktopAgentSelection, Loader } from './Loader.js';\nimport { Logger } from '../util/Logger.js';\nimport { DEFAULT_GETAGENT_TIMEOUT_MS } from './Timeouts.js';\n\n/**\n * This approach will resolve the loader promise if the fdc3Ready event occurs.\n * This is done by Desktop Agent Preload implementations setting window.fdc3.\n */\nexport class DesktopAgentPreloadLoader implements Loader {\n  name = 'DesktopAgentPreloadLoader';\n\n  /** Reference to the handler for the fdc3Ready event (used to remove it) */\n  readyEventHandler: (() => void) | null = null;\n  /** Variable used to end polling */\n  done: boolean = false;\n  /** Overall timeout */\n  timeout: NodeJS.Timeout | null = null;\n  /** Timeout used in polling */\n  pollingTimeout: NodeJS.Timeout | null = null;\n\n  /** Reference to the get fn's Promise's reject call - used when cancelling. */\n  rejectFn: ((reason?: string) => void) | null = null;\n\n  async poll(resolve: (value: DesktopAgentSelection) => void) {\n    if (!this.done) {\n      if (globalThis.window.fdc3) {\n        Logger.debug(`DesktopAgentPreloadLoader.get(): Discovered DA through polling...`);\n        this.prepareSelection(globalThis.window.fdc3, resolve);\n      } else {\n        this.pollingTimeout = setTimeout(() => this.poll(resolve), 100);\n      }\n    }\n  }\n\n  async prepareSelection(fdc3: DesktopAgent, resolve: (value: DesktopAgentSelection) => void) {\n    Logger.debug('DesktopAgentPreloadLoader: Preparing selection');\n\n    //note that we've found an agent and will be settling our get promise\n    this.rejectFn = null;\n    //stop polling and listening for fdc3Ready\n    this.cancel();\n\n    //retrieve appId from DA\n    const implMetadata = await fdc3.getInfo();\n    const selection: DesktopAgentSelection = {\n      agent: fdc3,\n      details: {\n        agentType: WebDesktopAgentType.Preload,\n        identityUrl: globalThis.window.location.href,\n        actualUrl: globalThis.window.location.href,\n        appId: implMetadata?.appMetadata?.appId ?? 'unknown',\n        instanceId: implMetadata?.appMetadata?.instanceId ?? 'unknown',\n        instanceUuid: implMetadata?.appMetadata?.instanceId ?? 'unknown', // preload DAs don't issue these so repeat the instanceId\n      },\n    };\n\n    resolve(selection);\n  }\n\n  get(options: GetAgentParams): Promise<DesktopAgentSelection> {\n    Logger.debug(`DesktopAgentPreloadLoader.get(): Initiating search for Desktop Agent Preload`);\n    return new Promise<DesktopAgentSelection>((resolve, reject) => {\n      //save reject fn in case we get cancelled\n      this.rejectFn = reject;\n\n      //do an initial check\n      if (globalThis.window.fdc3) {\n        this.prepareSelection(globalThis.window.fdc3, resolve);\n      } else {\n        //setup a timeout so that we can reject if don't find anything\n        const timeoutMs = options.timeoutMs ?? DEFAULT_GETAGENT_TIMEOUT_MS;\n        this.timeout = setTimeout(() => {\n          Logger.debug(`DesktopAgentPreloadLoader.get(): timeout (${timeoutMs} ms) at ${new Date().toISOString()}`);\n          reject(AgentError.AgentNotFound);\n          this.cancel();\n        }, timeoutMs);\n\n        //listen for the fdc3Ready event\n        this.readyEventHandler = () => {\n          Logger.debug(`DesktopAgentPreloadLoader.get(): discovered DA through fdc3Ready event`);\n          if (globalThis.window.fdc3) {\n            this.prepareSelection(globalThis.window.fdc3, resolve);\n          }\n        };\n        globalThis.window.addEventListener('fdc3Ready', this.readyEventHandler);\n\n        //also do polling (just in case)\n        this.poll(resolve);\n      }\n    });\n  }\n\n  async cancel(): Promise<void> {\n    Logger.debug('DesktopAgentPreloadLoader: Cleaning up');\n    this.done = true;\n    if (this.timeout) {\n      clearTimeout(this.timeout);\n    }\n    if (this.pollingTimeout) {\n      clearTimeout(this.pollingTimeout);\n    }\n    if (this.readyEventHandler) {\n      globalThis.window.removeEventListener('fdc3Ready', this.readyEventHandler);\n    }\n    if (this.rejectFn) {\n      this.rejectFn(AgentError.AgentNotFound);\n      this.rejectFn = null;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/FailoverHandler.ts",
    "content": "import {\n  GetAgentParams,\n  DesktopAgent,\n  WebDesktopAgentType,\n  AgentError,\n  AppIdentifier,\n  LogLevel,\n} from '@finos/fdc3-standard';\nimport { createDesktopAgentAPI } from '../messaging/message-port.js';\nimport { DesktopAgentSelection } from './Loader.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport { HelloHandler } from './HelloHandler.js';\nimport { IdentityValidationHandler } from './IdentityValidationHandler.js';\nimport { Logger } from '../util/Logger.js';\nimport { ConnectionDetails } from '../messaging/MessagePortMessaging.js';\n\n/** TypeGuard for a Desktop Agent */\nfunction isDesktopAgent(da: WindowProxy | DesktopAgent): da is DesktopAgent {\n  return (da as DesktopAgent).getInfo !== undefined;\n}\n\n/** TypeGuard for a Window */\nfunction isWindow(da: Window | DesktopAgent): da is Window {\n  return (da as Window).postMessage !== undefined;\n}\n\nexport class FailoverHandler {\n  constructor(options: GetAgentParams) {\n    this.options = options;\n    this.connectionAttemptUuid = uuidv4(); // we use a different connectionAttemptUuid to differnetiate from any (failed) messaging to a parent window\n    this.helloHandler = new HelloHandler(this.options, this.connectionAttemptUuid, WebDesktopAgentType.Failover);\n  }\n\n  /** Parameters passed to getAgent */\n  options: GetAgentParams;\n\n  /** UUID used to filter messages */\n  connectionAttemptUuid: string;\n\n  /** Handler class for hello/handshake messages */\n  helloHandler: HelloHandler;\n\n  /** Handler class for identity validation steps used for Desktop Agent Proxies */\n  identityValidationHandler?: IdentityValidationHandler;\n\n  /**\n   * This is a variation of the PostMessageLoader used for handling failover.\n   * If the failover returns a WindowProxy this is used to create a Desktop\n   * Agent Proxy. If a DesktopAgent is returned directly it is passed through.\n   *\n   */\n  async handleFailover(): Promise<DesktopAgentSelection> {\n    try {\n      //set-up a event listeners in case the failover returns a Window that wants to message us\n      const handshakePromise = this.helloHandler.listenForHelloResponses();\n\n      if (typeof this.options.failover === 'function') {\n        const failoverResult = await this.options.failover(this.options);\n\n        if (isDesktopAgent(failoverResult)) {\n          return await this.failoverResultIsDesktopAgent(failoverResult);\n        } else if (isWindow(failoverResult)) {\n          return await this.failoverResultIsProxyWindow(failoverResult, handshakePromise);\n        } else {\n          Logger.error('Failover function returned an invalid result: ', failoverResult);\n          throw AgentError.InvalidFailover;\n        }\n      } else {\n        Logger.error('Failover was not a function, actual type: ', typeof this.options.failover);\n        throw AgentError.InvalidFailover;\n      }\n    } finally {\n      //cleanup any remaining listeners\n      this.cancel();\n    }\n  }\n\n  private async failoverResultIsProxyWindow(failoverResult: Window, handshakePromise: Promise<ConnectionDetails>) {\n    this.helloHandler.sendWCP1Hello(failoverResult, '*');\n\n    //if we received a WindowProxy from failover, and it sent us a handshake, try to validate its identity\n    const connectionDetails = await handshakePromise;\n    try {\n      this.identityValidationHandler = new IdentityValidationHandler(\n        connectionDetails.messagePort,\n        this.options,\n        this.connectionAttemptUuid\n      );\n      const idValidationPromise = this.identityValidationHandler.listenForIDValidationResponses();\n\n      //start the message port so that we can receive responses\n      connectionDetails.messagePort.start();\n\n      this.identityValidationHandler.sendIdValidationMessage();\n      const idDetails = await idValidationPromise;\n      const appIdentifier: AppIdentifier = {\n        appId: idDetails.payload.appId,\n        instanceId: idDetails.payload.instanceId,\n      };\n\n      //prep log settings to pass on to the proxy\n      const logLevel: LogLevel | null = this.options?.logLevels?.proxy ?? null;\n\n      const desktopAgentSelection: DesktopAgentSelection = {\n        agent: await createDesktopAgentAPI(connectionDetails, appIdentifier, logLevel),\n        details: {\n          agentType: connectionDetails.agentType,\n          agentUrl: connectionDetails.agentUrl ?? undefined,\n          identityUrl: connectionDetails.options.identityUrl ?? connectionDetails.actualUrl,\n          actualUrl: connectionDetails.actualUrl,\n          appId: idDetails.payload.appId,\n          instanceId: idDetails.payload.instanceId,\n          instanceUuid: idDetails.payload.instanceUuid,\n        },\n      };\n\n      return desktopAgentSelection;\n    } catch (e) {\n      //identity validation may have failed\n      Logger.error('Error during identity validation of Failover', e);\n      throw e;\n    }\n  }\n\n  private async failoverResultIsDesktopAgent(failoverResult: DesktopAgent) {\n    this.cancel();\n\n    //retrieve appId and instanceId from the DA\n    const implMetadata = await failoverResult.getInfo();\n    const desktopAgentSelection: DesktopAgentSelection = {\n      agent: failoverResult,\n      details: {\n        agentType: WebDesktopAgentType.Failover,\n        identityUrl: globalThis.window.location.href,\n        actualUrl: globalThis.window.location.href,\n        appId: implMetadata.appMetadata.appId,\n        instanceId: implMetadata.appMetadata.instanceId ?? 'unknown',\n        instanceUuid: implMetadata.appMetadata.instanceId ?? 'unknown', // preload DAs don't issue these so repeat the instanceId\n      },\n    };\n    return desktopAgentSelection;\n  }\n\n  /** Removes listeners so that events are no longer processed */\n  cancel() {\n    this.helloHandler.cancel();\n    if (this.identityValidationHandler) {\n      this.identityValidationHandler.cancel();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/HelloHandler.ts",
    "content": "import { FDC3_VERSION, GetAgentParams, WebDesktopAgentType } from '@finos/fdc3-standard';\nimport { ConnectionDetails } from '../messaging/MessagePortMessaging.js';\nimport { Logger } from '../util/Logger.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS, DEFAULT_APP_LAUNCH_TIMEOUT_MS } from './Timeouts.js';\nconst { isWebConnectionProtocol2LoadURL, isWebConnectionProtocol3Handshake } = BrowserTypes;\ntype WebConnectionProtocolMessage = BrowserTypes.WebConnectionProtocolMessage;\ntype WebConnectionProtocol1Hello = BrowserTypes.WebConnectionProtocol1Hello;\n\nexport class HelloHandler {\n  constructor(\n    options: GetAgentParams,\n    connectionAttemptUuid: string,\n    agentType: WebDesktopAgentType = WebDesktopAgentType.ProxyParent\n  ) {\n    this.options = options;\n    this.connectionAttemptUuid = connectionAttemptUuid;\n    this.agentType = agentType;\n    this.helloResponseListener = null;\n  }\n\n  /** Parameters passed to getAgent */\n  options: GetAgentParams;\n\n  /** UUID used to filter messages */\n  connectionAttemptUuid: string;\n\n  /** The agentType to set, which may change if we're asked to load a URL into an iframe */\n  agentType: WebDesktopAgentType;\n\n  /** If we're asked to load a URL into an iframe, it is stored here to be saved in Session Storage */\n  agentUrl: string | null = null;\n\n  /** Reference to event listener used for responses from Desktop Agents -\n   *  Used to remove them when no longer needed.\n   *  Initialized when\n   *  - listening for hello responses\n   *  - listening for identity validation responses\n   * */\n  helloResponseListener: ((event: MessageEvent<WebConnectionProtocolMessage>) => void) | null;\n\n  /**\n   * Starts the connection process off by sending a hello message\n   */\n  sendWCP1Hello(w: MessageEventSource, origin: string) {\n    const requestMessage: WebConnectionProtocol1Hello = {\n      type: 'WCP1Hello',\n      meta: {\n        connectionAttemptUuid: this.connectionAttemptUuid,\n        timestamp: new Date(),\n      },\n      payload: {\n        channelSelector: this.options.channelSelector,\n        fdc3Version: FDC3_VERSION,\n        intentResolver: this.options.intentResolver,\n        identityUrl: this.options.identityUrl!,\n        actualUrl: globalThis.window.location.href,\n      },\n    };\n\n    Logger.debug(`HelloHandler: Sending hello msg:\\n${JSON.stringify(requestMessage, null, 2)}`);\n\n    w.postMessage(requestMessage, { targetOrigin: origin });\n  }\n\n  /**\n   * Handle a request from a desktop agent that the client loads an adaptor URL\n   * into an iframe instead of working with the parent window.\n   */\n  openFrame(url: string) {\n    const IFRAME_ID = 'fdc3-communications-embedded-iframe';\n\n    // remove an old one if it's there\n    document.getElementById(IFRAME_ID)?.remove();\n\n    //note the iframe URL and desktop agent type have changed\n    this.agentType = WebDesktopAgentType.ProxyUrl;\n    this.agentUrl = url;\n\n    // create a new one\n    const iframe = document.createElement('iframe');\n\n    //Wait for the iframe to load... then send it a hello message\n    iframe.addEventListener('load', () => {\n      if (iframe.contentWindow) {\n        Logger.debug('Sending hello message to communication iframe');\n        this.sendWCP1Hello(iframe.contentWindow, '*');\n      } else {\n        throw new Error(\n          `An iframe (url: ${url}) added to support communication with a Desktop Agent does not have a contentWindow, despite firing its load event!`\n        );\n      }\n    });\n\n    iframe.setAttribute('src', url);\n    iframe.setAttribute('id', IFRAME_ID);\n    iframe.setAttribute('name', 'FDC3 Communications');\n    iframe.style.width = '0px';\n    iframe.style.height = '0px';\n    iframe.style.border = '0';\n    iframe.style.position = 'fixed';\n\n    document.body.appendChild(iframe);\n  }\n\n  /** Listen for WCP responses from 'parent' windows and frames and handle them.\n   * Resolves when a response is received.\n   * @returns A Promise resolving to a set of ConnectionDetails\n   */\n  listenForHelloResponses(): Promise<ConnectionDetails> {\n    return new Promise<ConnectionDetails>(resolve => {\n      // setup listener for message and retrieve JS URL from it\n      this.helloResponseListener = (event: MessageEvent<WebConnectionProtocolMessage>) => {\n        const data = event.data;\n\n        if (data?.meta?.connectionAttemptUuid == this.connectionAttemptUuid) {\n          if (isWebConnectionProtocol2LoadURL(data)) {\n            // in this case, we need to load the URL with the embedded Iframe\n            const url = data.payload.iframeUrl;\n            this.openFrame(url);\n\n            //n.b event listener remains in place to receive messages from the iframe\n          } else if (isWebConnectionProtocol3Handshake(data)) {\n            Logger.debug(`HelloHandler: successful handshake:`, data);\n            const connectionDetails: ConnectionDetails = {\n              connectionAttemptUuid: this.connectionAttemptUuid,\n              handshake: data,\n              messagePort: event.ports[0],\n              options: this.options,\n              actualUrl: globalThis.window.location.href,\n              agentType: this.agentType,\n              agentUrl: this.agentUrl ?? undefined,\n              messageExchangeTimeout: data.payload.messageExchangeTimeout ?? DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS,\n              appLaunchTimeout: data.payload.appLaunchTimeout ?? DEFAULT_APP_LAUNCH_TIMEOUT_MS,\n            };\n            resolve(connectionDetails);\n\n            //remove the event listener as we've received a messagePort to use\n            this.cancel();\n          } else {\n            Logger.debug(\n              `Ignoring unexpected message in HelloHandler (because its not WCP2LoadUrl or WCP3Handshake).`,\n              data\n            );\n          }\n        } else {\n          Logger.warn(\n            `HelloHandler: Ignoring message with invalid connectionAttemptUuid. Expected ${this.connectionAttemptUuid}, received: ${data?.meta?.connectionAttemptUuid}`,\n            data\n          );\n        }\n      };\n\n      globalThis.window.addEventListener('message', this.helloResponseListener);\n    });\n  }\n\n  /** Removes listeners so that events are no longer processed */\n  cancel() {\n    if (this.helloResponseListener) {\n      globalThis.window.removeEventListener('message', this.helloResponseListener);\n      this.helloResponseListener = null;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/IdentityValidationHandler.ts",
    "content": "import { GetAgentParams, AgentError } from '@finos/fdc3-standard';\nimport { retrieveDesktopAgentDetails } from '../sessionStorage/DesktopAgentDetails.js';\nimport { Logger } from '../util/Logger.js';\n\nimport { BrowserTypes } from '@finos/fdc3-schema';\nconst {\n  isWebConnectionProtocol5ValidateAppIdentitySuccessResponse,\n  isWebConnectionProtocol5ValidateAppIdentityFailedResponse,\n} = BrowserTypes;\ntype WebConnectionProtocol4ValidateAppIdentity = BrowserTypes.WebConnectionProtocol4ValidateAppIdentity;\ntype WebConnectionProtocol5ValidateAppIdentitySuccessResponse =\n  BrowserTypes.WebConnectionProtocol5ValidateAppIdentitySuccessResponse;\ntype WebConnectionProtocolMessage = BrowserTypes.WebConnectionProtocolMessage;\n\n/** Timeout allowed for id validation to occur and for the DA to respond with details.\n * This is additional to the app's specified timeout for discovery - we have already\n * found an agent at that point we are just finishing setting up the connection. */\nconst ID_VALIDATION_TIMEOUT = 5000;\n\nexport class IdentityValidationHandler {\n  constructor(mp: MessagePort, options: GetAgentParams, connectionAttemptUuid: string) {\n    this.messagePort = mp;\n    this.options = options;\n    this.connectionAttemptUuid = connectionAttemptUuid;\n    this.idValidationResponseListener = null;\n  }\n\n  /** Reference to the MessagePort received. Used to remove listeners when cancelling. */\n  messagePort: MessagePort;\n\n  /** Parameters passed to getAgent */\n  options: GetAgentParams;\n\n  /** UUID used to filter messages */\n  connectionAttemptUuid: string;\n\n  /** Event listener for ID validation response from Desktop Agents over the MessagePort.\n   *  Used to remove them when no longer needed.\n   * Initialized during the id validation step.\n   */\n  idValidationResponseListener: ((event: MessageEvent<WebConnectionProtocolMessage>) => void) | null;\n\n  /**\n   * Starts the connection process off by sending a hello message\n   */\n  sendIdValidationMessage() {\n    const actualUrl = globalThis.window.location.href;\n    const identityUrl = this.options.identityUrl ?? actualUrl;\n\n    const requestMessage: WebConnectionProtocol4ValidateAppIdentity = {\n      type: 'WCP4ValidateAppIdentity',\n      meta: {\n        connectionAttemptUuid: this.connectionAttemptUuid,\n        timestamp: new Date(),\n      },\n      payload: {\n        identityUrl,\n        actualUrl,\n      },\n    };\n\n    const persistedDetails = retrieveDesktopAgentDetails(identityUrl);\n\n    if (persistedDetails) {\n      requestMessage.payload.instanceId = persistedDetails.instanceId;\n      requestMessage.payload.instanceUuid = persistedDetails.instanceUuid;\n    }\n\n    this.messagePort.postMessage(requestMessage);\n  }\n\n  /** Listen for WCP responses over the message port to identity validation messages. */\n  listenForIDValidationResponses(): Promise<WebConnectionProtocol5ValidateAppIdentitySuccessResponse> {\n    return new Promise<WebConnectionProtocol5ValidateAppIdentitySuccessResponse>((resolve, reject) => {\n      // setup listener for message and retrieve JS URL from it\n      this.idValidationResponseListener = (event: MessageEvent<WebConnectionProtocolMessage>) => {\n        const data = event.data;\n\n        if (data?.meta?.connectionAttemptUuid == this.connectionAttemptUuid) {\n          if (isWebConnectionProtocol5ValidateAppIdentitySuccessResponse(data)) {\n            //passed validation\n            clearTimeout(timeout);\n            if (this.idValidationResponseListener) {\n              //remove the event listener as we've received a messagePort to use\n              this.messagePort.removeEventListener('message', this.idValidationResponseListener);\n            }\n            Logger.debug(\n              `IdentityValidationHandler: Validated app identity, appId: ${data.payload.appId}, instanceId: ${data.payload.instanceId}`\n            );\n            resolve(data);\n          } else if (isWebConnectionProtocol5ValidateAppIdentityFailedResponse(data)) {\n            //failed validation...\n            clearTimeout(timeout);\n            if (this.idValidationResponseListener) {\n              //remove the event listener as we've received a messagePort to use\n              this.messagePort.removeEventListener('message', this.idValidationResponseListener);\n            }\n            Logger.error(\n              `IdentityValidationHandler: App identity validation failed: ${data.payload.message ?? 'No reason given'}`\n            );\n            reject(AgentError.AccessDenied);\n          } else {\n            Logger.debug(\n              `IdentityValidationHandler: Ignoring message unexpected message in PostMessageLoader (because its not a WCP5 message).`,\n              data\n            );\n          }\n        } else {\n          Logger.warn(\n            `IdentityValidationHandler: Ignoring message with invalid connectionAttemptUuid. Expected ${this.connectionAttemptUuid}, received: ${data?.meta?.connectionAttemptUuid}`,\n            data\n          );\n        }\n      };\n\n      //listening on a message port\n      this.messagePort.addEventListener('message', this.idValidationResponseListener);\n\n      //timeout for id validation only\n      const timeout = setTimeout(() => {\n        Logger.warn(`IdentityValidationHandler: Identity validation timed out`);\n\n        if (this.idValidationResponseListener) {\n          //remove the event listener as we won't proceed further\n          this.messagePort.removeEventListener('message', this.idValidationResponseListener);\n        }\n        Logger.error(\n          `The Desktop Agent didn't respond to ID validation within ${ID_VALIDATION_TIMEOUT / 1000} seconds`\n        );\n        reject(AgentError.ErrorOnConnect);\n      }, ID_VALIDATION_TIMEOUT);\n    });\n  }\n\n  cancel(): void {\n    if (this.idValidationResponseListener) {\n      this.messagePort.removeEventListener('message', this.idValidationResponseListener);\n    }\n    //TODO: cancel any timeouts and reject any returned promises\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/Loader.ts",
    "content": "import { DesktopAgent, WebDesktopAgentType } from '@finos/fdc3-standard';\nimport { GetAgentParams } from '@finos/fdc3-standard';\n\n/**\n * Represents the common interface for a loading strategy\n */\nexport interface Loader {\n  /**\n   * Promise will either resolve to a DesktopAgent or reject with an error\n   */\n  get(options: GetAgentParams): Promise<DesktopAgentSelection>;\n\n  cancel(): Promise<void>;\n\n  name: string;\n}\n\n/** Specific partial of DesktopAgentDetails defining the details that Loaders\n *  must return with a DesktopAgent to be put into SessionStorage at the end\n *  of the process.\n */\nexport interface DesktopAgentSelection {\n  agent: DesktopAgent;\n  details: {\n    agentType: WebDesktopAgentType;\n    identityUrl: string;\n    actualUrl: string;\n    agentUrl?: string;\n    appId: string;\n    instanceId: string;\n    instanceUuid: string;\n  };\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/PostMessageLoader.ts",
    "content": "import { AgentError, AppIdentifier, GetAgentParams, LogLevel } from '@finos/fdc3-standard';\nimport { createDesktopAgentAPI } from '../messaging/message-port.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport { DesktopAgentSelection, Loader } from './Loader.js';\nimport { HelloHandler } from './HelloHandler.js';\nimport { IdentityValidationHandler } from './IdentityValidationHandler.js';\nimport { Logger } from '../util/Logger.js';\nimport { DEFAULT_GETAGENT_TIMEOUT_MS } from './Timeouts.js';\n\n/**\n * Recursive search for all possible parent frames (windows) that we may\n * target with the WCP.\n * @param startWindow window object to search\n * @param found window objects found so far\n */\nfunction collectPossibleTargets(startWindow: Window, found: Window[]) {\n  _recursePossibleTargets(startWindow, startWindow, found);\n  Logger.debug(`Possible parent windows/frames found: ${found.length}`);\n}\n\nfunction _recursePossibleTargets(startWindow: Window, w: Window, found: Window[]) {\n  if (w) {\n    if (found.indexOf(w) == -1 && w != startWindow) {\n      found.push(w);\n    }\n\n    if (w.opener) {\n      _recursePossibleTargets(startWindow, w.opener, found);\n    }\n\n    if (w.parent != w) {\n      _recursePossibleTargets(startWindow, w.parent, found);\n    }\n  }\n}\n\n/** Loader for Desktop Agent Proxy implementations. Attempts to\n *  connect to parent windows or frames via teh Web Connection Protocol,\n *  which may include setting up an iframe to load an adaptor URL.\n *  A previously persisted adaptor URL may be passed to skip the\n *  discovery of parent windows and to move straight to loading that.\n */\nexport class PostMessageLoader implements Loader {\n  name = 'PostMessageLoader';\n  private proxyLogLevel: LogLevel | null;\n\n  constructor(options: GetAgentParams, previousUrl?: string) {\n    //prep log settings to pass on to the proxy\n    this.proxyLogLevel = options.logLevels?.proxy ?? null;\n\n    this.previousUrl = previousUrl ?? null;\n  }\n\n  previousUrl: string | null;\n  connectionAttemptUuid = uuidv4();\n\n  helloHandler?: HelloHandler;\n  identityValidationHandler?: IdentityValidationHandler;\n\n  /** Initial timeout (released once a MessagePort is received - additional steps are outside timeout) */\n  timeout: NodeJS.Timeout | null = null;\n\n  /** Reference to the get fn's Promise's reject call - used when cancelling. */\n  rejectFn: ((reason?: string) => void) | null = null;\n\n  get(options: GetAgentParams): Promise<DesktopAgentSelection> {\n    Logger.debug(`PostMessageLoader.get(): Initiating search for Desktop Agent Proxy`);\n    return new Promise<DesktopAgentSelection>((resolve, reject) => {\n      //save reject fn in case we get cancelled\n      this.rejectFn = reject;\n\n      //setup a timeout so we can reject if it runs out\n      const timeoutMs = options.timeoutMs ?? DEFAULT_GETAGENT_TIMEOUT_MS;\n      this.timeout = setTimeout(() => {\n        Logger.debug(`PostMessageLoader.get(): timeout (${timeoutMs} ms) at ${new Date().toISOString()}`);\n        this.cancel();\n        reject(AgentError.AgentNotFound);\n      }, timeoutMs);\n\n      this.helloHandler = new HelloHandler(options, this.connectionAttemptUuid);\n\n      // ok, begin the process\n      const handshakePromise = this.helloHandler.listenForHelloResponses();\n\n      if (this.previousUrl) {\n        Logger.debug(`PostMessageLoader.get(): Loading previously used adaptor URL: ${this.previousUrl}`);\n\n        //skip looking for target parent windows and open an iframe immediately\n        this.helloHandler.openFrame(this.previousUrl);\n      } else {\n        //collect target parent window references\n        const targets: Window[] = [];\n        collectPossibleTargets(globalThis.window, targets);\n\n        // use of origin '*': See https://github.com/finos/FDC3/issues/1316\n        for (let t = 0; t < targets.length; t++) {\n          this.helloHandler.sendWCP1Hello(targets[t], '*');\n        }\n      }\n\n      // wait for one of the windows to respond\n      //  This may involve a WCP2LoadUrl response being received\n      //  and an adaptor iframe setup to load it, resolves on\n      //  WCP3Handshake response.\n      // If no WCP3Handshake is ever received this will not resolve\n      handshakePromise.then(connectionDetails => {\n        //prevent us being cancelled\n        this.rejectFn = null;\n\n        //cancel the initial timeout as we got a handshake response\n        if (this.timeout) {\n          clearTimeout(this.timeout);\n        }\n\n        //perform id validation\n        this.identityValidationHandler = new IdentityValidationHandler(\n          connectionDetails.messagePort,\n          options,\n          this.connectionAttemptUuid\n        );\n        const idValidationPromise = this.identityValidationHandler.listenForIDValidationResponses();\n\n        //start the message port so that we can receive responses\n        connectionDetails.messagePort.start();\n\n        this.identityValidationHandler.sendIdValidationMessage();\n\n        idValidationPromise\n          .then(idDetails => {\n            //resolve\n            const appIdentifier: AppIdentifier = {\n              appId: idDetails.payload.appId,\n              instanceId: idDetails.payload.instanceId,\n            };\n\n            createDesktopAgentAPI(connectionDetails, appIdentifier, this.proxyLogLevel).then(da => {\n              const desktopAgentSelection: DesktopAgentSelection = {\n                agent: da,\n                details: {\n                  agentType: connectionDetails.agentType,\n                  agentUrl: connectionDetails.agentUrl ?? undefined,\n                  identityUrl: connectionDetails.options.identityUrl ?? connectionDetails.actualUrl,\n                  actualUrl: connectionDetails.actualUrl,\n                  appId: idDetails.payload.appId,\n                  instanceId: idDetails.payload.instanceId,\n                  instanceUuid: idDetails.payload.instanceUuid,\n                },\n              };\n\n              //clean up\n              this.cancel();\n\n              resolve(desktopAgentSelection);\n            });\n          })\n          .catch(e => {\n            //id validation may have failed\n            reject(e);\n          });\n      });\n    });\n  }\n\n  async cancel(): Promise<void> {\n    Logger.debug('PostMessageLoader: Cleaning up');\n\n    //if we're being cancelled while still running, reject the promise\n    if (this.rejectFn) {\n      this.rejectFn(AgentError.AgentNotFound);\n      this.rejectFn = null;\n    }\n\n    //cancel the timeout\n    if (this.timeout) {\n      clearTimeout(this.timeout);\n    }\n\n    //remove any event listeners to end processing\n    if (this.helloHandler) {\n      this.helloHandler.cancel();\n    }\n\n    if (this.identityValidationHandler) {\n      this.identityValidationHandler.cancel();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/Timeouts.ts",
    "content": "/**\n * The default timeout used by getAgent when discovering Desktop Agents.\n */\nexport const DEFAULT_GETAGENT_TIMEOUT_MS = 1000;\n\n/** Default timeout used by a DesktopAgentProxy for all message exchanges\n * with a DesktopAgent, except those that involve the launch of an application.\n * May be overridden by a DesktopAgent by passing a value in the\n * payload.messageExchangeTimeout of a WCP3Handshake message.\n */\nexport const DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS = 10000;\n\n/** Default timeout used by a DesktopAgentProxy for message exchanges with a\n * DesktopAgent that involve launching applications. May be overridden by a\n * DesktopAgent by passing a value in the payload.appLaunchTimeout of a\n * WCP3Handshake message.\n * */\nexport const DEFAULT_APP_LAUNCH_TIMEOUT_MS = 100000;\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/strategies/getAgent.ts",
    "content": "import {\n  DesktopAgent,\n  GetAgentType,\n  GetAgentParams,\n  AgentError,\n  DesktopAgentDetails,\n  WebDesktopAgentType,\n} from '@finos/fdc3-standard';\nimport { DesktopAgentPreloadLoader } from './DesktopAgentPreloadLoader.js';\nimport { PostMessageLoader } from './PostMessageLoader.js';\nimport { retrieveDesktopAgentDetails, storeDesktopAgentDetails } from '../sessionStorage/DesktopAgentDetails.js';\nimport { FailoverHandler } from './FailoverHandler.js';\nimport { Loader } from './Loader.js';\nimport { Logger } from '../util/Logger.js';\nimport { DEFAULT_GETAGENT_TIMEOUT_MS } from './Timeouts.js';\n\n// TypeGuards used to examine results of Loaders\nconst isRejected = (input: PromiseSettledResult<unknown>): input is PromiseRejectedResult =>\n  input.status === 'rejected';\n\nconst isFulfilled = <T>(input: PromiseSettledResult<T>): input is PromiseFulfilledResult<T> =>\n  input.status === 'fulfilled';\n\n/**\n * For now, we only allow a single call to getAgent per application, so\n * we keep track of the promise we use here.\n */\nlet theAgentPromise: Promise<DesktopAgent> | null = null;\n\nconst CLEAR_PROMISE_DELAY = 500;\n\nexport function clearAgentPromise() {\n  theAgentPromise = null;\n}\n\nfunction initAgentPromise(options: GetAgentParams): Promise<DesktopAgent> {\n  if (options?.logLevels?.connection) {\n    Logger.setLogLevel(options.logLevels.connection);\n  }\n\n  Logger.log(`Initiating Desktop Agent discovery at ${new Date().toISOString()}`);\n  let strategies: Loader[];\n\n  //if options doesn't contain an identityURL, use the actualUrl\n  if (!options.identityUrl) {\n    options.identityUrl = globalThis.window.location.href;\n  }\n\n  //Retrieve persisted connection data limit to a previous strategy if one exists\n  const persistedData = retrieveDesktopAgentDetails(options.identityUrl);\n  if (persistedData) {\n    switch (persistedData.agentType) {\n      case WebDesktopAgentType.Preload:\n        strategies = [new DesktopAgentPreloadLoader()];\n        break;\n      case WebDesktopAgentType.ProxyUrl:\n        //agentUrl will only be used by PostMessageLoader if not falsey\n        strategies = [new PostMessageLoader(options, persistedData.agentUrl)];\n        break;\n      case WebDesktopAgentType.ProxyParent:\n        strategies = [new PostMessageLoader(options)];\n        break;\n      case WebDesktopAgentType.Failover:\n        strategies = [];\n        break;\n      default:\n        Logger.warn('Unexpected agentType value in SessionStorage, ignoring. Stored data:', persistedData);\n        strategies = [new DesktopAgentPreloadLoader(), new PostMessageLoader(options)];\n    }\n  } else {\n    strategies = [new DesktopAgentPreloadLoader(), new PostMessageLoader(options)];\n  }\n\n  const promises = strategies.map(s =>\n    s.get(options).then(async selection => {\n      //cancel other strategies if we selected a DA\n      Logger.debug(`Strategy ${s.name} resolved - cleaning up other strategies`);\n      for (let s2 = 0; s2 < strategies.length; s2++) {\n        if (strategies[s2] !== s) {\n          Logger.debug(`  cleaning up ${strategies[s2].name}`);\n          await strategies[s2].cancel();\n        }\n      }\n      strategies.forEach(async s2 => {\n        if (s2 !== s) {\n          await s2.cancel();\n        }\n      });\n      return selection;\n    })\n  );\n\n  Logger.debug('Waiting for discovery promises to settle...');\n  return Promise.allSettled(promises).then(async results => {\n    //review results\n    const daResult = results.find(isFulfilled);\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const replacer = (key: string, value: any) => {\n      if (key == 'value') {\n        return '<DesktopAgent>';\n      } else {\n        return value;\n      }\n    };\n    Logger.debug(`Discovery results:  ${JSON.stringify(results, replacer, 2)}`);\n\n    if (daResult) {\n      const selection = daResult.value;\n      const desktopAgentDetails: DesktopAgentDetails = {\n        agentType: selection.details.agentType,\n        identityUrl: selection.details.identityUrl,\n        actualUrl: selection.details.actualUrl,\n        agentUrl: selection.details.agentUrl ?? undefined,\n        appId: selection.details.appId,\n        instanceId: selection.details.instanceId,\n        instanceUuid: selection.details.instanceUuid,\n      };\n      storeDesktopAgentDetails(desktopAgentDetails);\n      Logger.log(\n        `Desktop Agent located via discovery, appId: ${desktopAgentDetails.appId}, instanceId: ${desktopAgentDetails.instanceId}`\n      );\n      return selection.agent;\n    } else {\n      //if we received any error other than AgentError.AgentNotFound, throw it\n      const errors = results.filter(isRejected);\n\n      //n.b. the Loaders throw string error messages, rather than Error objects\n      const error = errors.find(aRejection => aRejection.reason !== AgentError.AgentNotFound);\n      if (error) {\n        //Clear the promise so a fresh call could be made later\n        setTimeout(() => clearAgentPromise(), CLEAR_PROMISE_DELAY);\n        throw new Error(error.reason);\n      } else if (options.failover != undefined) {\n        Logger.debug(`Calling failover fn...`);\n        //Proceed with the failover\n        try {\n          //TODO: consider adding a timeout for the failover, to avoid getting stuck here\n          //  However there is an argument to be made for hanging out in case the\n          //  function eventually returns, e.g. after an external DA started up\n\n          const failoverHandler = new FailoverHandler(options);\n          const selection = await failoverHandler.handleFailover();\n\n          //store details of the connection in SessionStorage\n          const desktopAgentDetails: DesktopAgentDetails = {\n            agentType: WebDesktopAgentType.Failover,\n            identityUrl: selection.details.identityUrl,\n            actualUrl: selection.details.actualUrl,\n            agentUrl: selection.details.agentUrl ?? undefined,\n            appId: selection.details.appId,\n            instanceId: selection.details.instanceId,\n            instanceUuid: selection.details.instanceUuid,\n          };\n          storeDesktopAgentDetails(desktopAgentDetails);\n          Logger.log(\n            `Desktop Agent located via failover, appId: ${desktopAgentDetails.appId}, instanceId: ${desktopAgentDetails.instanceId}`\n          );\n\n          return selection.agent;\n        } catch (e) {\n          //n.b. FailoverHandler throws Error Objects so we can return this directly\n          Logger.error('Desktop agent not found. Error reported during failover: ', e);\n          throw new Error(e as string);\n        }\n      } else {\n        //We didn't manage to find an agent.\n        Logger.error('Desktop agent not found. No error reported during discovery.');\n        //Clear the promise so a fresh call could be made later\n        setTimeout(() => clearAgentPromise(), CLEAR_PROMISE_DELAY);\n        throw new Error(AgentError.AgentNotFound);\n      }\n    }\n  });\n}\n\n/**\n * Function used to retrieve an FDC3 Desktop Agent API instance, which\n * supports the discovery of a Desktop Agent Preload (a container-injected\n * API implementation) or a Desktop Agent Proxy (a Browser-based Desktop Agent\n * running in another window or frame). Finally, if no Desktop Agent is found,\n * a failover function may be supplied by an app allowing it to start or otherwise\n * connect to a Desktop Agent (e.g. by loading a proprietary adaptor that\n * returns a `DesktopAgent` implementation or by creating a window or iframe of\n * its own that will provide a Desktop Agent Proxy.\n *\n * @param {GetAgentParams} params Optional parameters object, which\n * may include a URL to use for the app's identity, other settings\n * that affect the behavior of the getAgent() function and a `failover`\n * function that should be run if a Desktop Agent is not detected.\n *\n * @returns A promise that resolves to a DesktopAgent implementation or\n * rejects with an error message from the `AgentError` enumeration if unable to\n * return a Desktop Agent implementation.\n *\n * @example\n * const fdc3 = await getAgent();\n *\n * // OR\n *\n * getAgent({\n *     identityUrl: \"https://example.com/path?param=appName#example\",\n *     channelSelector: false,\n *     intentResolver: false\n * }).then((fdc3) => {\n *     //do FDC3 stuff here\n * };\n */\nexport const getAgent: GetAgentType = (params?: GetAgentParams) => {\n  const DEFAULT_OPTIONS: GetAgentParams = {\n    dontSetWindowFdc3: false,\n    channelSelector: true,\n    intentResolver: true,\n    timeoutMs: DEFAULT_GETAGENT_TIMEOUT_MS,\n    //default log levels are set in the relevant logging utils\n  };\n\n  const options: GetAgentParams = {\n    ...DEFAULT_OPTIONS,\n    ...params,\n  };\n\n  async function handleSetWindowFdc3(da: DesktopAgent) {\n    if (!options.dontSetWindowFdc3 && !globalThis.window.fdc3) {\n      globalThis.window.fdc3 = da;\n      globalThis.window.dispatchEvent(new Event('fdc3Ready'));\n    }\n    return da;\n  }\n\n  if (!theAgentPromise) {\n    theAgentPromise = initAgentPromise(options).then(handleSetWindowFdc3);\n  }\n\n  return theAgentPromise;\n};\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/ui/AbstractUIComponent.ts",
    "content": "import { Connectable, FDC3_VERSION } from '@finos/fdc3-standard';\nimport { Logger } from '../util/Logger.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nconst { isFdc3UserInterfaceHello, isFdc3UserInterfaceRestyle } = BrowserTypes;\ntype Fdc3UserInterfaceHandshake = BrowserTypes.Fdc3UserInterfaceHandshake;\ntype InitialCSS = BrowserTypes.InitialCSS;\ntype UpdatedCSS = BrowserTypes.UpdatedCSS;\n\nexport interface CSSPositioning {\n  [key: string]: string;\n}\n\nexport const INITIAL_CONTAINER_CSS = {\n  width: '0',\n  height: '0',\n  position: 'fixed',\n};\n\nexport const ALLOWED_CSS_ELEMENTS = [\n  'width',\n  'height',\n  'position',\n  'zIndex',\n  'left',\n  'right',\n  'top',\n  'bottom',\n  'transition',\n  'maxHeight',\n  'maxWidth',\n  'display',\n];\n\nexport const DEFAULT_UI_ROOT_URL = 'https://fdc3.finos.org/toolbox/fdc3-reference-ui/';\n\n/** Abstract implementation of an injected UI, used as the base for communication\n * with injected Channel Selector and Intent Resolver UIs.\n */\nexport abstract class AbstractUIComponent implements Connectable {\n  private container: HTMLDivElement | undefined = undefined;\n  private iframe: HTMLIFrameElement | undefined = undefined;\n  private url: string;\n  private name: string;\n  protected port: MessagePort | null = null;\n  protected messagePortIsReady: Promise<void>;\n  private markMessagePortReady: (() => void) | null = null;\n\n  constructor(url: string, name: string) {\n    this.url = url;\n    this.name = name;\n    this.messagePortIsReady = new Promise<void>(resolve => (this.markMessagePortReady = resolve));\n  }\n\n  /**\n   * Connect the UI component by creating the UI iframe, then wait on\n   * a Fdc3UserInterfaceHello message.\n   *\n   * This function is NOT properly async as we don't want to block the\n   * Desktop Agent connection on the UI frames as they may be blocked by\n   * security policies. I.e. awaiting this will not block.\n   */\n  connect(): Promise<void> {\n    Logger.debug(`AbstractUIComponent (${this.name}): Awaiting hello from `, this.name, ', url: ', this.url);\n    const portPromise = this.awaitHello();\n    this.openFrame();\n    portPromise.then(port => {\n      this.port = port;\n      this.setupMessagePort(port).then(() => {\n        this.messagePortReady(port);\n      });\n    });\n    return Promise.resolve();\n  }\n\n  async disconnect() {\n    this.port?.close();\n  }\n\n  /**\n   * Override and extend this method to provide functionality specific to the UI in question\n   */\n  async setupMessagePort(port: MessagePort): Promise<void> {\n    port.addEventListener('message', e => {\n      const data = e.data;\n\n      if (isFdc3UserInterfaceRestyle(data)) {\n        Logger.debug(`AbstractUIComponent (${this.name}): Restyling: `, data.payload);\n        const css = data.payload.updatedCSS;\n        this.themeContainer(css);\n      }\n    });\n    port.start();\n  }\n\n  async messagePortReady(port: MessagePort) {\n    // tells the iframe it can start posting\n    const message: Fdc3UserInterfaceHandshake = {\n      type: 'Fdc3UserInterfaceHandshake',\n      payload: {\n        fdc3Version: FDC3_VERSION,\n      },\n    };\n    Logger.debug(`AbstractUIComponent (${this.name}): Sending handshake: `, message);\n    port.postMessage(message);\n    this.markMessagePortReady!();\n  }\n\n  private awaitHello(): Promise<MessagePort> {\n    return new Promise(resolve => {\n      const ml = (e: MessageEvent) => {\n        //only respond to messages from this UI's iframe\n        if (e.source == this.iframe?.contentWindow) {\n          if (isFdc3UserInterfaceHello(e.data)) {\n            const helloData = e.data;\n            this.themeContainer(helloData.payload.initialCSS);\n            const port = e.ports[0];\n            globalThis.window.removeEventListener('message', ml);\n            resolve(port);\n          } else {\n            Logger.warn(\n              `AbstractUIComponent (${this.name}): ignored UI Message from UI iframe while awaiting hello: `,\n              e.data\n            );\n          }\n        } else {\n          //as there are two UIs, we expect some cross-over between their messages\n          Logger.debug(\n            `AbstractUIComponent (${this.name}): ignored Message that didn't come from expected UI frame: `,\n            e.data,\n            'my URL: ',\n            this.url\n          );\n        }\n      };\n\n      globalThis.window.addEventListener('message', ml);\n    });\n  }\n\n  private openFrame(): void {\n    this.container = globalThis.document.createElement('div');\n    this.iframe = globalThis.document.createElement('iframe');\n\n    this.themeContainer(INITIAL_CONTAINER_CSS);\n    this.themeFrame(this.iframe);\n\n    this.iframe.setAttribute('src', this.url);\n    this.iframe.setAttribute('name', this.name);\n\n    this.container.appendChild(this.iframe);\n    document.body.appendChild(this.container);\n  }\n\n  private toKebabCase(str: string) {\n    return str.replace(/[A-Z]/g, match => '-' + match.toLowerCase());\n  }\n\n  themeContainer(css: UpdatedCSS | InitialCSS) {\n    Logger.debug(`AbstractUIComponent (${this.name}): Applying styles to container`, css);\n    for (let i = 0; i < ALLOWED_CSS_ELEMENTS.length; i++) {\n      const k = ALLOWED_CSS_ELEMENTS[i];\n      const value: string | undefined = css[k as string];\n      if (value != null) {\n        this.container!.style.setProperty(this.toKebabCase(k), value);\n      } else {\n        this.container!.style.removeProperty(this.toKebabCase(k));\n      }\n    }\n  }\n\n  themeFrame(ifrm: HTMLIFrameElement) {\n    Logger.debug(`AbstractUIComponent (${this.name}): Applying 100% size style to iframe`);\n    ifrm.style.width = '100%';\n    ifrm.style.height = '100%';\n    ifrm.style.border = '0';\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/ui/DefaultDesktopAgentChannelSelector.ts",
    "content": "import { Channel } from '@finos/fdc3-standard';\nimport { ChannelSelector } from '@finos/fdc3-standard';\nimport { AbstractUIComponent, DEFAULT_UI_ROOT_URL } from './AbstractUIComponent.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { Logger } from '../util/Logger.js';\nconst { isFdc3UserInterfaceChannelSelected } = BrowserTypes;\ntype Fdc3UserInterfaceChannels = BrowserTypes.Fdc3UserInterfaceChannels;\n\n/**\n * Handles communication between an injected Channel Selector UI and the getAgent implementation.\n */\nexport class DefaultDesktopAgentChannelSelector extends AbstractUIComponent implements ChannelSelector {\n  private callback: ((channelId: string | null) => void) | null = null;\n\n  constructor(url: string | null) {\n    //TODO: check default UI URL is correct on release\n    super(url ?? DEFAULT_UI_ROOT_URL + 'channel_selector.html', 'FDC3 Channel Selector');\n  }\n\n  async setupMessagePort(port: MessagePort): Promise<void> {\n    this.port = port;\n\n    port.addEventListener('message', e => {\n      if (isFdc3UserInterfaceChannelSelected(e.data)) {\n        Logger.debug(`DefaultDesktopAgentChannelSelector: Received channel selection message: `, e.data);\n        const choice = e.data;\n        if (this.callback) {\n          this.callback(choice.payload.selected);\n        }\n      }\n    });\n\n    //This starts the port so do it last\n    await super.setupMessagePort(port);\n  }\n\n  async updateChannel(channelId: string | null, availableChannels: Channel[]): Promise<void> {\n    const message: Fdc3UserInterfaceChannels = {\n      type: 'Fdc3UserInterfaceChannels',\n      payload: {\n        selected: channelId,\n        userChannels: availableChannels.map(ch => {\n          return {\n            id: ch.id,\n            type: 'user',\n            displayMetadata: ch.displayMetadata,\n          };\n        }),\n      },\n    };\n\n    //don't post until the messageport is ready\n    await this.messagePortIsReady;\n\n    this.port?.postMessage(message);\n    Logger.debug(`DefaultDesktopAgentChannelSelector: Sent channels data to channel selector: `, message);\n  }\n\n  setChannelChangeCallback(callback: (channelId: string | null) => void): void {\n    this.callback = callback;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/ui/DefaultDesktopAgentIntentResolver.ts",
    "content": "import { AppIntent } from '@finos/fdc3-standard';\nimport { IntentResolver, IntentResolutionChoice } from '@finos/fdc3-standard';\nimport { AbstractUIComponent, DEFAULT_UI_ROOT_URL } from './AbstractUIComponent.js';\nimport { Context } from '@finos/fdc3-context';\nimport { Logger } from '../util/Logger.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nconst { isFdc3UserInterfaceResolveAction } = BrowserTypes;\ntype Fdc3UserInterfaceResolve = BrowserTypes.Fdc3UserInterfaceResolve;\n\n/**\n * Handles communication between an injected Intent Resolver UI and the getAgent implementation.\n */\nexport class DefaultDesktopAgentIntentResolver extends AbstractUIComponent implements IntentResolver {\n  private pendingResolve: ((x: IntentResolutionChoice | void) => void) | null = null;\n\n  constructor(url: string | null) {\n    //TODO: check default UI URL is correct on release\n    super(url ?? DEFAULT_UI_ROOT_URL + 'intent_resolver.html', 'FDC3 Intent Resolver');\n  }\n\n  async setupMessagePort(port: MessagePort): Promise<void> {\n    this.port = port;\n\n    this.port.addEventListener('message', e => {\n      if (isFdc3UserInterfaceResolveAction(e.data)) {\n        Logger.debug('DefaultDesktopAgentIntentResolver: Received resolveAction message: ', e.data);\n\n        const choice = e.data;\n        if (choice.payload.action == 'click' && this.pendingResolve) {\n          this.pendingResolve({\n            appId: choice.payload.appIdentifier!,\n            intent: choice.payload.intent!,\n          });\n        } else if (choice.payload.action == 'cancel' && this.pendingResolve) {\n          this.pendingResolve();\n        }\n\n        this.pendingResolve = null;\n      }\n    });\n\n    //This starts the port so do it last\n    await super.setupMessagePort(port);\n  }\n\n  async chooseIntent(appIntents: AppIntent[], context: Context): Promise<IntentResolutionChoice | void> {\n    const out = new Promise<IntentResolutionChoice | void>(resolve => {\n      this.pendingResolve = resolve;\n    });\n    const message: Fdc3UserInterfaceResolve = {\n      type: 'Fdc3UserInterfaceResolve',\n      payload: {\n        appIntents,\n        context,\n      },\n    };\n    this.port?.postMessage(message);\n    Logger.debug(`DefaultDesktopAgentIntentResolver: Requested resolution: `, message);\n    return out;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/ui/NullChannelSelector.ts",
    "content": "import { Connectable } from '@finos/fdc3-standard';\nimport { ChannelSelector } from '@finos/fdc3-standard';\n\n/** Implementation used when an injected Channel selector is not in use. */\nexport class NullChannelSelector implements ChannelSelector, Connectable {\n  async disconnect(): Promise<void> { }\n  async connect(): Promise<void> { }\n  async updateChannel(): Promise<void> { }\n  setChannelChangeCallback(): void { }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/ui/NullIntentResolver.ts",
    "content": "import { IntentResolver, IntentResolutionChoice } from '@finos/fdc3-standard';\n\n/** Implementation used when an injected IntentResolver is not in use. */\nexport class NullIntentResolver implements IntentResolver {\n  async disconnect(): Promise<void> { }\n  async connect(): Promise<void> { }\n  async chooseIntent(): Promise<IntentResolutionChoice | void> { }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/util/Logger.ts",
    "content": "import { AbstractFDC3Logger } from '@finos/fdc3-agent-proxy';\nimport { LogLevel } from '@finos/fdc3-standard';\n\n/**\n * Logging utility used by getAgent when connecting to Desktop Agents,\n * which defaults to printing INFO, WARN and ERROR level messages.\n */\nexport class Logger extends AbstractFDC3Logger {\n  static override get prefix(): string {\n    return 'FDC3 getAgent: ';\n  }\n\n  //set default log level - will not be picked up in test scope so ignored\n  /* istanbul ignore next */\n  logLevel: LogLevel = LogLevel.INFO;\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/src/util/Uuid.ts",
    "content": "import { v4 as uuidv4 } from 'uuid';\n\nexport function createUUID(): string {\n  return uuidv4();\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/README.md",
    "content": "# FDC3 GetAgent Test Infrastructure\n\nThe test infrastructure for fdc3-get-agent is complex as it has to mock a collection of windows, documents and iframes to simulate a Wed-based Desktop Agent. Additional tests in the /toolbox/fdc3-for-web/fdc3-web-impl package test against the reference implementation of web-based Desktop Agent, while the tests here work against a simulated one.\n\nTo enable debug logs for the test infrastructure, set the `debugLogs` flag in packages\\fdc3-get-agent\\test\\world\\index.ts to true.\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/default-channel-selector.feature",
    "content": "Feature: Default Channel Selector\n\n  Background: Desktop Agent API\n    Given a parent window document in \"parentDoc\", window in \"parentWin\", child window document in \"childDoc\" and window in \"childWin\"\n    And A Channel Selector in \"channel-selector\" with callback piping to \"cb\"\n    Given User Channels one, two and three in \"channel-list\"\n\n  Scenario: Channel Selector Requests Channel Change\n    Given The channel selector sends a channel change message for channel \"one\"\n    And we wait for a period of \"200\" ms\n    Then \"{cb}\" is \"one\"\n\n  Scenario: Updating channel information in the channel selector\n    Given I call \"{channel-selector}\" with \"updateChannel\" with parameters \"one\" and \"{channel-list}\"\n    And we wait for a period of \"200\" ms\n    Then \"{lastChannelSelectorMessage}\" is an object with the following contents\n      | type           | payload.selected | payload.userChannels[0].id | payload.userChannels[1].id | payload.userChannels[2].id |\n      | Fdc3UserInterfaceChannels | one              | one                        | two                        | three                      |\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/default-intent-resolver.feature",
    "content": "Feature: Default Intent Resolver\n\n  Background: Desktop Agent API\n    Given a parent window document in \"parentDoc\", window in \"parentWin\", child window document in \"childDoc\" and window in \"childWin\"\n    And An Intent Resolver in \"intent-resolver\"\n    And \"instrumentContext\" is a \"fdc3.instrument\" context\n    And \"appIntents\" is an AppIntents array with a ViewNews intent and two apps\n\n  Scenario: App Requests Intent Resolution\n    Given I call \"{intent-resolver}\" with \"chooseIntent\" with parameters \"{appIntents}\" and \"{instrumentContext}\" for a promise\n    And I refer to \"{result}\" as \"theIntentPromise\"\n    And we wait for a period of \"200\" ms\n    Given The intent resolver sends an intent selection message\n    Then the promise \"{theIntentPromise}\" should resolve\n    And \"{result}\" is an object with the following contents\n      | intent   | appId.appId |\n      | ViewNews | app1        |\n    And I call \"{intent-resolver}\" with \"disconnect\"\n\n  Scenario: Intent Resolution Cancelled\n    Given I call \"{intent-resolver}\" with \"chooseIntent\" with parameters \"{appIntents}\" and \"{instrumentContext}\" for a promise\n    And I refer to \"{result}\" as \"theIntentPromise\"\n    And we wait for a period of \"200\" ms\n    Given The intent resolver cancels the intent selection message\n    Then the promise \"{theIntentPromise}\" should resolve\n    And \"{result}\" is undefined\n    And I call \"{intent-resolver}\" with \"disconnect\"\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/desktop-agent-disconnect.feature",
    "content": "Feature: Death of the Desktop Agent\n\n  Background: Desktop Agent API\n    # Given a browser document in \"document\" and window in \"window\"\n    Given a parent window document in \"parentDoc\", window in \"parentWin\", child window document in \"childDoc\" and window in \"childWin\"\n    #And Testing ends after \"8000\" ms\n\n  Scenario: Loaded in the browser, but the user navigates away\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    And the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    When \"{childWin}\" pagehide occurs with persisted = \"{false}\"\n    And we wait for a period of \"200\" ms\n    Then The Desktop Agent receives a WCP6Goodbye message\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/desktop-agent-strategy.feature",
    "content": "Feature: Different Strategies for Accessing the Desktop Agent\n\n  Background: Desktop Agent API\n    Given a parent window document in \"parentDoc\", window in \"parentWin\", child window document in \"childDoc\" and window in \"childWin\"\n    And SessionStorage is clear\n\n  Scenario: Running inside a Browser and using post message with direct message ports and no identityUrl\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |    8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I refer to \"{document.body.children[0]}\" as \"channel-selector\"\n    And I refer to \"{channel-selector.children[0]}\" as \"iframe\"\n    And \"{childWin.fdc3}\" is undefined\n    And \"{childWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP3Handshake |\n    And \"{parentWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP1Hello     |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Running inside a Browser and using post message, direct message ports, no identityUrl and default UI URLs\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response and uses default UI URLs\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |    8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I refer to \"{document.body.children[0]}\" as \"channel-selector\"\n    And I refer to \"{channel-selector.children[0]}\" as \"iframe\"\n    And \"{childWin.fdc3}\" is undefined\n    And \"{childWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP3Handshake |\n    And \"{parentWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP1Hello     |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Connecting with a specified identityUrl\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | identityUrl                              | timeoutMs | intentResolver | channelSelector |\n      | true              | https://dummyOrigin.test/alternativePath | 8000      | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId        | appMetadata.instanceId        | provider               |\n      |         2.0 | cucumber-alternative-app | cucumber-alternative-instance | cucumber-provider      |\n    And \"{childWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP3Handshake |\n    And \"{parentWin.events}\" is an array of objects with the following contents\n      | type    | data.type     |\n      | message | WCP1Hello     |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Connecting with an unknown identityUrl fails\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | identityUrl                     | timeoutMs | intentResolver | channelSelector |\n      | true              | \"https://bad.identity.com/path\" | 4000      | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"AccessDenied\"\n\nScenario: Connecting but identity validation times out\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response, but times out identity validation\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              | 2000      | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"ErrorOnConnect\"\n\n  Scenario: Running inside a Browser using the embedded iframe strategy\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns iframe response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs |\n      | false             |    8000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I refer to \"{childDoc.iframes[0]}\" as \"embedded-iframe\"\n    Then \"{embedded-iframe}\" is an object with the following contents\n      | tag    | atts.name           | style.width | style.height |\n      | iframe | FDC3 Communications |         0px |          0px |\n    And I refer to \"{childDoc.iframes[1]}\" as \"intent-resolver-iframe\"\n    And I refer to \"{childDoc.iframes[2]}\" as \"channel-selector-iframe\"\n    Then \"{channel-selector-iframe}\" is an object with the following contents\n      | tag    | atts.name             | atts.src                              | style.width | style.height |\n      | iframe | FDC3 Channel Selector | https://mock.fdc3.com/channelSelector |        100% |         100% |\n    Then \"{intent-resolver-iframe}\" is an object with the following contents\n      | tag    | atts.name            | atts.src                       | style.width | style.height |\n      | iframe | FDC3 Intent Resolver | https://mock.fdc3.com/resolver |        100% |         100% |\n    And \"{childWin.fdc3}\" is not null\n    And \"{childWin.events}\" is an array of objects with the following contents\n      | type      | data.type              |\n      | message   | WCP2LoadUrl            |\n      | message   | WCP3Handshake          |\n      | message   | Fdc3UserInterfaceHello |\n      | message   | Fdc3UserInterfaceHello |\n      | fdc3Ready | {null}                 |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Desktop Agent Preload (injected after the getAgent call with no event)\n    In this scenario, window.fdc3 is set by the electron container and returned by getAgent\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    And we wait for a period of \"500\" ms\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n\n  Scenario: Desktop Agent Preload (arrived after getAgent call with fdc3Ready event) \n    In this scenario, window.fdc3 is set by the electron container and returned by getAgent\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    And we wait for a period of \"100\" ms\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\" and fdc3Ready is fired\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n \n  Scenario: Desktop Agent preload (present before getAgent call)\n    In this scenario, window.fdc3 is set by the electron container and returned by getAgent\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n\n  Scenario: Failover Strategy returning desktop agent\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And \"dummyFailover\" is a function which returns a promise of \"{dummy-api}\"\n    And I call getAgent for a promise result with the following options\n      | failover        | timeoutMs |\n      | {dummyFailover} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n\n  Scenario: Failover Strategy returning a proxy\n    Given \"dummyFailover2\" is a function which opens an iframe for communications on \"{childDoc}\"\n    And I call getAgent for a promise result with the following options\n      | failover         | timeoutMs |\n      | {dummyFailover2} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Failover Strategy returning an invalid result\n    Given \"invalidFailover\" is a function which returns a promise of \"some string\"\n    And I call getAgent for a promise result with the following options\n      | failover        | timeoutMs |\n      | {invalidFailover} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"InvalidFailover\"\n\n  Scenario: Failover that is not a function\n    Given I call getAgent for a promise result with the following options\n      | failover        | timeoutMs |\n      | \"some string\" |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"InvalidFailover\"\n\n  Scenario: Failover with identity validation timeout\n    Given \"dummyFailover2\" is a function which opens an iframe for communications on \"{childDoc}\" but times out identity validation\n    And I call getAgent for a promise result with the following options\n      | failover         | timeoutMs |\n      | {dummyFailover2} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve within 10 seconds\n    And \"{result}\" is an error with message \"ErrorOnConnect\"\n\n  Scenario: Recover adaptor URL from SessionStorage\n  Here, we recover the details of the session from the session state, obviating the need to \n  make a request to the parent iframe.\n\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns iframe response\n    And an existing app instance in \"instanceID\"\n    And SessionStorage contains instanceUuid \"some-instance-uuid\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\", agentType \"PROXY_URL\" and agentUrl \"http://localhost:8080/static/da/embed.html\"\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    Then SessionStorage should contain instanceUuid \"some-instance-uuid\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\", agentType \"PROXY_URL\" and agentUrl \"http://localhost:8080/static/da/embed.html\"\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\nScenario: Go straight to (preload) failover as directed by SessionStorage\n  Here, we recover the details of the session from the session state, obviating the need to \n  to do discovery and going straight to failover.\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And \"dummyFailover\" is a function which returns a promise of \"{dummy-api}\"\n    And SessionStorage contains instanceUuid \"uuid-0\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\", agentType \"FAILOVER\" and agentUrl \"{undefined}\"\n    And I call getAgent for a promise result with the following options\n      | failover        | timeoutMs |\n      | {dummyFailover} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n    Then SessionStorage for identityUrl \"https://dummyOrigin.test/path\" should contain the following values\n      | appId        | agentType  | identityUrl                     |\n      | cucumber-app | FAILOVER   | https://dummyOrigin.test/path   |\n\n  Scenario: Go straight to (proxy) failover as directed by SessionStorage\n  Here, we recover the details of the session from the session state, obviating the need to \n  to do discovery and going straight to failover.\n\n    Given \"dummyFailover2\" is a function which opens an iframe for communications on \"{childDoc}\"\n    And I call getAgent for a promise result with the following options\n      | failover         | timeoutMs |\n      | {dummyFailover2} |      1000 |\n    And SessionStorage contains instanceUuid \"uuid-0\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\", agentType \"FAILOVER\" and agentUrl \"{undefined}\"\n    And I call getAgent for a promise result with the following options\n      | failover        | timeoutMs |\n      | {dummyFailover} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I call \"{result}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    Then SessionStorage for identityUrl \"https://dummyOrigin.test/path\" should contain the following values\n      | appId        | agentType  | identityUrl                   |\n      | cucumber-app | FAILOVER   | https://dummyOrigin.test/path |\n\n\n  Scenario: Handle corrupted data in SessionStorage\n  Here we deal with data in SessionStorage that is not in the proper format.\n\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And an existing app instance in \"instanceID\"\n    And SessionStorage contains corrupted data\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n  \n  Scenario: Handle truncated data in SessionStorage\n  Here we deal with data in SessionStorage that is only partially complete.\n\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And an existing app instance in \"instanceID\"\n    And SessionStorage contains partial data with with identityUrl \"https://dummyOrigin.test/path\", appId \"cucumber-app\" and agentType \"PROXY_PARENT\"\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Latch to Desktop Agent Proxy parent via SessionStorage\n  Here, we recover the details of the session from session storage, and latch to the\n  same Desktop Agent type (preload) - the connection should succeed.\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And SessionStorage contains instanceUuid \"{instanceID}\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\" and agentType \"PROXY_PARENT\"\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | cucumber-provider |\n\n  Scenario: Latch to Desktop Agent Preload via SessionStorage\n  Here, we recover the details of the session from session storage, and latch to the\n  same Desktop Agent type (preload) - the connection should succeed.\n\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And SessionStorage contains instanceUuid \"{instanceID}\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\" and agentType \"PRELOAD\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    And we wait for a period of \"500\" ms\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n\nScenario: Latch to Desktop Agent Preload via SessionStorage which has gone away\n  Here, we recover the details of the session from session storage, and latch to the\n  same Desktop Agent type (preload) - the connection should fail.\n    Given SessionStorage contains instanceUuid \"{instanceID}\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\" and agentType \"PRELOAD\"\n    And Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |    3000   | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"AgentNotFound\"\n\n  Scenario: Ignore invalid agentType in SessionStorage\n  Here, we recover the details of the session from session storage, \n  but it has an invalid agentType field - the connection should still succeed.\n    Given A Dummy Desktop Agent in \"dummy-api\"\n    And SessionStorage contains instanceUuid \"{instanceID}\", appId \"cucumber-app\" with identityUrl \"https://dummyOrigin.test/path\" and agentType \"SPOON\"\n    And `window.fdc3` is injected into the runtime with the value in \"{dummy-api}\"\n    And I call fdc3Ready for a promise result\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call \"{desktopAgent}\" with \"getInfo\"\n    Then \"{result}\" is an object with the following contents\n      | fdc3Version | appMetadata.appId | provider          |\n      |         2.0 | cucumber-app      | preload-provider |\n\n  Scenario: Nothing works and we timeout\n    When I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      4000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And \"{result}\" is an error with message \"AgentNotFound\"\n\n  Scenario: Someone calls getAgent twice\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise1\"\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |      8000 | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise2\"\n    Then the promise \"{theAPIPromise1}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent1\"\n    And the promise \"{theAPIPromise2}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent2\"\n    And \"{desktopAgent1}\" is \"{desktopAgent2}\"\n    And I call \"{desktopAgent1}\" with \"disconnect\"\n\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/proxy-timeouts.feature",
    "content": "Feature: Message exchange timeouts\n\n  Background: Desktop Agent API\n    Given a parent window document in \"parentDoc\", window in \"parentWin\", child window document in \"childDoc\" and window in \"childWin\"\n    And SessionStorage is clear\n\n  Scenario: Desktop Agent times out message exchanges when running inside a Browser with custom timeout\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response and times out message exchanges\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |    8000   | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call broadcast with an fdc3.instrument context on \"{desktopAgent}\" and allow 3 seconds\n    Then \"{result}\" is an error with message \"ApiTimeout\"\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Desktop Agent times out app launch when running inside a Browser with custom timeout\n    Given Parent Window desktop \"da\" listens for postMessage events in \"{parentWin}\", returns direct message response, times out message exchanges and uses message exchange timeout \"{1000}\" ms and app launch timeout \"{2000}\" ms\n    And we wait for a period of \"200\" ms\n    And I call getAgent for a promise result with the following options\n      | dontSetWindowFdc3 | timeoutMs | intentResolver | channelSelector |\n      | true              |    8000   | false          | false           |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call open with appId \"someApp\" on \"{desktopAgent}\" and allow 3 seconds\n    Then \"{result}\" is an error with message \"ApiTimeout\"\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Desktop Agent times out message exchanges when running in browser and connected via failover with custom timeout\n    Given \"dummyFailover\" is a function which opens an iframe for communications on \"{childDoc}\", times out message exchanges and uses message exchange timeout \"{1000}\" ms and app launch timeout \"{2000}\" ms\n    And I call getAgent for a promise result with the following options\n      | failover         | timeoutMs |\n      | {dummyFailover}  |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call broadcast with an fdc3.instrument context on \"{desktopAgent}\" and allow 3 seconds\n    Then \"{result}\" is an error with message \"ApiTimeout\"\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n  Scenario: Desktop Agent times out app launch when running in browser and connected via failover with custom timeout\n    Given \"dummyFailover\" is a function which opens an iframe for communications on \"{childDoc}\", times out message exchanges and uses message exchange timeout \"{1000}\" ms and app launch timeout \"{2000}\" ms\n    And I call getAgent for a promise result with the following options\n      | failover         | timeoutMs |\n      | {dummyFailover} |      1000 |\n    And I refer to \"{result}\" as \"theAPIPromise\"\n    Then the promise \"{theAPIPromise}\" should resolve\n    And I refer to \"{result}\" as \"desktopAgent\"\n    And I call open with appId \"someApp\" on \"{desktopAgent}\" and allow 3 seconds\n    Then \"{result}\" is an error with message \"ApiTimeout\"\n    And I call \"{desktopAgent}\" with \"disconnect\"\n\n\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/features/utils.feature",
    "content": "Feature: Utility functions\n\n  Scenario: Logger utility\n    When All log functions are used with a message\n    When All log functions are used with an error\n\n  Scenario: UUID generator\n    When A uuid is generated\n    \n# Uncomment to debug the tests not exiting - will dump a list of open handles keeping node open\n#   Scenario: We dump any open handles\n#     Given I call \"{parentDoc}\" with \"shutdown\"\n#     Then I call \"{childDoc}\" with \"shutdown\"\n#     Then Testing ends after \"8000\" ms \n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/channel-selector.steps.ts",
    "content": "import { Given } from 'quickpickle';\nimport { handleResolve } from '@finos/testing';\nimport { DefaultDesktopAgentChannelSelector } from '../../src/ui/DefaultDesktopAgentChannelSelector.js';\nimport { CHANNEL_SELECTOR_URL } from '../support/MockFDC3Server.js';\nimport { USER_CHANNELS } from '../support/responses/UserChannels.js';\nimport { CustomWorld } from '../world/index.js';\nimport { Fdc3UserInterfaceChannelSelected } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Logger } from '../../src/util/Logger.js';\nimport { loggingSettings } from './desktop-agent.steps.js';\n\nGiven(\n  'A Channel Selector in {string} with callback piping to {string}',\n  async (world: CustomWorld, field: string, cb: string) => {\n    Logger.setLogLevel(loggingSettings.connection);\n\n    const cs = new DefaultDesktopAgentChannelSelector(CHANNEL_SELECTOR_URL);\n\n    cs.setChannelChangeCallback((channelId: string | null) => {\n      world.props[cb] = channelId;\n    });\n\n    world.props[field] = cs;\n    await cs.connect();\n  }\n);\n\nGiven('User Channels one, two and three in {string}', (world: CustomWorld, field: string) => {\n  world.props[field] = USER_CHANNELS;\n});\n\nGiven(\n  'The channel selector sends a channel change message for channel {string}',\n  async (world: CustomWorld, channel: string) => {\n    const port = handleResolve('{childDoc.iframes[0].messageChannels[0].port2}', world);\n    const msg: Fdc3UserInterfaceChannelSelected = {\n      type: 'Fdc3UserInterfaceChannelSelected',\n      payload: {\n        selected: channel,\n      },\n    };\n    port.postMessage(msg);\n  }\n);\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/desktop-agent-api.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { handleResolve } from '@finos/testing';\nimport { CustomWorld } from '../world/index.js';\nimport { DesktopAgent } from '@finos/fdc3-standard';\nimport { Instrument } from '@finos/fdc3-context';\n\nWhen(\n  'I call broadcast with an fdc3.instrument context on {string} and allow 3 seconds',\n  async (world: CustomWorld, field: string) => {\n    try {\n      const da: DesktopAgent = handleResolve(field, world);\n      const instrument: Instrument = {\n        type: 'fdc3.instrument',\n        id: { ticker: 'MSFT' },\n        name: 'microsoft',\n      };\n      const result = await da.broadcast(instrument);\n      world.props['result'] = result;\n      world.log('Received non-error result: ' + JSON.stringify(result));\n    } catch (error) {\n      world.props['result'] = error;\n      world.log('Received error with message: ' + ((error as Error).message ?? error));\n    }\n  }\n);\n\nWhen(\n  'I call open with appId {string} on {string} and allow 3 seconds',\n  async (world: CustomWorld, appId: string, field: string) => {\n    try {\n      const da: DesktopAgent = handleResolve(field, world);\n      const result = await da.open({ appId: appId });\n      world.props['result'] = result;\n      world.log('Received non-error result: ' + JSON.stringify(result));\n    } catch (error) {\n      world.props['result'] = error;\n      world.log('Received error with message: ' + ((error as Error).message ?? error));\n    }\n  }\n);\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/desktop-agent.steps.ts",
    "content": "import { After, Given, Then, When } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { CustomWorld } from '../world/index.js';\nimport { doesRowMatch, handleResolve } from '@finos/testing';\nimport { MockDocument } from '../support/MockDocument.js';\nimport { MockWindow } from '../support/MockWindow.js';\nimport { fdc3Ready, getAgent } from '../../src/index.js';\nimport {\n  DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX,\n  DesktopAgentDetails,\n  GetAgentLogLevels,\n  GetAgentParams,\n  LogLevel,\n} from '@finos/fdc3-standard';\nimport { EMBED_URL, MockFDC3Server } from '../support/MockFDC3Server.js';\nimport { MockStorage } from '../support/MockStorage.js';\nimport { DesktopAgent, ImplementationMetadata } from '@finos/fdc3-standard';\nimport { clearAgentPromise } from '../../src/strategies/getAgent.js';\nimport { expect } from 'vitest';\nimport { dummyInstanceDetails } from '../support/TestServerContext.js';\nimport { MockIFrame } from '../support/MockIFrame.js';\n\ninterface MockPageTransitionEvent extends Event {\n  persisted?: boolean;\n}\n\nexport const loggingSettings: GetAgentLogLevels = {\n  connection: LogLevel.INFO,\n  proxy: LogLevel.INFO,\n};\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns direct message response',\n  async (world: CustomWorld, field: string, w: string) => {\n    const mockWindow = handleResolve(w, world);\n    world.mockFDC3Server = new MockFDC3Server(mockWindow, false, world.mockContext);\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns direct message response, but times out identity validation',\n  async (world: CustomWorld, field: string, w: string) => {\n    const mockWindow = handleResolve(w, world);\n    world.mockFDC3Server = new MockFDC3Server(mockWindow, false, world.mockContext, true, true);\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns direct message response and uses default UI URLs',\n  async (world: CustomWorld, field: string, w: string) => {\n    const mockWindow = handleResolve(w, world);\n    world.mockFDC3Server = new MockFDC3Server(mockWindow, false, world.mockContext, true);\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns direct message response and times out message exchanges',\n  async (world: CustomWorld, field: string, w: string) => {\n    const mockWindow = handleResolve(w, world);\n    world.mockFDC3Server = new MockFDC3Server(mockWindow, false, world.mockContext, true, false, true);\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns direct message response, times out message exchanges and uses message exchange timeout {string} ms and app launch timeout {string} ms',\n  async (world: CustomWorld, field: string, w: string, t1: string, t2: string) => {\n    const mockWindow = handleResolve(w, world);\n    const messageExchangeTimeout: number = handleResolve(t1, world);\n    const appLaunchTimeout: number = handleResolve(t2, world);\n    world.mockFDC3Server = new MockFDC3Server(\n      mockWindow,\n      false,\n      world.mockContext,\n      true,\n      false,\n      true,\n      messageExchangeTimeout,\n      appLaunchTimeout\n    );\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  'Parent Window desktop {string} listens for postMessage events in {string}, returns iframe response',\n  async (world: CustomWorld, field: string, w: string) => {\n    const mockWindow = handleResolve(w, world);\n    world.mockFDC3Server = new MockFDC3Server(mockWindow, true, world.mockContext);\n    world.props[field] = world.mockFDC3Server;\n    world.mockContext.open(dummyInstanceDetails[0].appId);\n    world.mockContext.open(dummyInstanceDetails[1].appId);\n  }\n);\n\nGiven(\n  '{string} is a function which opens an iframe for communications on {string}',\n  (world: CustomWorld, fn: string, doc: string) => {\n    world.props[fn] = () => {\n      world.mockContext.open(dummyInstanceDetails[0].appId);\n      const document = handleResolve(doc, world) as MockDocument;\n      const ifrm = document.createElement('iframe');\n\n      world.mockFDC3Server = new MockFDC3Server(ifrm as unknown as MockIFrame, false, world.mockContext);\n      ifrm.setAttribute('src', EMBED_URL);\n      document.body.appendChild(ifrm);\n      return ifrm;\n    };\n  }\n);\n\nGiven(\n  '{string} is a function which opens an iframe for communications on {string} but times out identity validation',\n  (world: CustomWorld, fn: string, doc: string) => {\n    world.props[fn] = () => {\n      world.mockContext.open(dummyInstanceDetails[0].appId);\n      const document = handleResolve(doc, world) as MockDocument;\n      const ifrm = document.createElement('iframe');\n\n      world.mockFDC3Server = new MockFDC3Server(ifrm as unknown as MockIFrame, false, world.mockContext, true, true);\n      ifrm.setAttribute('src', EMBED_URL);\n      document.body.appendChild(ifrm);\n      return ifrm;\n    };\n  }\n);\n\nGiven(\n  '{string} is a function which opens an iframe for communications on {string} and times out message exchanges',\n  (world: CustomWorld, fn: string, doc: string) => {\n    world.props[fn] = () => {\n      world.mockContext.open(dummyInstanceDetails[0].appId);\n      const document = handleResolve(doc, world) as MockDocument;\n      const ifrm = document.createElement('iframe');\n\n      world.mockFDC3Server = new MockFDC3Server(\n        ifrm as unknown as MockIFrame,\n        false,\n        world.mockContext,\n        false,\n        false,\n        true\n      );\n      ifrm.setAttribute('src', EMBED_URL);\n      document.body.appendChild(ifrm);\n      return ifrm;\n    };\n  }\n);\n\nGiven(\n  '{string} is a function which opens an iframe for communications on {string}, times out message exchanges and uses message exchange timeout {string} ms and app launch timeout {string} ms',\n  (world: CustomWorld, fn: string, doc: string, t1: string, t2: string) => {\n    const messageExchangeTimeout: number = handleResolve(t1, world);\n    const appLaunchTimeout: number = handleResolve(t2, world);\n    world.props[fn] = () => {\n      world.mockContext.open(dummyInstanceDetails[0].appId);\n      const document = handleResolve(doc, world) as MockDocument;\n      const ifrm = document.createElement('iframe');\n\n      world.mockFDC3Server = new MockFDC3Server(\n        ifrm as unknown as MockIFrame,\n        false,\n        world.mockContext,\n        false,\n        false,\n        true,\n        messageExchangeTimeout,\n        appLaunchTimeout\n      );\n      ifrm.setAttribute('src', EMBED_URL);\n      document.body.appendChild(ifrm);\n      return ifrm;\n    };\n  }\n);\n\nGiven('an existing app instance in {string}', async (world: CustomWorld, field: string) => {\n  const uuid = world.mockContext.open(dummyInstanceDetails[0].appId);\n  world.props[field] = uuid;\n});\n\nGiven('A Dummy Desktop Agent in {string}', async (world: CustomWorld, field: string) => {\n  const notImplemented = () => {\n    throw new Error('Function not implemented.');\n  };\n  const da: DesktopAgent = {\n    async getInfo(): Promise<ImplementationMetadata> {\n      return {\n        fdc3Version: '2.0',\n        optionalFeatures: {\n          DesktopAgentBridging: false,\n          OriginatingAppMetadata: false,\n          UserChannelMembershipAPIs: false,\n        },\n        appMetadata: {\n          appId: 'cucumber-app',\n          instanceId: 'uuid-0',\n        },\n        provider: 'preload-provider',\n      };\n    },\n    open: notImplemented,\n    findIntent: notImplemented,\n    findIntentsByContext: notImplemented,\n    findInstances: notImplemented,\n    broadcast: notImplemented,\n    raiseIntent: notImplemented,\n    raiseIntentForContext: notImplemented,\n    addIntentListener: notImplemented,\n    addContextListener: notImplemented,\n    addEventListener: notImplemented,\n    getUserChannels: notImplemented,\n    joinUserChannel: notImplemented,\n    getOrCreateChannel: notImplemented,\n    createPrivateChannel: notImplemented,\n    getCurrentChannel: notImplemented,\n    leaveCurrentChannel: notImplemented,\n    getAppMetadata: notImplemented,\n    getSystemChannels: notImplemented,\n    joinChannel: notImplemented,\n  };\n\n  world.props[field] = da;\n  world.props['result'] = null;\n});\n\nGiven(\n  '`window.fdc3` is injected into the runtime with the value in {string}',\n  async (world: CustomWorld, field: string) => {\n    const object = handleResolve(field, world);\n    window.fdc3 = object;\n  }\n);\n\nGiven(\n  '`window.fdc3` is injected into the runtime with the value in {string} and fdc3Ready is fired',\n  async (world: CustomWorld, field: string) => {\n    const object = handleResolve(field, world);\n    window.fdc3 = object;\n    window.dispatchEvent(new Event('fdc3Ready'));\n  }\n);\n\nWhen('I call getAgent for a promise result', (world: CustomWorld) => {\n  try {\n    const params: GetAgentParams = {\n      logLevels: loggingSettings,\n    };\n    world.props['result'] = getAgent(params);\n  } catch (error) {\n    world.props['result'] = error;\n  }\n});\n\nWhen('I call fdc3Ready for a promise result', (world: CustomWorld) => {\n  try {\n    world.props['result'] = fdc3Ready();\n  } catch (error) {\n    world.props['result'] = error;\n  }\n});\n\nAfter((world: CustomWorld) => {\n  console.log('    Cleaning up test infrastructure');\n  clearAgentPromise();\n  MockDocument.shutdownAllDocuments();\n});\n\nWhen('I call getAgent for a promise result with the following options', (world: CustomWorld, dt: DataTable) => {\n  try {\n    const first = dt.hashes()[0];\n    const toArgs: GetAgentParams = Object.fromEntries(\n      Object.entries(first).map(([k, v]) => {\n        const val = handleResolve(v, world);\n        const val2 = isNaN(val) ? val : Number(val);\n        const val3 = val2 === 'true' ? true : val2 === 'false' ? false : val2;\n        return [k, val3];\n      })\n    );\n    toArgs.logLevels = loggingSettings;\n    world.props['result'] = getAgent(toArgs);\n  } catch (error) {\n    world.props['result'] = error;\n  }\n});\n\nGiven(\n  'a parent window document in {string}, window in {string}, child window document in {string} and window in {string}',\n  async (world: CustomWorld, pd: string, pw: string, cd: string, cw: string) => {\n    const mpw = new MockWindow('mockParentWindow', world, 'parentWin');\n    world.props[pw] = mpw;\n\n    world.props[pd] = new MockDocument('parentDoc', mpw);\n\n    const mcw = new MockWindow('mockWindow', world, 'mocky');\n    world.props[cw] = mcw;\n\n    world.props[cd] = new MockDocument('childDoc', mcw);\n\n    globalThis.window = world.props[cw];\n    globalThis.document = world.props[cd];\n\n    mcw.parent = mpw;\n\n    mpw.child = mcw;\n\n    globalThis.sessionStorage = new MockStorage();\n  }\n);\n\nGiven(\n  'SessionStorage contains instanceUuid {string}, appId {string} with identityUrl {string} and agentType {string}',\n  async (world: CustomWorld, uuid: string, appId: string, identityUrl: string, agentType: string) => {\n    const theUuid = handleResolve(uuid, world);\n    const theAppId = handleResolve(appId, world);\n    const theIdentityUrl = handleResolve(identityUrl, world);\n    const theAgentType = handleResolve(agentType, world);\n    const details: Record<string, DesktopAgentDetails> = {};\n    details[theIdentityUrl] = {\n      agentType: theAgentType,\n      instanceUuid: theUuid,\n      appId: theAppId,\n      instanceId: 'uuid-0',\n      identityUrl: theIdentityUrl,\n      actualUrl: theIdentityUrl,\n    };\n\n    globalThis.sessionStorage.setItem(DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky', JSON.stringify(details));\n  }\n);\n\nGiven(\n  'SessionStorage contains instanceUuid {string}, appId {string} with identityUrl {string}, agentType {string} and agentUrl {string}',\n  async (world: CustomWorld, uuid: string, appId: string, identityUrl: string, agentType: string, agentUrl: string) => {\n    const theUuid = handleResolve(uuid, world);\n    const theAppId = handleResolve(appId, world);\n    const theIdentityUrl = handleResolve(identityUrl, world);\n    const theAgentType = handleResolve(agentType, world);\n    const theAgentUrl = handleResolve(agentUrl, world);\n    const details: Record<string, DesktopAgentDetails> = {};\n    details[theIdentityUrl] = {\n      agentType: theAgentType,\n      instanceUuid: theUuid,\n      appId: theAppId,\n      instanceId: 'uuid-0',\n      identityUrl: theIdentityUrl,\n      actualUrl: theIdentityUrl,\n      agentUrl: theAgentUrl,\n    };\n\n    globalThis.sessionStorage.setItem(DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky', JSON.stringify(details));\n  }\n);\n\nGiven(\n  'SessionStorage contains partial data with with identityUrl {string}, appId {string} and agentType {string}',\n  async (world: CustomWorld, identityUrl: string, agentType: string, appId: string) => {\n    const theIdentityUrl = handleResolve(identityUrl, world);\n    const theAgentType = handleResolve(agentType, world);\n    const theAppId = handleResolve(appId, world);\n\n    const partialDetails: Record<string, Partial<DesktopAgentDetails>> = {};\n    partialDetails[theIdentityUrl] = {\n      agentType: theAgentType,\n      appId: theAppId,\n      identityUrl: identityUrl,\n    };\n\n    globalThis.sessionStorage.setItem(\n      DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky',\n      JSON.stringify(partialDetails)\n    );\n  }\n);\n\nGiven('SessionStorage contains corrupted data', async () => {\n  const corruptedData = ['All your base are belong to us'];\n\n  globalThis.sessionStorage.setItem(DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky', JSON.stringify(corruptedData));\n});\n\nGiven('SessionStorage is clear', async () => {\n  globalThis.sessionStorage.clear();\n});\n\nThen(\n  'SessionStorage should contain instanceUuid {string}, appId {string} with identityUrl {string}, agentType {string} and agentUrl {string}',\n  async (world: CustomWorld, uuid: string, appId: string, identityUrl: string, agentType: string, agentUrl: string) => {\n    const theUuid = handleResolve(uuid, world);\n    const theAppId = handleResolve(appId, world);\n    const theIdentityUrl = handleResolve(identityUrl, world);\n    const theAgentType = handleResolve(agentType, world);\n    const theAgentUrl = handleResolve(agentUrl, world);\n\n    const value = globalThis.sessionStorage.getItem(DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky');\n    expect(value).toBeTruthy();\n    const theObject = JSON.parse(value!);\n    const details = theObject[theIdentityUrl];\n    expect(details).toBeTruthy();\n    expect(details.agentType).toEqual(theAgentType);\n    expect(details.agentUrl).toEqual(theAgentUrl);\n    expect(details.appId).toEqual(theAppId);\n    expect(details.instanceUuid).toEqual(theUuid);\n  }\n);\n\nThen(\n  'SessionStorage for identityUrl {string} should contain the following values',\n  (world: CustomWorld, identityUrl: string, dt: DataTable) => {\n    const theIdentityUrl = handleResolve(identityUrl, world);\n    const value = globalThis.sessionStorage.getItem(DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX + '-mocky');\n    expect(value).toBeTruthy();\n    const theObject = JSON.parse(value!);\n    const details = theObject[theIdentityUrl];\n    const table = dt.hashes();\n    expect(doesRowMatch(world, table[0], details)).toBeTruthy();\n  }\n);\n\nWhen(\n  '{string} pagehide occurs with persisted = {string}',\n  async (world: CustomWorld, field: string, persisted: string) => {\n    const window: MockWindow = handleResolve(field, world);\n    const isPersisted = handleResolve(persisted, world);\n    const transitionEvent: MockPageTransitionEvent = new Event('pagehide');\n    transitionEvent.persisted = isPersisted;\n    window.dispatchEvent(transitionEvent);\n  }\n);\n\nWhen('The Desktop Agent receives a WCP6Goodbye message', async (world: CustomWorld) => {\n  expect(world.mockFDC3Server?.hasReceivedGoodbye).toBeTruthy();\n});\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/generic.steps.ts",
    "content": "import { setupGenericSteps } from '@finos/testing';\nimport path from 'path';\n\n// Register shared generic steps from @finos/testing\nconst schemaBasePath = path.join(import.meta.dirname, '../../../');\nsetupGenericSteps(schemaBasePath);\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/intent-resolver.steps.ts",
    "content": "import { Given, When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { handleResolve } from '@finos/testing';\nimport { DefaultDesktopAgentIntentResolver } from '../../src/ui/DefaultDesktopAgentIntentResolver.js';\nimport { INTENT_RESOLVER_URL } from '../support/MockFDC3Server.js';\nimport { FDC3_USER_INTERFACE_RESOLVE_ACTION_TYPE } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Context } from '@finos/fdc3-context';\nimport { loggingSettings } from './desktop-agent.steps.js';\nimport { Logger } from '@finos/fdc3-agent-proxy/src/util/Logger';\n\nLogger.setLogLevel(loggingSettings.connection);\n\nconst contextMap: Record<string, Context> = {\n  'fdc3.instrument': {\n    type: 'fdc3.instrument',\n    name: 'Apple',\n    id: {\n      ticker: 'AAPL',\n    },\n  },\n  'fdc3.country': {\n    type: 'fdc3.country',\n    name: 'Sweden',\n    id: {\n      COUNTRY_ISOALPHA2: 'SE',\n      COUNTRY_ISOALPHA3: 'SWE',\n    },\n  },\n  'fdc3.unsupported': {\n    type: 'fdc3.unsupported',\n    bogus: true,\n  },\n};\n\nGiven('{string} is a {string} context', (world: CustomWorld, field: string, type: string) => {\n  world.props[field] = contextMap[type];\n});\n\nGiven('An Intent Resolver in {string}', async (world: CustomWorld, field: string) => {\n  const cs = new DefaultDesktopAgentIntentResolver(INTENT_RESOLVER_URL);\n  world.props[field] = cs;\n  await cs.connect();\n});\n\nGiven('{string} is an AppIntents array with a ViewNews intent and two apps', (world: CustomWorld, field: string) => {\n  world.props[field] = [\n    {\n      intent: {\n        name: 'ViewNews',\n      },\n      apps: [\n        {\n          appId: 'app1',\n        },\n        {\n          appId: 'app2',\n        },\n      ],\n    },\n  ];\n});\n\nWhen(\n  'I call {string} with {string} with parameters {string} and {string} for a promise',\n  (world: CustomWorld, field: string, fnName: string, param1: string, param2: string) => {\n    try {\n      const object = handleResolve(field, world);\n      const fn = object[fnName];\n      const arg0 = handleResolve(param1, world);\n      const arg1 = handleResolve(param2, world);\n      const result = fn.call(object, arg0, arg1);\n      world.props['result'] = result;\n    } catch (error) {\n      world.props['result'] = error;\n    }\n  }\n);\n\nGiven('The intent resolver sends an intent selection message', async (world: CustomWorld) => {\n  const port = handleResolve('{childDoc.iframes[0].messageChannels[0].port2}', world);\n\n  port.postMessage({\n    type: FDC3_USER_INTERFACE_RESOLVE_ACTION_TYPE,\n    payload: {\n      action: 'click',\n      appIdentifier: {\n        appId: 'app1',\n      },\n      intent: 'ViewNews',\n    },\n  });\n});\n\nGiven('The intent resolver cancels the intent selection message', async (world: CustomWorld) => {\n  const port = handleResolve('{childDoc.iframes[0].messageChannels[0].port2}', world);\n\n  port.postMessage({\n    type: FDC3_USER_INTERFACE_RESOLVE_ACTION_TYPE,\n    payload: {\n      action: 'cancel',\n    },\n  });\n});\n\n// Given('{string} receives a {string} message for the intent resolver and pipes comms to {string}', async function (this: CustomWorld, frame: string, type: string, output: string) {\n//     const channelSelectorIframe = handleResolve(frame, this)\n//     const mc = new MessageChannel();\n//     const internalPort = mc.port1;\n//     const externalPort = mc.port2;\n\n//     if (type == \"SelectorMessageInitialize\") {\n//         globalThis.window.dispatchEvent({\n//             type: 'message',\n//             data: {\n//                 type: 'SelectorMessageInitialize'\n//             },\n//             origin: globalThis.window.location.origin,\n//             ports: [externalPort],\n//             source: channelSelectorIframe\n//         } as any)\n//     }\n\n//     const out: any[] = []\n//     this.props[output] = out\n\n//     internalPort.start()\n//     internalPort.onmessage = (e) => {\n//         out.push({ type: e.type, data: e.data })\n//     }\n// });\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/port-creation.steps.ts",
    "content": "import { Given, Then } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { handleResolve } from '@finos/testing';\nimport wtf from 'wtfnode';\n\nGiven(\n  '{string} receives a {string} message for the {string} and creates port {string}',\n  async (world: CustomWorld, frame: string, type: string, _item: string, port: string) => {\n    const channelSelectorIframe = handleResolve(frame, world);\n    const mc = new MessageChannel();\n    const internalPort = mc.port1;\n    const externalPort = mc.port2;\n\n    if (type == 'SelectorMessageInitialize') {\n      globalThis.window.dispatchEvent({\n        type: 'message',\n        data: {\n          type: 'SelectorMessageInitialize',\n        },\n        origin: globalThis.window.location.origin,\n        ports: [externalPort],\n        source: channelSelectorIframe,\n      } as unknown as Event);\n    }\n\n    internalPort.start();\n    world.props[port] = internalPort;\n  }\n);\n\nGiven('{string} pipes messages to {string}', async (world: CustomWorld, port: string, output: string) => {\n  const out: { type: string; data: unknown }[] = [];\n  world.props[output] = out;\n\n  const internalPort = handleResolve(port, world);\n  internalPort.onmessage = (e: MessageEvent) => {\n    out.push({ type: e.type, data: e.data });\n  };\n});\n\nGiven('Testing ends after {string} ms', (world: CustomWorld, string: string) => {\n  setTimeout(() => {\n    wtf.dump();\n\n    process.exit();\n  }, parseInt(string));\n});\n\nThen('{string} receives a {string} message', (world: CustomWorld, port: string, type: string) => {\n  const internalPort = handleResolve(port, world);\n\n  if (type == 'ResolverMessageChoice') {\n    (internalPort as MessagePort).postMessage({\n      type,\n      payload: {\n        intent: 'viewNews',\n        target: {\n          appId: 'test-app-1',\n        },\n      },\n    });\n  }\n});\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/step-definitions/util.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { Logger } from '../../src/util/Logger.js';\nimport { createUUID } from '../../src/util/Uuid.js';\n\nconst TEST_ERROR = 'Test error - This is expected on the console';\n\nWhen('All log functions are used with a message', async (world: CustomWorld) => {\n  Logger.debug('Debug msg');\n  Logger.log('Log msg');\n  Logger.warn('Warning msg');\n  Logger.error('Error msg');\n});\n\nWhen('All log functions are used with an error', async (world: CustomWorld) => {\n  Logger.debug('debug-level error: ', new Error(TEST_ERROR));\n  Logger.log('log-level error: ', new Error(TEST_ERROR));\n  Logger.warn('warn-level error: ', new Error(TEST_ERROR));\n  Logger.error('error-level error: ', new Error(TEST_ERROR));\n});\n\nWhen('A uuid is generated', async (world: CustomWorld) => {\n  return createUUID();\n});\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/steps.ts",
    "content": "// Main step definitions entry point for quickpickle\n// This file is loaded by vitest as a setupFile\n\nimport { setWorldConstructor } from 'quickpickle';\nimport { CustomWorld } from './world/index.js';\n\n// Set up the world constructor\nsetWorldConstructor(CustomWorld);\n\n// Import all step definitions\nimport './step-definitions/generic.steps.js';\nimport './step-definitions/channel-selector.steps.js';\nimport './step-definitions/desktop-agent-api.steps.js';\nimport './step-definitions/desktop-agent.steps.js';\nimport './step-definitions/intent-resolver.steps.js';\nimport './step-definitions/port-creation.steps.js';\nimport './step-definitions/util.steps.js';\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/EventHandler.ts",
    "content": "export type EventHandler = {\n  type: string;\n  callback: (e: Event) => void;\n};\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/FrameTypes.ts",
    "content": "import { CustomWorld } from '../world/index.js';\nimport { MockWindow } from './MockWindow.js';\nimport { CHANNEL_SELECTOR_URL, INTENT_RESOLVER_URL } from './MockFDC3Server.js';\nimport { isWebConnectionProtocol1Hello } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport {\n  Fdc3UserInterfaceHello,\n  Fdc3UserInterfaceRestyle,\n  isFdc3UserInterfaceHandshake,\n  WebConnectionProtocol3Handshake,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\n/**\n * This handles the frame communications when we're using the embedded iframe approach\n */\nexport function handleEmbeddedIframeComms(_value: string, parent: MockWindow, source: MockWindow, cw: CustomWorld) {\n  const helloHandler = (e: Event) => {\n    const event = e as MessageEvent;\n    const eventSource = event.source as unknown as MockWindow;\n    const data = event.data;\n\n    if (isWebConnectionProtocol1Hello(data)) {\n      console.debug(\n        'Received hello message from: ',\n        eventSource.name,\n        eventSource == parent ? '(parent window): ' : '(NOT parent win): ',\n        event.data\n      );\n      const connection = cw.mockContext.getFirstInstance();\n\n      // send the other end of the channel to the app\n      const message: WebConnectionProtocol3Handshake = {\n        type: 'WCP3Handshake',\n        meta: {\n          connectionAttemptUuid: data.meta.connectionAttemptUuid,\n          timestamp: new Date(),\n        },\n        payload: {\n          fdc3Version: '2.2',\n          channelSelectorUrl: CHANNEL_SELECTOR_URL,\n          intentResolverUrl: INTENT_RESOLVER_URL,\n        },\n      };\n      // nosemgrep\n      eventSource.postMessage(message, '*', [connection!.externalPort]);\n\n      window.removeEventListener('message', helloHandler);\n    } else {\n      console.warn(`Unexpected message received by MockIframe - ignored`, e);\n    }\n  };\n\n  //listen for hello message events from parent to respond to\n  source.addEventListener('message', helloHandler);\n}\n\nexport function handleChannelSelectorComms(\n  _value: string,\n  parent: MockWindow,\n  source: MockWindow,\n  cw: CustomWorld\n): MessageChannel {\n  const connection = new MessageChannel();\n  try {\n    const msg: Fdc3UserInterfaceHello = {\n      type: 'Fdc3UserInterfaceHello',\n      payload: {\n        implementationDetails: 'mock channel selector',\n        initialCSS: {\n          width: '100px',\n        },\n      },\n    };\n\n    const event: Event = {\n      type: 'message',\n      data: msg,\n      origin: CHANNEL_SELECTOR_URL,\n      source: source,\n      ports: [connection.port1],\n    } as unknown as Event;\n    parent.dispatchEvent(event);\n\n    connection.port2.onmessage = e => {\n      if (isFdc3UserInterfaceHandshake(e.data)) {\n        setTimeout(() => {\n          const msg: Fdc3UserInterfaceRestyle = {\n            type: 'Fdc3UserInterfaceRestyle',\n            payload: {\n              updatedCSS: {\n                width: '100px',\n              },\n            },\n          };\n          connection.port2.postMessage(msg);\n        }, 100);\n      }\n      cw.props['lastChannelSelectorMessage'] = e.data;\n    };\n  } catch (e) {\n    console.error(e);\n  }\n\n  return connection;\n}\n\nexport function handleIntentResolverComms(\n  _value: string,\n  parent: MockWindow,\n  source: MockWindow,\n  cw: CustomWorld\n): MessageChannel {\n  const connection = new MessageChannel();\n  try {\n    const msg: Fdc3UserInterfaceHello = {\n      type: 'Fdc3UserInterfaceHello',\n      payload: {\n        implementationDetails: 'mock intent resolver',\n        initialCSS: {\n          width: '100px',\n        },\n      },\n    };\n    const event: Event = {\n      type: 'message',\n      data: msg,\n      origin: INTENT_RESOLVER_URL,\n      source,\n      ports: [connection.port1],\n    } as unknown as Event;\n    parent.dispatchEvent(event);\n\n    connection.port2.onmessage = e => {\n      if (isFdc3UserInterfaceHandshake(e.data)) {\n        setTimeout(() => {\n          const msg: Fdc3UserInterfaceRestyle = {\n            type: 'Fdc3UserInterfaceRestyle',\n            payload: {\n              updatedCSS: {\n                width: '100px',\n              },\n            },\n          };\n          connection.port2.postMessage(msg);\n        }, 100);\n      }\n\n      cw.props['lastIntentResolverMessage'] = e;\n    };\n  } catch (e) {\n    console.error(e);\n  }\n\n  return connection;\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockCSSStyleDeclaration.ts",
    "content": "export class MockCSSStyleDeclaration {\n  setProperty(name: string, value: string) {\n    (this as any)[name] = value;\n  }\n\n  removeProperty(name: string) {\n    delete (this as any)[name];\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockDocument.ts",
    "content": "import { MockWindow } from './MockWindow.js';\nimport { MockIFrame } from './MockIFrame.js';\nimport { MockElement } from './MockElement.js';\n\nexport class MockDocument {\n  name: string;\n  window: MockWindow;\n  iframes: MockIFrame[] = [];\n  static allDocuments: MockDocument[] = [];\n\n  constructor(name: string, window: MockWindow) {\n    this.name = name;\n    this.window = window;\n    if (this.window.cw.debugLogs) {\n      console.log(`MockDocument (name: ${name} / window.name: ${this.window.name}): Created`);\n    }\n    MockDocument.allDocuments.push(this);\n  }\n\n  createElement(tag: string): HTMLElement {\n    if (tag == 'iframe') {\n      if (this.window.cw.debugLogs) {\n        console.log(`MockDocument (name: ${this.name} / window.name: ${this.window.name}): creating iframe`);\n      }\n      const mw = new MockIFrame('iframe', this.window.cw, this.window, 'pending-iframe');\n      //n.b. variables are set on the parent window to link each iframe in order to allow use as source in\n      // postMessages from them - these are set in the MockIframe.setAttribute function\n\n      this.iframes.push(mw);\n\n      return mw as unknown as HTMLElement;\n    } else {\n      return new MockElement(tag) as unknown as HTMLElement;\n    }\n  }\n\n  getElementById(/*_id: string*/): HTMLElement | null {\n    return new MockElement('div') as unknown as HTMLElement;\n  }\n\n  body = new MockElement('body');\n\n  shutdown() {\n    this.window.shutdown();\n    this.iframes.forEach(i => i.shutdown());\n  }\n\n  static shutdownAllDocuments() {\n    MockDocument.allDocuments.forEach((doc: MockDocument) => {\n      doc.shutdown();\n    });\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockElement.ts",
    "content": "import { MockCSSStyleDeclaration } from './MockCSSStyleDeclaration.js';\nimport { MockIFrame } from './MockIFrame.js';\n\nexport class MockElement {\n  public tag: string;\n  public atts: { [name: string]: unknown } = {};\n  public children: HTMLElement[] = [];\n\n  constructor(tag: string) {\n    this.tag = tag;\n  }\n\n  style = new MockCSSStyleDeclaration();\n\n  setAttribute(name: string, value: string) {\n    this.atts[name] = value;\n  }\n\n  removeAttribute(name: string) {\n    delete this.atts[name];\n  }\n\n  appendChild(child: HTMLElement) {\n    this.children.push(child);\n\n    //if its an iframe make it load here\n    if ((child as unknown as MockIFrame).load) {\n      (child as unknown as MockIFrame).load();\n    }\n  }\n\n  removeChild(child: HTMLElement) {\n    this.children.splice(this.children.indexOf(child), 1);\n  }\n\n  remove() {}\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockFDC3Server.ts",
    "content": "import { FDC3Server, InstanceID, State } from '@finos/fdc3-web-impl';\nimport { TestServerContext } from './TestServerContext.js';\nimport { MockWindow } from './MockWindow.js';\nimport { AutomaticResponse } from './responses/AutomaticResponses.js';\nimport { Broadcast } from './responses/Broadcast.js';\nimport { FindIntent } from './responses/FindIntent.js';\nimport { RaiseIntent } from './responses/RaiseIntent.js';\nimport { Handshake } from './responses/Handshake.js';\nimport { UserChannels } from './responses/UserChannels.js';\nimport { CurrentChannel } from './responses/CurrentChannel.js';\nimport { GetInfo } from './responses/GetInfo.js';\nimport {\n  AppRequestMessage,\n  WebConnectionProtocol2LoadURL,\n  WebConnectionProtocol3Handshake,\n} from '@finos/fdc3-schema/generated/api/BrowserTypes';\nimport { AddEventListener } from './responses/AddEventListener';\nimport { UnsubscribeEventListener } from './responses/UnsubscribeEventListener';\n\nexport const EMBED_URL = 'http://localhost:8080/static/da/embed.html';\nexport const CHANNEL_SELECTOR_URL = 'https://mock.fdc3.com/channelSelector';\nexport const INTENT_RESOLVER_URL = 'https://mock.fdc3.com/resolver';\n\nexport class MockFDC3Server implements FDC3Server {\n  private useIframe: boolean;\n  private useDefaultUIUrls: boolean;\n  private timeOutIdValidation: boolean;\n  private window: MockWindow;\n  private tsc: TestServerContext;\n  private receivedGoodbye = false;\n  private messageExchangeTimeout: number | null = null;\n  private appLaunchTimeout: number | null = null;\n\n  readonly automaticResponses: AutomaticResponse[];\n\n  constructor(\n    window: MockWindow,\n    useIframe: boolean,\n    ctx: TestServerContext,\n    useDefaultUIUrls: boolean = false,\n    timeOutIdValidation: boolean = false,\n    timeoutMessageExchanges: boolean = false,\n    messageExchangeTimeout?: number,\n    appLaunchTimeout?: number\n  ) {\n    this.useIframe = useIframe;\n    this.useDefaultUIUrls = useDefaultUIUrls;\n    this.timeOutIdValidation = timeOutIdValidation;\n    this.window = window;\n    this.tsc = ctx;\n    if (messageExchangeTimeout) {\n      this.messageExchangeTimeout = messageExchangeTimeout;\n    }\n    if (appLaunchTimeout) {\n      this.appLaunchTimeout = appLaunchTimeout;\n    }\n\n    if (timeoutMessageExchanges) {\n      this.automaticResponses = [\n        new GetInfo(),\n        new Handshake(this.timeOutIdValidation),\n        new CurrentChannel(),\n        new UserChannels(),\n        new AddEventListener(),\n      ];\n    } else {\n      this.automaticResponses = [\n        new GetInfo(),\n        new Handshake(this.timeOutIdValidation),\n        new CurrentChannel(),\n        new FindIntent(),\n        new RaiseIntent(),\n        new UserChannels(),\n        new Broadcast(),\n        new AddEventListener(),\n        new UnsubscribeEventListener(),\n      ];\n    }\n\n    this.init();\n  }\n\n  cleanup(instanceId: InstanceID): void {\n    //message handler are faked with automated responses, so no need to clean up their state\n    this.tsc.setAppState(instanceId, State.Terminated);\n  }\n\n  async receive(message: AppRequestMessage, from: string): Promise<void> {\n    //If timeoutMessageExchanges was set then we will not respond to some messages here\n    this.automaticResponses.forEach(r => {\n      if (r.filter(message.type)) {\n        r.action(message, this.tsc, from);\n      }\n    });\n  }\n\n  shutdown() {\n    this.tsc.shutdown();\n  }\n\n  hasReceivedGoodbye(): boolean {\n    return this.receivedGoodbye;\n  }\n\n  init() {\n    this.window.addEventListener('message', e => {\n      const event = e as MessageEvent;\n      const data = event.data;\n      const source = event.source as Window;\n      const origin = event.origin;\n\n      if (this.tsc.cw.debugLogs) {\n        console.log('MockFDC3Server received: ', event.data);\n      }\n      if (data.type == 'WCP1Hello') {\n        if (this.useIframe) {\n          const message: WebConnectionProtocol2LoadURL = {\n            type: 'WCP2LoadUrl',\n            meta: {\n              connectionAttemptUuid: data.meta.connectionAttemptUuid,\n              timestamp: new Date(),\n            },\n            payload: {\n              iframeUrl: EMBED_URL + '?connectionAttemptUuid=' + data.meta.connectionAttemptUuid,\n            },\n          };\n          source.postMessage(message, origin);\n        } else {\n          const details = this.tsc.getMatchingInstance(data.payload.identityUrl);\n          if (details) {\n            const message: WebConnectionProtocol3Handshake = {\n              type: 'WCP3Handshake',\n              meta: {\n                connectionAttemptUuid: data.meta.connectionAttemptUuid,\n                timestamp: new Date(),\n              },\n              payload: {\n                fdc3Version: '2.2',\n                intentResolverUrl: this.useDefaultUIUrls ? true : INTENT_RESOLVER_URL,\n                channelSelectorUrl: this.useDefaultUIUrls ? true : CHANNEL_SELECTOR_URL,\n                messageExchangeTimeout: 1000,\n                appLaunchTimeout: 2000,\n              },\n            };\n            if (this.messageExchangeTimeout) {\n              message.payload.messageExchangeTimeout = this.messageExchangeTimeout;\n            }\n            if (this.appLaunchTimeout) {\n              message.payload.appLaunchTimeout = this.appLaunchTimeout;\n            }\n            source.postMessage(message, origin, [details.externalPort]);\n          } //getMatchingInstance will log if it didn't find anything\n        }\n      } else if (data.type == 'WCP6Goodbye') {\n        this.receivedGoodbye = true;\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockIFrame.ts",
    "content": "import { CustomWorld } from '../world/index.js';\nimport { handleChannelSelectorComms, handleEmbeddedIframeComms, handleIntentResolverComms } from './FrameTypes.js';\nimport { EMBED_URL, CHANNEL_SELECTOR_URL, INTENT_RESOLVER_URL } from './MockFDC3Server.js';\nimport { MockWindow } from './MockWindow.js';\n\nexport class MockIFrame extends MockWindow {\n  contentWindow: MockWindow;\n  messageChannels: MessageChannel[] = [];\n  parent: MockWindow;\n  initFn: (() => void) | null = null;\n\n  constructor(tag: string, cw: CustomWorld, parent: MockWindow, name: string) {\n    super(tag, cw, name);\n    this.parent = parent;\n    this.contentWindow = this;\n    if (this.cw.debugLogs) {\n      console.log(`MockIFrame (name: ${name} / parent.name: ${parent.name}): Created`);\n    }\n  }\n\n  /** Used to simulate the iframe loading. */\n  load(): void {\n    if (this.cw.debugLogs) {\n      console.log(`MockIFrame (name: ${this.name}): Dispatching load event`);\n    }\n\n    //if we've got an init fn *to simulate comms) call it before we dispatch the load event\n    if (this.initFn) {\n      this.initFn();\n    }\n\n    this.dispatchEvent(new Event('load'));\n  }\n\n  setAttribute(name: string, value: string): void {\n    this.atts[name] = value;\n    const parent = this.parent as MockWindow;\n\n    if (name === 'src') {\n      //set the frame up properly along wih a function to initialize comms when it loads\n      if (value.startsWith(EMBED_URL)) {\n        this.name = 'embedded-iframe';\n        this.parent.commsIframe = this;\n        this.initFn = () => {\n          handleEmbeddedIframeComms(value, parent, this.contentWindow, this.cw);\n        };\n        if (this.cw.debugLogs) {\n          console.debug(`MockIframe (name: ${this.name}): Created comms iframe with url: ${value}`);\n        }\n      } else if (value.startsWith(CHANNEL_SELECTOR_URL)) {\n        this.name = 'channel-selector';\n        this.parent.channelSelectorIframe = this;\n        this.initFn = () => {\n          this.messageChannels.push(handleChannelSelectorComms(value, parent, this.contentWindow, this.cw));\n        };\n        if (this.cw.debugLogs) {\n          console.debug(`MockIframe (name: ${this.name}): Created channel selector iframe with url: ${value}`);\n        }\n      } else if (value.startsWith(INTENT_RESOLVER_URL)) {\n        this.name = 'intent-resolver';\n        this.parent.intentResolverIframe = this;\n        this.initFn = () => {\n          this.messageChannels.push(handleIntentResolverComms(value, parent, this.contentWindow, this.cw));\n        };\n        if (this.cw.debugLogs) {\n          console.debug(`MockIframe (name: ${this.name}): Created intent resolver iframe with url: ${value}`);\n        }\n      } else {\n        if (this.cw.debugLogs) {\n          console.warn(`MockIframe (name: ${this.name}): Set an unrecognized URL: ${value}`);\n        }\n      }\n    } else if (name === 'name') {\n      if (this.cw.debugLogs) {\n        console.debug(`MockIframe (name: ${this.name}): setAttribute() changing iframe name to: ${value}`);\n      }\n      this.name = value;\n    }\n  }\n\n  shutdown() {\n    super.shutdown();\n    this.messageChannels.forEach(mc => {\n      mc.port1.close();\n      mc.port2.close();\n    });\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockStorage.ts",
    "content": "export class MockStorage implements Storage {\n  private store: { [key: string]: string } = {};\n\n  get length(): number {\n    return Object.keys(this.store).length;\n  }\n\n  clear(): void {\n    this.store = {};\n  }\n\n  getItem(key: string): string | null {\n    return this.store[key] || null;\n  }\n\n  key(index: number): string | null {\n    return Object.keys(this.store)[index] || null;\n  }\n\n  removeItem(key: string): void {\n    delete this.store[key];\n  }\n\n  setItem(key: string, value: string): void {\n    this.store[key] = value;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/MockWindow.ts",
    "content": "import { DesktopAgent } from '@finos/fdc3-standard';\nimport { CustomWorld } from '../world/index.js';\nimport { EventHandler } from './EventHandler.js';\nimport { MockElement } from './MockElement.js';\nimport {\n  AgentEventMessage,\n  AgentResponseMessage,\n  AppRequestMessage,\n  Fdc3UserInterfaceMessage,\n  isFdc3UserInterfaceHello,\n  WebConnectionProtocolMessage,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype STANDARD_MESSAGES =\n  | AppRequestMessage\n  | AgentResponseMessage\n  | AgentEventMessage\n  | WebConnectionProtocolMessage\n  | Fdc3UserInterfaceMessage;\n\nexport class MockWindow extends MockElement {\n  fdc3: DesktopAgent | undefined;\n  cw: CustomWorld;\n  name: string;\n\n  constructor(tag: string, cw: CustomWorld, name: string) {\n    super(tag);\n    this.cw = cw;\n    this.name = name;\n    if (cw.debugLogs) {\n      console.debug(`MockWindow (name: ${this.name} / tag: ${this.tag}): Created`);\n    }\n  }\n\n  eventHandlers: EventHandler[] = [];\n  events: { type: string; data: MessageEvent }[] = [];\n\n  //references used to attribute postMessages to sources\n  parent: MockWindow | null = null;\n  child: MockWindow | null = null;\n  commsIframe: MockWindow | null = null;\n  channelSelectorIframe: MockWindow | null = null;\n  intentResolverIframe: MockWindow | null = null;\n\n  location = {\n    origin: 'https://dummyOrigin.test',\n    href: 'https://dummyOrigin.test/path',\n  };\n\n  addEventListener(type: string, callback: (e: Event) => void): void {\n    this.eventHandlers.push({ type, callback });\n    if (this.cw.debugLogs) {\n      console.log(`MockWindow (name: ${this.name} / tag: ${this.tag}): added event handler: ${type}`);\n    }\n  }\n\n  removeEventListener(type: string, el: EventListener): void {\n    const removeIndex = this.eventHandlers.findIndex(e => e.type === type && e.callback === el);\n    if (removeIndex !== -1) {\n      this.eventHandlers.splice(removeIndex, 1);\n      if (this.cw.debugLogs) {\n        console.debug(`MockWindow (name: ${this.name} / tag: ${this.tag}): removed event handler: ${type}`);\n      }\n    }\n  }\n\n  dispatchEvent(event: Event): void {\n    this.events.push({ type: event.type, data: (event as unknown as MessageEvent).data });\n    this.eventHandlers.forEach(e => {\n      if (e.type === event.type) {\n        e.callback(event);\n      }\n    });\n  }\n\n  postMessage(msg: STANDARD_MESSAGES, targetOrigin: string, transfer: MessagePort[] | undefined): void {\n    //usually only one of these will be set - however parent might be set initially,\n    //  but later overridden by commsIframe wafter a WCP2LoadUrl\n    let source = this.commsIframe ?? this.child ?? this.parent ?? this;\n\n    //adjust source for mock UI iframes - these variables are set in MockDocument.setAttribute\n    if (isFdc3UserInterfaceHello(msg)) {\n      if (msg.payload.implementationDetails == 'mock channel selector') {\n        source = this.channelSelectorIframe!;\n      } else if (msg.payload.implementationDetails == 'mock intent resolver') {\n        source = this.intentResolverIframe!;\n      }\n    }\n\n    const event = {\n      type: 'message',\n      data: msg,\n      origin: targetOrigin,\n      ports: transfer,\n      //TODO: set source for UI iframes, comms iframe, parent DA or child app depending on message type\n      source,\n    } as unknown as MessageEvent;\n\n    if (this.cw.debugLogs) {\n      console.debug(\n        `MockWindow (name: ${this.name} / tag: ${this.tag}): postMessage called with source: ${(event.source as WindowProxy)?.name ?? 'UNKNOWN'}`\n      );\n    }\n    this.dispatchEvent(event);\n  }\n\n  shutdown() {\n    this.eventHandlers = [];\n    this.fdc3 = undefined;\n    if (this.cw.mockFDC3Server) {\n      this.cw.mockFDC3Server.shutdown();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/TestServerContext.ts",
    "content": "import { ServerContext, InstanceID, FDC3Server } from '@finos/fdc3-web-impl';\nimport { CustomWorld } from '../world/index.js';\nimport { OpenError, AppIdentifier, AppIntent } from '@finos/fdc3-standard';\nimport { AppRegistration, State } from '@finos/fdc3-web-impl';\n\ntype ConnectionDetails = AppRegistration & {\n  msg?: object;\n  connectionId: string;\n  externalPort: MessagePort;\n  internalPort: MessagePort;\n  url: string;\n};\n\ntype MessageRecord = {\n  to?: AppIdentifier;\n  uuid?: InstanceID;\n  msg: object;\n};\n\nexport const dummyInstanceDetails = [\n  { appId: 'Test App Id', url: 'https://dummyOrigin.test/path' },\n  { appId: 'Test App Id 2', url: 'https://dummyOrigin.test/alternativePath' },\n];\n\nexport class TestServerContext implements ServerContext<ConnectionDetails> {\n  public postedMessages: MessageRecord[] = [];\n  public readonly cw: CustomWorld;\n  private instances: ConnectionDetails[] = [];\n  private server: FDC3Server | null = null;\n\n  private nextInstanceId: number = 0;\n  private nextUUID: number = 0;\n\n  constructor(cw: CustomWorld) {\n    this.cw = cw;\n  }\n\n  setFDC3Server(server: FDC3Server): void {\n    this.server = server;\n  }\n\n  async narrowIntents(_raiser: AppIdentifier, appIntents: AppIntent[] /*, _context: Context*/): Promise<AppIntent[]> {\n    return appIntents;\n  }\n\n  getInstanceDetails(uuid: string) {\n    return this.instances.find(ca => ca.instanceId === uuid);\n  }\n\n  setInstanceDetails(uuid: InstanceID, appId: ConnectionDetails) {\n    this.instances = this.instances.filter(ca => ca.connectionId !== uuid);\n    this.instances.push({\n      ...appId,\n      connectionId: uuid,\n    });\n  }\n\n  getMatchingInstance(url: string): ConnectionDetails | undefined {\n    const details = this.instances.find(ca => ca.url === url);\n    if (!details) {\n      const knownInstances = this.instances.map(inst => {\n        return { appId: inst.appId, url: inst.url };\n      });\n      console.error(\n        'No connection instance found - will return a mismatched instance, url: ',\n        url,\n        '\\nknown instances: ',\n        knownInstances\n      );\n      return this.instances[0];\n    }\n    return details;\n  }\n\n  async shutdown(): Promise<void> {\n    await Promise.all(this.instances.map(i => i.internalPort.close()));\n    await Promise.all(this.instances.map(i => i.externalPort.close()));\n  }\n\n  /** Used to mock connections to the server from apps. Must be called before the app attempts to connect for that connection to succeed. */\n  async open(appId: string): Promise<InstanceID> {\n    const url = dummyInstanceDetails.find(value => value.appId === appId)?.url;\n    if (!url) {\n      console.error('TestServerContext Tried to open an unknown appId');\n      throw new Error(OpenError.AppNotFound);\n    } else {\n      const ni = this.nextInstanceId++;\n      if (appId.includes('missing')) {\n        throw new Error(OpenError.AppNotFound);\n      } else {\n        const mc = new MessageChannel();\n        const internalPort = mc.port1;\n        const externalPort = mc.port2;\n\n        internalPort.start();\n\n        const connectionDetails = {\n          appId,\n          instanceId: 'uuid-' + ni,\n          connected: false,\n          connectionId: 'uuid-' + ni,\n          externalPort,\n          internalPort,\n          url: url,\n          state: State.Pending,\n        };\n\n        this.instances.push(connectionDetails);\n        internalPort.onmessage = msg => {\n          this.cw.mockFDC3Server?.receive(msg.data, connectionDetails.instanceId);\n        };\n\n        return connectionDetails.connectionId;\n      }\n    }\n  }\n\n  async getConnectedApps(): Promise<AppRegistration[]> {\n    return (await this.getAllApps()).filter(ca => ca.state == State.Connected);\n  }\n\n  async isAppConnected(app: InstanceID): Promise<boolean> {\n    const found = this.instances.find(a => a.instanceId == app && a.state == State.Connected);\n    return found != null;\n  }\n\n  async setAppState(app: InstanceID, newState: State): Promise<void> {\n    const found = this.instances.find(a => a.instanceId == app);\n    if (found) {\n      const currentState = found.state;\n      if (currentState !== State.Terminated && newState === State.Terminated) {\n        this.server?.cleanup(app);\n      }\n      found.state = newState;\n    }\n  }\n\n  async getAllApps(): Promise<AppRegistration[]> {\n    return this.instances.map(x => {\n      return {\n        appId: x.appId,\n        instanceId: x.instanceId,\n        state: x.state,\n      };\n    });\n  }\n\n  provider(): string {\n    return 'cucumber-provider';\n  }\n  providerVersion(): string {\n    return '1.2.3.TEST';\n  }\n  fdc3Version(): string {\n    return '2.0';\n  }\n\n  createUUID(): string {\n    return 'uuid' + this.nextUUID++;\n  }\n\n  /**\n   * USED FOR TESTING\n   */\n  getInstanceUUID(appId: AppIdentifier): InstanceID | undefined {\n    return this.instances.find(\n      ca => ca.appId == appId.appId && ca.instanceId == appId.instanceId && ca.state == State.Connected\n    )?.instanceId;\n  }\n\n  /**\n   * USED FOR TESTING\n   */\n  getFirstInstance() {\n    return this.instances[0];\n  }\n\n  post(msg: object, to: InstanceID): Promise<void> {\n    const details = this.getInstanceDetails(to);\n    details?.internalPort.postMessage(msg);\n    return Promise.resolve();\n  }\n\n  log(message: string): void {\n    this.cw.log(message);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/AddEventListener.ts",
    "content": "import { AutomaticResponse } from './AutomaticResponses';\nimport { AddEventListenerRequest, AddEventListenerResponse } from '@finos/fdc3-schema/generated/api/BrowserTypes';\nimport { createUUID } from '../../../src/util/Uuid';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { TestServerContext } from '../TestServerContext';\n\nexport class AddEventListener implements AutomaticResponse {\n  private count: number = 0;\n\n  filter(t: string) {\n    return t == 'addEventListenerRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const request = input as AddEventListenerRequest;\n    const response = this.createResponse(request);\n    setTimeout(() => {\n      m.post(response, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: AddEventListenerRequest): AddEventListenerResponse {\n    return {\n      meta: {\n        requestUuid: i.meta.requestUuid,\n        responseUuid: createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'addEventListenerResponse',\n      payload: {\n        listenerUUID: 'listener-' + this.count++,\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/AutomaticResponses.ts",
    "content": "import { InstanceID } from '@finos/fdc3-web-impl';\nimport { TestServerContext } from '../TestServerContext.js';\n\nexport interface AutomaticResponse {\n  filter: (t: string) => boolean;\n  action: (input: object, m: TestServerContext, from: InstanceID) => Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/Broadcast.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport { BroadcastRequest, BroadcastResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { createUUID } from '../../../src/util/Uuid.js';\n\nexport class Broadcast implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'broadcastRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const broadcastRequest = input as BroadcastRequest;\n    const request = this.createBroadcastResponseMessage(broadcastRequest);\n    setTimeout(() => {\n      m.post(request, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createBroadcastResponseMessage(m: BroadcastRequest): BroadcastResponse {\n    const response: BroadcastResponse = {\n      meta: {\n        requestUuid: m.meta.requestUuid,\n        responseUuid: createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'broadcastResponse',\n      payload: {},\n    };\n    return response;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/CurrentChannel.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport {\n  GetCurrentChannelRequest,\n  GetCurrentChannelResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class CurrentChannel implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getCurrentChannelRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const out = this.createResponse(input as GetCurrentChannelRequest, m);\n    setTimeout(() => {\n      m.post(out, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: GetCurrentChannelRequest, m: TestServerContext): GetCurrentChannelResponse {\n    const response: GetCurrentChannelResponse = {\n      meta: {\n        ...i.meta,\n        responseUuid: m.createUUID(),\n      },\n      type: 'getCurrentChannelResponse',\n      payload: {\n        channel: {\n          id: 'one',\n          type: 'user',\n        },\n      },\n    };\n    return response;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/FindIntent.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport { FindIntentRequest, FindIntentResponse } from '@finos/fdc3-schema/generated/api/BrowserTypes';\nimport { createUUID } from '../../../src/util/Uuid.js';\n\nexport class FindIntent implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'findIntentRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const intentRequest = input as FindIntentRequest;\n    const request = this.createFindIntentResponseMessage(intentRequest);\n    setTimeout(() => {\n      m.post(request, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createFindIntentResponseMessage(m: FindIntentRequest): FindIntentResponse {\n    const response: FindIntentResponse = {\n      meta: {\n        requestUuid: m.meta.requestUuid,\n        responseUuid: createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'findIntentResponse',\n      payload: {\n        appIntent: {\n          intent: { name: m.payload.intent },\n          apps: [\n            {\n              appId: 'test-app-1',\n              name: 'Test App 1',\n            },\n            {\n              appId: 'test-app-2',\n              name: 'Test App 2',\n            },\n          ],\n        },\n      },\n    };\n    return response;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/GetInfo.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport { GetInfoRequest, GetInfoResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class GetInfo implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getInfoRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const out = this.createResponse(input as GetInfoRequest, m);\n    setTimeout(() => {\n      m.post(out, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: GetInfoRequest, m: TestServerContext): GetInfoResponse {\n    const response: GetInfoResponse = {\n      meta: {\n        ...i.meta,\n        responseUuid: m.createUUID(),\n      },\n      type: 'getInfoResponse',\n      payload: {\n        implementationMetadata: {\n          appMetadata: i.meta.source!, //{appId: \"cucumber-app\", instanceId: \"cucumber-instance\"},\n          provider: 'cucumber-provider',\n          providerVersion: 'test',\n          fdc3Version: '2.0',\n          optionalFeatures: {\n            DesktopAgentBridging: false,\n            OriginatingAppMetadata: false,\n            UserChannelMembershipAPIs: false,\n          },\n        },\n      },\n    };\n    return response;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/Handshake.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport {\n  WebConnectionProtocol4ValidateAppIdentity,\n  WebConnectionProtocol5ValidateAppIdentityFailedResponse,\n  WebConnectionProtocol5ValidateAppIdentitySuccessResponse,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport const BAD_INSTANCE_ID = 'BAD_INSTANCE';\nexport const EXPECTED_IDENTITY_URL = 'https://dummyOrigin.test/path';\nexport const ALTERNATIVE_IDENTITY_URL = 'https://dummyOrigin.test/alternativePath';\n\nexport class Handshake implements AutomaticResponse {\n  timeOut: boolean;\n\n  constructor(timeOut: boolean = false) {\n    this.timeOut = timeOut;\n  }\n\n  filter(t: string) {\n    return t == 'WCP4ValidateAppIdentity';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    if (!this.timeOut) {\n      const out = this.createResponse(input as WebConnectionProtocol4ValidateAppIdentity);\n      setTimeout(() => {\n        m.post(out, from);\n      }, 100);\n    } else {\n      console.debug('Forcing timeout of identity validation');\n    }\n    return Promise.resolve();\n  }\n\n  private createResponse(\n    i: WebConnectionProtocol4ValidateAppIdentity\n  ):\n    | WebConnectionProtocol5ValidateAppIdentitySuccessResponse\n    | WebConnectionProtocol5ValidateAppIdentityFailedResponse {\n    const identityURL = i.payload.identityUrl;\n    if (i.payload.instanceUuid == BAD_INSTANCE_ID) {\n      const msg: WebConnectionProtocol5ValidateAppIdentityFailedResponse = {\n        meta: {\n          connectionAttemptUuid: i.meta.connectionAttemptUuid,\n          timestamp: new Date(),\n        },\n        type: 'WCP5ValidateAppIdentityFailedResponse',\n        payload: {\n          message: 'Invalid instance',\n        },\n      };\n      return msg;\n    } else if (identityURL == EXPECTED_IDENTITY_URL || identityURL == ALTERNATIVE_IDENTITY_URL) {\n      let appId = 'cucumber-app';\n      let instanceId = 'cucumber-instance';\n      let instanceUuid = 'some-instance-uuid';\n\n      if (identityURL == ALTERNATIVE_IDENTITY_URL) {\n        appId = 'cucumber-alternative-app';\n        instanceId = 'cucumber-alternative-instance';\n        instanceUuid = 'some-alternative-instance-uuid';\n      }\n\n      const msg: WebConnectionProtocol5ValidateAppIdentitySuccessResponse = {\n        meta: {\n          connectionAttemptUuid: i.meta.connectionAttemptUuid,\n          timestamp: new Date(),\n        },\n        type: 'WCP5ValidateAppIdentityResponse',\n        payload: {\n          implementationMetadata: {\n            appMetadata: {\n              appId: appId,\n              instanceId: instanceId,\n            },\n            fdc3Version: '2.0',\n            optionalFeatures: {\n              DesktopAgentBridging: false,\n              OriginatingAppMetadata: true,\n              UserChannelMembershipAPIs: true,\n            },\n            provider: 'cucumber-provider',\n            providerVersion: 'test',\n          },\n          appId: appId,\n          instanceId: instanceId,\n          instanceUuid: instanceUuid,\n        },\n      };\n      return msg;\n    } else {\n      const msg: WebConnectionProtocol5ValidateAppIdentityFailedResponse = {\n        meta: {\n          connectionAttemptUuid: i.meta.connectionAttemptUuid,\n          timestamp: new Date(),\n        },\n        type: 'WCP5ValidateAppIdentityFailedResponse',\n        payload: {\n          message: 'Unknown identity URL',\n        },\n      };\n      return msg;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/RaiseIntent.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport { RaiseIntentRequest, RaiseIntentResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport class RaiseIntent implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'raiseIntentRequest';\n  }\n\n  createRaiseIntentAgentResponseMessage(intentRequest: RaiseIntentRequest, m: TestServerContext): RaiseIntentResponse {\n    const out: RaiseIntentResponse = {\n      meta: {\n        ...intentRequest.meta,\n        responseUuid: m.createUUID(),\n      },\n      payload: {\n        intentResolution: {\n          intent: intentRequest.payload.intent,\n          source: intentRequest.payload.app!,\n        },\n      },\n      type: 'raiseIntentResponse',\n    };\n\n    return out;\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const intentRequest = input as RaiseIntentRequest;\n    // this sends out the intent resolution\n    const out1 = this.createRaiseIntentAgentResponseMessage(intentRequest, m);\n    setTimeout(() => {\n      m.post(out1, from);\n    }, 100);\n    return Promise.resolve();\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/UnsubscribeEventListener.ts",
    "content": "import { AutomaticResponse } from './AutomaticResponses';\nimport {\n  EventListenerUnsubscribeRequest,\n  EventListenerUnsubscribeResponse,\n} from '@finos/fdc3-schema/generated/api/BrowserTypes';\nimport { createUUID } from '../../../src/util/Uuid';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { TestServerContext } from '../TestServerContext';\n\nexport class UnsubscribeEventListener implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'eventListenerUnsubscribeRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const request = input as EventListenerUnsubscribeRequest;\n    const response = this.createResponse(request);\n    setTimeout(() => {\n      m.post(response, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: EventListenerUnsubscribeRequest): EventListenerUnsubscribeResponse {\n    return {\n      meta: {\n        requestUuid: i.meta.requestUuid,\n        responseUuid: createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'eventListenerUnsubscribeResponse',\n      payload: {},\n    };\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/support/responses/UserChannels.ts",
    "content": "import { TestServerContext } from '../TestServerContext.js';\nimport { InstanceID } from '@finos/fdc3-web-impl';\nimport { AutomaticResponse } from './AutomaticResponses.js';\nimport { GetUserChannelsRequest, GetUserChannelsResponse } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport const USER_CHANNELS = [\n  {\n    id: 'one',\n    type: 'user',\n  },\n  {\n    id: 'two',\n    type: 'user',\n  },\n  {\n    id: 'three',\n    type: 'user',\n  },\n] as any;\n\nexport class UserChannels implements AutomaticResponse {\n  filter(t: string) {\n    return t == 'getUserChannelsRequest';\n  }\n\n  action(input: object, m: TestServerContext, from: InstanceID) {\n    const out = this.createResponse(input as GetUserChannelsRequest, m);\n\n    setTimeout(() => {\n      m.post(out, from);\n    }, 100);\n    return Promise.resolve();\n  }\n\n  private createResponse(i: GetUserChannelsRequest, m: TestServerContext): GetUserChannelsResponse {\n    const response: GetUserChannelsResponse = {\n      meta: {\n        ...i.meta,\n        responseUuid: m.createUUID(),\n      },\n      type: 'getUserChannelsResponse',\n      payload: {\n        userChannels: USER_CHANNELS,\n      },\n    };\n    return response;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/test/world/index.ts",
    "content": "import { QuickPickleWorld, QuickPickleWorldInterface } from 'quickpickle';\nimport { MockFDC3Server } from '../support/MockFDC3Server.js';\nimport { TestServerContext } from '../support/TestServerContext.js';\n\nexport interface CustomWorldInterface extends QuickPickleWorldInterface {\n  props: Record<string, any>;\n  mockFDC3Server: MockFDC3Server | null;\n  mockContext: TestServerContext;\n  debugLogs: boolean;\n  log: (message: string) => void;\n}\n\nexport class CustomWorld extends QuickPickleWorld implements CustomWorldInterface {\n  props: Record<string, any> = {};\n  mockFDC3Server: MockFDC3Server | null = null;\n  mockContext: TestServerContext = new TestServerContext(this);\n  debugLogs: boolean = false;\n\n  log(message: string): void {\n    console.log(message);\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-get-agent/tsconfig.json",
    "content": "{\n    \"extends\": \"../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"module\": \"NodeNext\",\n        \"moduleResolution\": \"NodeNext\",\n        \"rootDirs\": [\n            \"src\",\n            \"test\"\n        ],\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src\"\n    ],\n    \"references\": [\n        {\n            \"path\": \"../fdc3-agent-proxy\"\n        },\n        {\n            \"path\": \"../fdc3-standard\"\n        },\n        {\n            \"path\": \"../testing\"\n        },\n        {\n            \"path\": \"../fdc3-schema\"\n        },\n        {\n            \"path\": \"../fdc3-context\"\n        },\n        {\n            \"path\": \"../../toolbox/fdc3-for-web/fdc3-web-impl\"\n        }\n    ]\n}"
  },
  {
    "path": "packages/fdc3-get-agent/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\nimport { quickpickle } from 'quickpickle';\n\nexport default defineConfig({\n  plugins: [\n    quickpickle({\n      stepTimeout: 15000,\n    }),\n  ],\n  test: {\n    include: ['test/features/**/*.feature'],\n    setupFiles: ['test/steps.ts'],\n    testTimeout: 30000,\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n    coverage: {\n      enabled: true,\n      provider: 'v8',\n      reporter: ['text', 'lcov', 'json'],\n      reportsDirectory: './coverage',\n      include: ['src/**/*.ts'],\n      exclude: ['src/**/*.d.ts', 'src/**/*.test.ts', 'src/**/*.spec.ts'],\n    },\n  },\n});\n"
  },
  {
    "path": "packages/fdc3-schema/README.md",
    "content": "# FDC3 Bridging and FDC3 for Web Message Schemas\n\nThis package holds both the schema files and TypeScript types generated from them used that define JSON message formats used in the FDC3 Desktop Agent Bridging Protocol and both the Web Connection Protocol (WCP) and Desktop Agent COmmunication Protocol (DACP) that allow FDC3 to be used in a Web Browser.\n\nThe Schema files distributed in this package are also deployed to the Web at the locations given in their `$id` fields and can be found in the relevant sections of the FDC3 documentation ([Bridging](https://fdc3.finos.org/docs/next/agent-bridging/spec), [Web Connection protocol](https://fdc3.finos.org/docs/next/api/specs/webConnectionProtocol), [Desktop Agent Communication Protocol](https://fdc3.finos.org/docs/next/api/specs/desktopAgentCommunicationProtocol)).\n\nTypeScript types are generated from each schema and can be imported from the package as a set:\n\n```ts\nimport { BrowserTypes, BridgingTypes } from '@finos/fdc3-schema';\n```\n\nor individually:\n\n```ts\nimport {\n  GetUserChannelsRequest,\n  JoinUserChannelRequest,\n  LeaveCurrentChannelRequest\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n```\n\nFurther details:\n\n - https://github.com/finos/FDC3\n - [FDC3 Specification](https://fdc3.finos.org/)\n - Main FDC3 module: https://www.npmjs.com/package/@finos/fdc3\n\n## Message types generation notes\n\nThis folder contains Typescript interfaces, in BridgingTypes.ts generated from the context JSONSchema (https://json-schema.org/) files via quicktype (https://quicktype.io/). Source files may also be generated for us in other languages supported by Quicktype.\n\nPlease note that these definitions are provided to help developers working in TypeScript to produce valid bridging or FDC3 for Web messages objects - but should not be considered the 'source of truth' for message definitions (instead look to the schemas and documentation).\n\nIt is not always possible to perfectly replicate a type/interface defined in JSONSchema via TypeScript. Hence, if there is any disagreement between the definitions, the JSON Schema should be assumed to be correct, rather than the TypeScript. For example, JSON Schema may define optional fields on an object + a restriction on the type of additional properties (via `\"additionalProperties\": { \"type\": \"string\"}`), which will result in an index signature `[property: string]: string;` in generated TypeScript. That signature is incompatible with optional properties (including string properties) as they have type `string | undefined`. A similar problem may occur in JSON Schema if the schema is used to create a subtype via composition as `additionalProperties` is not aware of the subschema's definitions. Both issues can be worked around by using `unevaluatedProperties` in the schema, which will defer to the declared type of the optional property in the subschema, but is also currently ignored by Quicktype - resulting in a type that will compile but doesn't restrict the type of optional property values as defined in the schema.\n\nFurther, Quicktype doesn't always perfectly replicate polymorphic fields specified with `oneOf` or `allOf` in JSON Schema as it will usually merge the different objects into a single type (where fields not in one of the constituent schemas become optional) rather than creating a union type. In such situations, the type produced is usable (has all the necessary fields) but may allow the construction of invalid instances which are missing required properties or include properties from the multiple schemas combined, which are not possible/valid according to JSON Schema.\n\nHence, the Types provided here can be used to provide valid message objects and to read/write their JSON encodings, but may not detect or prevent a limited set of invalid objects that would be identified by JSON Schema.\n\nFinally, Quicktype will generate types or interfaces representing subunits of the schema, which are then referenced in the primary interface definition. These often do not have unique names (generated from title fields in the schemas). If a name conflict is encountered, Quicktype will generate a random name for such an interface, to use to reference it, and as it is randomly generated it may appear oddly named (e.g. `PurpleId`, `FluffyMarket`, `TentacledIdentifier` etc.). Please ignore such names as these types/interfaces will not normally be used outside of the composition of the primary type, e.g.:\n\n```TypeScript\nexport interface Instrument {\n  id: StickyId;\n  market?: FluffyMarket;\n  type: string;\n  name?: string;\n  [property: string]: any;\n}\n\nexport interface StickyId {\n  BBG?: string;\n  CUSIP?: string;\n  FDS_ID?: string;\n  FIGI?: string;\n  ISIN?: string;\n  PERMID?: string;\n  RIC?: string;\n  SEDOL?: string;\n  ticker?: string;\n  [property: string]: any;\n}\n\nexport interface FluffyMarket {\n  BBG?: string;\n  COUNTRY_ISOALPHA2?: string;\n  MIC?: string;\n  name?: string;\n  [property: string]: any;\n}\n```\n\nand should not be considered a planned part of the type structure (which should not be replicated in any derivative work). When applied, the naming of these sub-units is not used, rather they are replaced with their contents. Generating better names for these sub-units is usually a case of adding or adjusting `title` fields on the relevant elements of the schema documents.\n\nFinally, please note that the latest version of Quicktype (at the time of writing `23.0.49`) has a number of bugs that must be worked around:\n\n- Using a directory or .schema.json files as a source will cause the input type argument `-s schema` to be ignored, causing the files to be interpreted as JSON rather than JSON Schema.\n  - A utility is provided in this repository (_../../quicktypeUtil.js_) to work around this bug by listing directories and constructing a call to quicktype where each file is provided as an individual source.\n- Setting the `--nice-property-names` TypeScript output option will crash the generator and can't be used.\n- The --debug setting must be the first argument passed or it will be ignored."
  },
  {
    "path": "packages/fdc3-schema/code-generation/generate-type-predicates.ts",
    "content": "import {\n  InterfaceDeclaration,\n  KindToNodeMappings,\n  MethodDeclaration,\n  Project,\n  SyntaxKind,\n  TypeAliasDeclaration,\n} from 'ts-morph';\nimport messageAwait from 'message-await';\n\n// Normalise export of message-await so it works with tsx and ts-node\nconst print: typeof messageAwait = (messageAwait as any).default ?? messageAwait;\n\n// open a new project with just BrowserTypes as the only source file\nconst project = new Project();\nconst sourceFile = project.addSourceFileAtPath('./generated/api/BrowserTypes.ts');\n\nconst APP_REQUEST_MESSAGE = 'AppRequestMessage';\nconst AGENT_RESPONSE_MESSAGE = 'AgentResponseMessage';\nconst AGENT_EVENT_MESSAGE = 'AgentEventMessage';\n\n/**\n * We generate the union types and remove the existing interfaces first so that we are not left with a generated type predicate for the removed base interface\n */\nwriteMessageUnionTypes();\nwriteTypePredicates();\n\nsourceFile.formatText();\nproject.saveSync();\n\n/**\n * Replaces the existing interfaces AppRequestMessage, AgentResponseMessage and AgentEventMessage with unions of INterfaces instead of a base type\n */\nfunction writeMessageUnionTypes() {\n  const typeAliases = sourceFile.getChildrenOfKind(SyntaxKind.TypeAliasDeclaration);\n\n  writeMessageUnion(APP_REQUEST_MESSAGE, 'RequestMessageType', typeAliases);\n  writeMessageUnion(AGENT_RESPONSE_MESSAGE, 'ResponseMessageType', typeAliases);\n  writeMessageUnion(AGENT_EVENT_MESSAGE, 'EventMessageType', typeAliases);\n}\n\nfunction writeMessageUnion(unionName: string, typeUnionName: string, typeAliases: TypeAliasDeclaration[]) {\n  let awaitMessage = print(`Writing ${unionName} (finding types)`, { spinner: true });\n\n  // get the types listed in the types union type\n  // i.e. look for: export type RequestMessageType = \"addContextListenerRequest\" | \"whatever\"\n  const requestMessageTypeUnion = findUnionType(typeAliases, typeUnionName);\n  if (requestMessageTypeUnion != null) {\n    //remove existing type alias\n    findExisting(unionName, SyntaxKind.TypeAliasDeclaration).forEach(node => node.remove());\n\n    awaitMessage.updateMessage(`Writing ${unionName} (writing union)`, true);\n\n    // Write a union type of all interfaces that have a type that extends RequestMessageType\n    // i.e. export type AppRequestMessage = AddContextListenerRequest | AddEventListenerRequest | AddIntentListenerRequest;\n    writeUnionType(unionName, requestMessageTypeUnion);\n  }\n\n  awaitMessage.complete(true, `Writing ${unionName}`);\n}\n\n/**\n * Writes type predicates for all interfaces found that have a matching convert function\n */\nfunction writeTypePredicates() {\n  let awaitMessage = print(`Writing Type Predicates (finding convert functions)`, { spinner: true });\n\n  // get a list of all conversion functions in the Convert class that return a string\n  const convert = sourceFile.getClass('Convert');\n  const convertFunctions = (convert?.getChildrenOfKind(SyntaxKind.MethodDeclaration) ?? []).filter(\n    func => func.getReturnType().getText() === 'string'\n  );\n\n  awaitMessage.updateMessage(`Writing Type Predicates (finding message interfaces)`, true);\n\n  //get a list of all interfaces in the file\n  let messageInterfaces = sourceFile.getChildrenOfKind(SyntaxKind.InterfaceDeclaration);\n\n  // generate a list of Interfaces that have an associated conversion function\n  const matchedInterfaces = convertFunctions\n    .map(func => {\n      const valueParameter = func.getParameter('value');\n\n      const matchingInterface = messageInterfaces.find(interfaceNode => {\n        /// Find an interface who's name matches the type passed into the value parameter of the convert function\n        return valueParameter?.getType().getText(valueParameter) === interfaceNode.getName();\n      });\n\n      if (matchingInterface != null) {\n        return { func, matchingInterface };\n      }\n\n      return undefined;\n    })\n    .filter(isDefined);\n\n  const allFunctionDeclarations = sourceFile.getChildrenOfKind(SyntaxKind.FunctionDeclaration);\n\n  // write a type predicate for each matched interface\n  matchedInterfaces.forEach((matched, index) => {\n    awaitMessage.updateMessage(`Writing Type Predicates (${index}/${matchedInterfaces.length})`, true);\n\n    writeFastPredicate(matched.matchingInterface, allFunctionDeclarations);\n    writeValidPredicate(matched.matchingInterface, matched.func, allFunctionDeclarations);\n    writeTypeConstant(matched.matchingInterface);\n  });\n\n  awaitMessage.complete(true, `Writing Type Predicates`);\n}\n\n/**\n * Looks for a string union type in the form:\n * export type NAME = \"stringOne\" | \"stringTwo\" | \"stringThree\";\n * and returns the string values\n * if the union type is not found returns undefined\n * @param name\n * @returns\n */\nfunction findUnionType(typeAliases: TypeAliasDeclaration[], name: string): string[] | undefined {\n  const typeAlias = typeAliases.find(alias => {\n    const identifiers = alias.getChildrenOfKind(SyntaxKind.Identifier);\n\n    return identifiers[0].getText() === name;\n  });\n\n  return typeAlias\n    ?.getChildrenOfKind(SyntaxKind.UnionType)?.[0]\n    .getDescendantsOfKind(SyntaxKind.StringLiteral)\n    .map(literal => literal.getLiteralText());\n}\n\n/**\n * Finds an existing declaration with the given type and name\n * @param name\n * @param kind\n * @returns\n */\nfunction findExisting<T extends SyntaxKind>(name: string, kind: T, allDeclarationsOfType?: KindToNodeMappings[T][]) {\n  allDeclarationsOfType = allDeclarationsOfType ?? sourceFile.getChildrenOfKind(kind);\n\n  return sourceFile.getChildrenOfKind(kind).filter(child => {\n    const identifier = child.getDescendantsOfKind(SyntaxKind.Identifier)[0];\n\n    return identifier?.getText() === name;\n  });\n}\n\n/**\n * Writes a type predicate for the given interface using the Convert method declaration\n * @param matchingInterface\n * @param func\n */\nfunction writeValidPredicate(\n  matchingInterface: InterfaceDeclaration,\n  func: MethodDeclaration,\n  allFunctionDeclarations: KindToNodeMappings[SyntaxKind.FunctionDeclaration][]\n): void {\n  const predicateName = `isValid${matchingInterface.getName()}`;\n\n  // remove existing instances\n  findExisting(predicateName, SyntaxKind.FunctionDeclaration, allFunctionDeclarations).forEach(node => node.remove());\n\n  sourceFile.addStatements(`\n/**\n * Returns true if value is a valid ${matchingInterface.getName()}. This checks the type against the json schema for the message and will be slower\n */ \nexport function ${predicateName}(value: any): value is ${matchingInterface.getName()} {\n    try{\n        Convert.${func.getName()}(value);\n        return true;\n    } catch(_e: any){\n        return false; \n    }\n}`);\n}\n\n/**\n * Writes a type predicate for the given interface checking just the value of the type property\n * @param matchingInterface\n * @param func\n */\nfunction writeFastPredicate(\n  matchingInterface: InterfaceDeclaration,\n  allFunctionDeclarations: KindToNodeMappings[SyntaxKind.FunctionDeclaration][]\n): void {\n  const predicateName = `is${matchingInterface.getName()}`;\n\n  // remove existing instances\n  findExisting(predicateName, SyntaxKind.FunctionDeclaration, allFunctionDeclarations).forEach(node => node.remove());\n\n  const typePropertyValue = extractTypePropertyValue(matchingInterface);\n\n  if (typePropertyValue == null) {\n    return;\n  }\n\n  sourceFile.addStatements(`\n/**\n * Returns true if the value has a type property with value '${typePropertyValue}'. This is a fast check that does not check the format of the message\n */ \nexport function ${predicateName}(value: any): value is ${matchingInterface.getName()} {\n    return value != null && value.type === '${typePropertyValue}';\n}`);\n}\n\nfunction writeTypeConstant(matchingInterface: InterfaceDeclaration): void {\n  const constantName = `${matchingInterface\n    .getName()\n    .replaceAll(/([A-Z])/g, '_$1')\n    .toUpperCase()\n    .substring(1)}_TYPE`;\n\n  //remove existing\n  findExisting(constantName, SyntaxKind.VariableStatement).forEach(node => node.remove());\n\n  sourceFile.addStatements(`\n        export const ${matchingInterface\n          .getName()\n          .replaceAll(/([A-Z])/g, '_$1')\n          .toUpperCase()\n          .substring(1)}_TYPE = \"${matchingInterface.getName()}\";`);\n}\n\n/**\n * Writes a union type of all the interfaces that have a type property that extends the type values passed in.\n * For example:\n * export type RequestMessage = AddContextListenerRequest | AddEventListenerRequest ...\n * @param unionName\n * @param interfaces\n * @param typeValues\n */\nfunction writeUnionType(unionName: string, typeValues: string[]): void {\n  // generate interfaces list again as we may have just removed some\n  const unionInterfaces = sourceFile.getChildrenOfKind(SyntaxKind.InterfaceDeclaration);\n\n  // look for interfaces that have a type property that extends one of the values in typeValues\n  const matchingInterfaces = unionInterfaces.filter(currentInterface => {\n    const typePropertyValue = extractTypePropertyValue(currentInterface);\n\n    return typeValues.some(typeValue => typeValue === typePropertyValue);\n  });\n\n  //remove existing Type\n  findExisting(unionName, SyntaxKind.InterfaceDeclaration).forEach(node => node.remove());\n\n  sourceFile.addStatements(`\n    export type ${unionName} = ${matchingInterfaces.map(match => match.getName()).join(' | ')}; `);\n}\n\n/**\n * Extract the type string constant from an interface such as\n * interface ExampleMessage{\n *     type: \"stringConstant\";\n * }\n * @param parentInterface\n * @returns\n */\nfunction extractTypePropertyValue(parentInterface: InterfaceDeclaration): string | undefined {\n  const typeProperty = parentInterface.getChildrenOfKind(SyntaxKind.PropertySignature).filter(propertySignature => {\n    return (\n      propertySignature.getChildrenOfKind(SyntaxKind.Identifier).find(identifier => identifier.getText() === 'type') !=\n      null\n    );\n  })[0];\n\n  return typeProperty?.getDescendantsOfKind(SyntaxKind.StringLiteral).map(literal => literal.getLiteralText())[0];\n}\n\n/**\n * Type predicate to test that value is defined\n */\nfunction isDefined<T>(value: T | null | undefined): value is T {\n  return value != null;\n}\n"
  },
  {
    "path": "packages/fdc3-schema/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n  {\n    rules: {\n      'no-empty': 'off',\n      'no-prototype-builtins': 'off',\n      '@typescript-eslint/adjacent-overload-signatures': 'warn',\n      '@typescript-eslint/no-empty-function': 'warn',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-empty-object-type': [\n        'error',\n        {\n          allowInterfaces: 'always',\n        },\n      ],\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          argsIgnorePattern: '^_',\n          caughtErrorsIgnorePattern: '^_',\n        },\n      ],\n    },\n  },\n];\n"
  },
  {
    "path": "packages/fdc3-schema/generated/api/BrowserTypes.ts",
    "content": "// To parse this data:\n//\n//   import { Convert, WebConnectionProtocol1Hello, WebConnectionProtocol2LoadURL, WebConnectionProtocol3Handshake, WebConnectionProtocol4ValidateAppIdentity, WebConnectionProtocol5ValidateAppIdentityFailedResponse, WebConnectionProtocol5ValidateAppIdentitySuccessResponse, WebConnectionProtocol6Goodbye, WebConnectionProtocolMessage, AddContextListenerRequest, AddContextListenerResponse, AddEventListenerRequest, AddEventListenerResponse, AddIntentListenerRequest, AddIntentListenerResponse, AgentEventMessage, AgentResponseMessage, AppRequestMessage, BroadcastEvent, BroadcastRequest, BroadcastResponse, ChannelChangedEvent, ClearContextRequest, ClearContextResponse, ContextClearedEvent, ContextListenerUnsubscribeRequest, ContextListenerUnsubscribeResponse, CreatePrivateChannelRequest, CreatePrivateChannelResponse, EventListenerUnsubscribeRequest, EventListenerUnsubscribeResponse, Fdc3UserInterfaceChannelSelected, Fdc3UserInterfaceChannels, Fdc3UserInterfaceDrag, Fdc3UserInterfaceHandshake, Fdc3UserInterfaceHello, Fdc3UserInterfaceMessage, Fdc3UserInterfaceResolve, Fdc3UserInterfaceResolveAction, Fdc3UserInterfaceRestyle, FindInstancesRequest, FindInstancesResponse, FindIntentRequest, FindIntentResponse, FindIntentsByContextRequest, FindIntentsByContextResponse, GetAppMetadataRequest, GetAppMetadataResponse, GetCurrentChannelRequest, GetCurrentChannelResponse, GetCurrentContextRequest, GetCurrentContextResponse, GetInfoRequest, GetInfoResponse, GetOrCreateChannelRequest, GetOrCreateChannelResponse, GetUserChannelsRequest, GetUserChannelsResponse, HeartbeatAcknowledgementRequest, HeartbeatEvent, IntentEvent, IntentListenerUnsubscribeRequest, IntentListenerUnsubscribeResponse, IntentResultRequest, IntentResultResponse, JoinUserChannelRequest, JoinUserChannelResponse, LeaveCurrentChannelRequest, LeaveCurrentChannelResponse, OpenRequest, OpenResponse, PrivateChannelAddEventListenerRequest, PrivateChannelAddEventListenerResponse, PrivateChannelDisconnectRequest, PrivateChannelDisconnectResponse, PrivateChannelOnAddContextListenerEvent, PrivateChannelOnDisconnectEvent, PrivateChannelOnUnsubscribeEvent, PrivateChannelUnsubscribeEventListenerRequest, PrivateChannelUnsubscribeEventListenerResponse, RaiseIntentForContextRequest, RaiseIntentForContextResponse, RaiseIntentRequest, RaiseIntentResponse, RaiseIntentResultResponse } from \"./file\";\n//\n//   const webConnectionProtocol1Hello = Convert.toWebConnectionProtocol1Hello(json);\n//   const webConnectionProtocol2LoadURL = Convert.toWebConnectionProtocol2LoadURL(json);\n//   const webConnectionProtocol3Handshake = Convert.toWebConnectionProtocol3Handshake(json);\n//   const webConnectionProtocol4ValidateAppIdentity = Convert.toWebConnectionProtocol4ValidateAppIdentity(json);\n//   const webConnectionProtocol5ValidateAppIdentityFailedResponse = Convert.toWebConnectionProtocol5ValidateAppIdentityFailedResponse(json);\n//   const webConnectionProtocol5ValidateAppIdentitySuccessResponse = Convert.toWebConnectionProtocol5ValidateAppIdentitySuccessResponse(json);\n//   const webConnectionProtocol6Goodbye = Convert.toWebConnectionProtocol6Goodbye(json);\n//   const webConnectionProtocolMessage = Convert.toWebConnectionProtocolMessage(json);\n//   const addContextListenerRequest = Convert.toAddContextListenerRequest(json);\n//   const addContextListenerResponse = Convert.toAddContextListenerResponse(json);\n//   const addEventListenerRequest = Convert.toAddEventListenerRequest(json);\n//   const addEventListenerResponse = Convert.toAddEventListenerResponse(json);\n//   const addIntentListenerRequest = Convert.toAddIntentListenerRequest(json);\n//   const addIntentListenerResponse = Convert.toAddIntentListenerResponse(json);\n//   const agentEventMessage = Convert.toAgentEventMessage(json);\n//   const agentResponseMessage = Convert.toAgentResponseMessage(json);\n//   const appRequestMessage = Convert.toAppRequestMessage(json);\n//   const broadcastEvent = Convert.toBroadcastEvent(json);\n//   const broadcastRequest = Convert.toBroadcastRequest(json);\n//   const broadcastResponse = Convert.toBroadcastResponse(json);\n//   const channelChangedEvent = Convert.toChannelChangedEvent(json);\n//   const clearContextRequest = Convert.toClearContextRequest(json);\n//   const clearContextResponse = Convert.toClearContextResponse(json);\n//   const contextClearedEvent = Convert.toContextClearedEvent(json);\n//   const contextListenerUnsubscribeRequest = Convert.toContextListenerUnsubscribeRequest(json);\n//   const contextListenerUnsubscribeResponse = Convert.toContextListenerUnsubscribeResponse(json);\n//   const createPrivateChannelRequest = Convert.toCreatePrivateChannelRequest(json);\n//   const createPrivateChannelResponse = Convert.toCreatePrivateChannelResponse(json);\n//   const eventListenerUnsubscribeRequest = Convert.toEventListenerUnsubscribeRequest(json);\n//   const eventListenerUnsubscribeResponse = Convert.toEventListenerUnsubscribeResponse(json);\n//   const fdc3UserInterfaceChannelSelected = Convert.toFdc3UserInterfaceChannelSelected(json);\n//   const fdc3UserInterfaceChannels = Convert.toFdc3UserInterfaceChannels(json);\n//   const fdc3UserInterfaceDrag = Convert.toFdc3UserInterfaceDrag(json);\n//   const fdc3UserInterfaceHandshake = Convert.toFdc3UserInterfaceHandshake(json);\n//   const fdc3UserInterfaceHello = Convert.toFdc3UserInterfaceHello(json);\n//   const fdc3UserInterfaceMessage = Convert.toFdc3UserInterfaceMessage(json);\n//   const fdc3UserInterfaceResolve = Convert.toFdc3UserInterfaceResolve(json);\n//   const fdc3UserInterfaceResolveAction = Convert.toFdc3UserInterfaceResolveAction(json);\n//   const fdc3UserInterfaceRestyle = Convert.toFdc3UserInterfaceRestyle(json);\n//   const findInstancesRequest = Convert.toFindInstancesRequest(json);\n//   const findInstancesResponse = Convert.toFindInstancesResponse(json);\n//   const findIntentRequest = Convert.toFindIntentRequest(json);\n//   const findIntentResponse = Convert.toFindIntentResponse(json);\n//   const findIntentsByContextRequest = Convert.toFindIntentsByContextRequest(json);\n//   const findIntentsByContextResponse = Convert.toFindIntentsByContextResponse(json);\n//   const getAppMetadataRequest = Convert.toGetAppMetadataRequest(json);\n//   const getAppMetadataResponse = Convert.toGetAppMetadataResponse(json);\n//   const getCurrentChannelRequest = Convert.toGetCurrentChannelRequest(json);\n//   const getCurrentChannelResponse = Convert.toGetCurrentChannelResponse(json);\n//   const getCurrentContextRequest = Convert.toGetCurrentContextRequest(json);\n//   const getCurrentContextResponse = Convert.toGetCurrentContextResponse(json);\n//   const getInfoRequest = Convert.toGetInfoRequest(json);\n//   const getInfoResponse = Convert.toGetInfoResponse(json);\n//   const getOrCreateChannelRequest = Convert.toGetOrCreateChannelRequest(json);\n//   const getOrCreateChannelResponse = Convert.toGetOrCreateChannelResponse(json);\n//   const getUserChannelsRequest = Convert.toGetUserChannelsRequest(json);\n//   const getUserChannelsResponse = Convert.toGetUserChannelsResponse(json);\n//   const heartbeatAcknowledgementRequest = Convert.toHeartbeatAcknowledgementRequest(json);\n//   const heartbeatEvent = Convert.toHeartbeatEvent(json);\n//   const intentEvent = Convert.toIntentEvent(json);\n//   const intentListenerUnsubscribeRequest = Convert.toIntentListenerUnsubscribeRequest(json);\n//   const intentListenerUnsubscribeResponse = Convert.toIntentListenerUnsubscribeResponse(json);\n//   const intentResultRequest = Convert.toIntentResultRequest(json);\n//   const intentResultResponse = Convert.toIntentResultResponse(json);\n//   const joinUserChannelRequest = Convert.toJoinUserChannelRequest(json);\n//   const joinUserChannelResponse = Convert.toJoinUserChannelResponse(json);\n//   const leaveCurrentChannelRequest = Convert.toLeaveCurrentChannelRequest(json);\n//   const leaveCurrentChannelResponse = Convert.toLeaveCurrentChannelResponse(json);\n//   const openRequest = Convert.toOpenRequest(json);\n//   const openResponse = Convert.toOpenResponse(json);\n//   const privateChannelAddEventListenerRequest = Convert.toPrivateChannelAddEventListenerRequest(json);\n//   const privateChannelAddEventListenerResponse = Convert.toPrivateChannelAddEventListenerResponse(json);\n//   const privateChannelDisconnectRequest = Convert.toPrivateChannelDisconnectRequest(json);\n//   const privateChannelDisconnectResponse = Convert.toPrivateChannelDisconnectResponse(json);\n//   const privateChannelOnAddContextListenerEvent = Convert.toPrivateChannelOnAddContextListenerEvent(json);\n//   const privateChannelOnDisconnectEvent = Convert.toPrivateChannelOnDisconnectEvent(json);\n//   const privateChannelOnUnsubscribeEvent = Convert.toPrivateChannelOnUnsubscribeEvent(json);\n//   const privateChannelUnsubscribeEventListenerRequest = Convert.toPrivateChannelUnsubscribeEventListenerRequest(json);\n//   const privateChannelUnsubscribeEventListenerResponse = Convert.toPrivateChannelUnsubscribeEventListenerResponse(json);\n//   const raiseIntentForContextRequest = Convert.toRaiseIntentForContextRequest(json);\n//   const raiseIntentForContextResponse = Convert.toRaiseIntentForContextResponse(json);\n//   const raiseIntentRequest = Convert.toRaiseIntentRequest(json);\n//   const raiseIntentResponse = Convert.toRaiseIntentResponse(json);\n//   const raiseIntentResultResponse = Convert.toRaiseIntentResultResponse(json);\n//\n// These functions will throw an error if the JSON doesn't\n// match the expected interface, even if the JSON is valid.\n\n/**\n * Hello message sent by an application to a parent window or frame when attempting to\n * establish connectivity to a Desktop Agent.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol1Hello {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol1HelloPayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP1Hello';\n}\n\n/**\n * Metadata for a Web Connection Protocol message.\n */\nexport interface WebConnectionProtocol1HelloMeta {\n  connectionAttemptUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol1HelloPayload {\n  /**\n   * The current URL of the page attempting to connect. This may differ from the identityUrl,\n   * but the origins MUST match.\n   */\n  actualUrl: string;\n  /**\n   * A flag that may be used to indicate that a channel selector user interface is or is not\n   * required. Set to `false` if the app includes its own interface for selecting channels or\n   * does not work with user channels.\n   */\n  channelSelector?: boolean;\n  /**\n   * The version of FDC3 API that the app supports.\n   */\n  fdc3Version: string;\n  /**\n   * URL to use for the identity of the application. Desktop Agents MUST validate that the\n   * origin of the message matches the URL, but MAY implement custom comparison logic.\n   */\n  identityUrl: string;\n  /**\n   * A flag that may be used to indicate that an intent resolver is or is not required. Set to\n   * `false` if no intents, or only targeted intents, are raised.\n   */\n  intentResolver?: boolean;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Response from a Desktop Agent to an application requesting access to it indicating that\n * it should load a specified URL into a hidden iframe in order to establish connectivity to\n * a Desktop Agent.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol2LoadURL {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol2LoadURLPayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP2LoadUrl';\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol2LoadURLPayload {\n  /**\n   * A URL which can be used to establish communication with the Desktop Agent, via loading\n   * the URL into an iframe and restarting the Web Connection protocol with the iframe as the\n   * target.\n   */\n  iframeUrl: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Handshake message sent by the Desktop Agent to the app (with a MessagePort appended) that\n * should be used for subsequent communication steps.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol3Handshake {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol3HandshakePayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP3Handshake';\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol3HandshakePayload {\n  /**\n   * Indicates a custom timeout (in milliseconds) that should be used for API message\n   * exchanges that may involve launching an application, instead of the default 100,000\n   * millisecond timeout.\n   */\n  appLaunchTimeout?: number;\n  /**\n   * Indicates whether a channel selector user interface is required and the URL to use to do\n   * so. Set to `true` to use the default or `false` to disable the channel selector (as the\n   * Desktop Agent will handle it another way).\n   */\n  channelSelectorUrl: boolean | string;\n  /**\n   * The version of FDC3 API that the Desktop Agent will provide support for.\n   */\n  fdc3Version: string;\n  /**\n   * Indicates whether an intent resolver user interface is required and the URL to use to do\n   * so. Set to `true` to use the default or `false` to disable the intent resolver (as the\n   * Desktop Agent will handle it another way).\n   */\n  intentResolverUrl: boolean | string;\n  /**\n   * Indicates a custom timeout (in milliseconds) that should be used for the majority of API\n   * message exchanges instead of the default 10,000 millisecond timeout.\n   */\n  messageExchangeTimeout?: number;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Identity Validation request from an app attempting to connect to a Desktop Agent.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol4ValidateAppIdentity {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol4ValidateAppIdentityPayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP4ValidateAppIdentity';\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol4ValidateAppIdentityPayload {\n  /**\n   * The current URL of the page attempting to connect. This may differ from the identityUrl,\n   * but the origins MUST match.\n   */\n  actualUrl: string;\n  /**\n   * URL to use for the identity of the application. Desktop Agents MUST validate that the\n   * origin of the message matches the URL, but MAY implement custom comparison logic.\n   */\n  identityUrl: string;\n  /**\n   * If an application has previously connected to the Desktop Agent, it may specify its prior\n   * instance id and associated instance UUID to request the same same instance Id be assigned.\n   */\n  instanceId?: string;\n  /**\n   * Instance UUID associated with the requested instanceId.\n   */\n  instanceUuid?: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Message sent by the Desktop Agent to an app if their identity validation fails.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol5ValidateAppIdentityFailedResponse {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol5ValidateAppIdentityFailedResponsePayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP5ValidateAppIdentityFailedResponse';\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol5ValidateAppIdentityFailedResponsePayload {\n  message?: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Message sent by the Desktop Agent to an app after successful identity validation.\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol5ValidateAppIdentitySuccessResponse {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol1HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: WebConnectionProtocol5ValidateAppIdentitySuccessResponsePayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP5ValidateAppIdentityResponse';\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface WebConnectionProtocol5ValidateAppIdentitySuccessResponsePayload {\n  /**\n   * The appId that the app's identity was validated against.\n   */\n  appId: string;\n  /**\n   * Implementation metadata for the Desktop Agent, which includes an appMetadata element\n   * containing a copy of the app's own metadata.\n   */\n  implementationMetadata: ImplementationMetadata;\n  /**\n   * The instance Id granted to the application by the Desktop Agent.\n   */\n  instanceId: string;\n  /**\n   * Instance UUID associated with the instanceId granted, which may be used to retrieve the\n   * same instanceId if the app is reloaded or navigates.\n   */\n  instanceUuid: string;\n}\n\n/**\n * Implementation metadata for the Desktop Agent, which includes an appMetadata element\n * containing a copy of the app's own metadata.\n *\n * Includes Metadata for the current application.\n *\n * Metadata relating to the FDC3 Desktop Agent implementation and its provider.\n */\nexport interface ImplementationMetadata {\n  /**\n   * The calling application instance's own metadata, according to the Desktop Agent (MUST\n   * include at least the `appId` and `instanceId`).\n   */\n  appMetadata: AppMetadata;\n  /**\n   * The version number of the FDC3 specification that the implementation provides.\n   * The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  fdc3Version: string;\n  /**\n   * Metadata indicating whether the Desktop Agent implements optional features of\n   * the Desktop Agent API.\n   */\n  optionalFeatures: OptionalFeatures;\n  /**\n   * The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42,\n   * OpenFin etc.).\n   */\n  provider: string;\n  /**\n   * The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\n   */\n  providerVersion?: string;\n}\n\n/**\n * The calling application instance's own metadata, according to the Desktop Agent (MUST\n * include at least the `appId` and `instanceId`).\n *\n * Extends an `AppIdentifier`, describing an application or instance of an application, with\n * additional descriptive metadata that is usually provided by an FDC3 App Directory that\n * the Desktop Agent connects to.\n *\n * The additional information from an app directory can aid in rendering UI elements, such\n * as a launcher menu or resolver UI. This includes a title, description, tooltip and icon\n * and screenshot URLs.\n *\n * Note that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the\n * `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\n */\nexport interface AppMetadata {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * A longer, multi-paragraph description for the application that could include markup.\n   */\n  description?: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent?: string;\n  /**\n   * A list of icon URLs for the application that can be used to render UI elements.\n   */\n  icons?: Icon[];\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  /**\n   * An optional set of, implementation specific, metadata fields that can be used to\n   * disambiguate instances, such as a window title or screen position. Must only be set if\n   * `instanceId` is set.\n   */\n  instanceMetadata?: { [key: string]: any };\n  /**\n   * The 'friendly' app name.\n   * This field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now\n   * require an `AppIdentifier` wth `appId` set.\n   * Note that for display purposes the `title` field should be used, if set, in preference to\n   * this field.\n   */\n  name?: string;\n  /**\n   * The type of output returned for any intent specified during resolution. May express a\n   * particular context type (e.g. \"fdc3.instrument\"), channel (e.g. \"channel\") or a channel\n   * that will receive a specified type (e.g. \"channel<fdc3.instrument>\").\n   */\n  resultType?: null | string;\n  /**\n   * Images representing the app in common usage scenarios that can be used to render UI\n   * elements.\n   */\n  screenshots?: Image[];\n  /**\n   * A more user-friendly application title that can be used to render UI elements.\n   */\n  title?: string;\n  /**\n   * A tooltip for the application that can be used to render UI elements.\n   */\n  tooltip?: string;\n  /**\n   * The Version of the application.\n   */\n  version?: string;\n}\n\n/**\n * Describes an Icon image that may be used to represent the application.\n */\nexport interface Icon {\n  /**\n   * The icon dimension, formatted as `<height>x<width>`.\n   */\n  size?: string;\n  /**\n   * The icon url.\n   */\n  src: string;\n  /**\n   * Icon media type. If not present the Desktop Agent may use the src file extension.\n   */\n  type?: string;\n}\n\n/**\n * Describes an image file, typically a screenshot, that often represents the application in\n * a common usage scenario.\n */\nexport interface Image {\n  /**\n   * Caption for the image.\n   */\n  label?: string;\n  /**\n   * The image dimension, formatted as `<height>x<width>`.\n   */\n  size?: string;\n  /**\n   * The image url.\n   */\n  src: string;\n  /**\n   * Image media type. If not present the Desktop Agent may use the src file extension.\n   */\n  type?: string;\n}\n\n/**\n * Metadata indicating whether the Desktop Agent implements optional features of\n * the Desktop Agent API.\n */\nexport interface OptionalFeatures {\n  /**\n   * Used to indicate whether the experimental Desktop Agent Bridging\n   * feature is implemented by the Desktop Agent.\n   */\n  DesktopAgentBridging: boolean;\n  /**\n   * Used to indicate whether the exposure of 'originating app metadata' for\n   * context and intent messages is supported by the Desktop Agent.\n   */\n  OriginatingAppMetadata: boolean;\n  /**\n   * Used to indicate whether the optional `fdc3.joinUserChannel`,\n   * `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n   * the Desktop Agent.\n   */\n  UserChannelMembershipAPIs: boolean;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Goodbye message to be sent to the Desktop Agent when disconnecting (e.g. when closing the\n * window or navigating). Desktop Agents should close the MessagePort after receiving this\n * message, but retain instance details in case the application reconnects (e.g. after a\n * navigation event).\n *\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocol6Goodbye {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: WebConnectionProtocol6GoodbyeMeta;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'WCP6Goodbye';\n}\n\n/**\n * Metadata for a Web Connection Protocol message.\n */\nexport interface WebConnectionProtocol6GoodbyeMeta {\n  timestamp: Date;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * A message used during the connection flow for an application to a Desktop Agent in a\n * browser window. Used for messages sent in either direction.\n */\nexport interface WebConnectionProtocolMessage {\n  /**\n   * Metadata for a Web Connection Protocol message.\n   */\n  meta: ConnectionStepMetadata;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload?: { [key: string]: any };\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: ConnectionStepMessageType;\n}\n\n/**\n * Metadata for a Web Connection Protocol message.\n */\nexport interface ConnectionStepMetadata {\n  timestamp: Date;\n  connectionAttemptUuid?: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\nexport type ConnectionStepMessageType =\n  | 'WCP1Hello'\n  | 'WCP2LoadUrl'\n  | 'WCP3Handshake'\n  | 'WCP4ValidateAppIdentity'\n  | 'WCP5ValidateAppIdentityFailedResponse'\n  | 'WCP5ValidateAppIdentityResponse'\n  | 'WCP6Goodbye';\n\n/**\n * A request to add a context listener to a specified Channel OR to the current user\n * channel. Where the listener is added to the current user channel (channelId == null), and\n * this app has already been added to a user channel, client code should make a subsequent\n * request to get the current context of that channel for this listener and then call its\n * handler with it.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface AddContextListenerRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: AddContextListenerRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'addContextListenerRequest';\n}\n\n/**\n * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n */\nexport interface AddContextListenerRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that a request or response was received\n   * from. Please note that this may be set by an app or Desktop Agent proxy for debugging\n   * purposes but a Desktop Agent should make its own determination of the source of a message\n   * to avoid spoofing.\n   */\n  source?: AppIdentifier;\n  timestamp: Date;\n}\n\n/**\n * Field that represents the source application that a request or response was received\n * from. Please note that this may be set by an app or Desktop Agent proxy for debugging\n * purposes but a Desktop Agent should make its own determination of the source of a message\n * to avoid spoofing.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that the request being responded to was\n * received from, for debugging purposes.\n *\n * Details of the application instance that broadcast the context.\n *\n * The App resolution option chosen.\n *\n * Details of the application instance that raised the intent.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface AppIdentifier {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface AddContextListenerRequestPayload {\n  /**\n   * The id of the channel to add the listener to or `null` indicating that it should listen\n   * to the current user channel (at the time of broadcast).\n   */\n  channelId: null | string;\n  /**\n   * The type of context to listen for OR `null` indicating that it should listen to all\n   * context types.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a addContextListener request. Where the listener was added to the current\n * user channel (channelId == null), and this app has already been added to a user channel,\n * client code should make a subsequent request to get the current context of that channel\n * for this listener and then call its handler with it.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface AddContextListenerResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: AddContextListenerResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'addContextListenerResponse';\n}\n\n/**\n * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n */\nexport interface AddContextListenerResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  /**\n   * Field that represents the source application that the request being responded to was\n   * received from, for debugging purposes.\n   */\n  source?: AppIdentifier;\n  timestamp: Date;\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface AddContextListenerResponsePayload {\n  error?: PurpleError;\n  listenerUUID?: string;\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type PurpleError =\n  | 'AccessDenied'\n  | 'CreationFailed'\n  | 'MalformedContext'\n  | 'NoChannelFound'\n  | 'ApiTimeout'\n  | 'InvalidArguments';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to add an event listener for a specified event type to the Desktop Agent.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface AddEventListenerRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: AddEventListenerRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'addEventListenerRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface AddEventListenerRequestPayload {\n  /**\n   * The type of the event to be listened to or `null` to listen to all event types.\n   */\n  type: 'USER_CHANNEL_CHANGED' | null;\n}\n\n/**\n * The type of a (non-context and non-intent) event that may be received via the FDC3 API's\n * addEventListener function.\n */\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to an addEventListener request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface AddEventListenerResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: AddEventListenerResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'addEventListenerResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface AddEventListenerResponsePayload {\n  error?: ResponsePayloadError;\n  listenerUUID?: string;\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type ResponsePayloadError =\n  | 'AccessDenied'\n  | 'CreationFailed'\n  | 'MalformedContext'\n  | 'NoChannelFound'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'AppNotFound'\n  | 'AppTimeout'\n  | 'DesktopAgentNotFound'\n  | 'ErrorOnLaunch'\n  | 'ResolverUnavailable'\n  | 'IntentDeliveryFailed'\n  | 'NoAppsFound'\n  | 'ResolverTimeout'\n  | 'TargetAppUnavailable'\n  | 'TargetInstanceUnavailable'\n  | 'UserCancelledResolution'\n  | 'IntentListenerConflict'\n  | 'IntentHandlerRejected'\n  | 'NoResultReturned'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to add an Intent listener for a specified intent type.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface AddIntentListenerRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: AddIntentListenerRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'addIntentListenerRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface AddIntentListenerRequestPayload {\n  /**\n   * The name of the intent to listen for.\n   */\n  intent: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a addIntentListener request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface AddIntentListenerResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: PayloadObject;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'addIntentListenerResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface PayloadObject {\n  error?: FluffyError;\n  listenerUUID?: string;\n  [property: string]: any;\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type FluffyError =\n  | 'MalformedContext'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'DesktopAgentNotFound'\n  | 'ResolverUnavailable'\n  | 'IntentDeliveryFailed'\n  | 'NoAppsFound'\n  | 'ResolverTimeout'\n  | 'TargetAppUnavailable'\n  | 'TargetInstanceUnavailable'\n  | 'UserCancelledResolution'\n  | 'IntentListenerConflict';\n\n/**\n * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n */\nexport interface AgentEventMessageMeta {\n  eventUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\nexport type EventMessageType =\n  | 'addEventListenerEvent'\n  | 'broadcastEvent'\n  | 'channelChangedEvent'\n  | 'heartbeatEvent'\n  | 'intentEvent'\n  | 'privateChannelOnAddContextListenerEvent'\n  | 'privateChannelOnDisconnectEvent'\n  | 'privateChannelOnUnsubscribeEvent'\n  | 'contextClearedEvent';\n\n/**\n * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n */\nexport interface AgentResponseMessageMeta {\n  requestUuid: string;\n  responseUuid: string;\n  /**\n   * Field that represents the source application that the request being responded to was\n   * received from, for debugging purposes.\n   */\n  source?: AppIdentifier;\n  timestamp: Date;\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface AgentResponseMessageResponsePayload {\n  error?: ResponsePayloadError;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\nexport type ResponseMessageType =\n  | 'addContextListenerResponse'\n  | 'addEventListenerResponse'\n  | 'addIntentListenerResponse'\n  | 'broadcastResponse'\n  | 'contextListenerUnsubscribeResponse'\n  | 'createPrivateChannelResponse'\n  | 'eventListenerUnsubscribeResponse'\n  | 'findInstancesResponse'\n  | 'findIntentResponse'\n  | 'findIntentsByContextResponse'\n  | 'getAppMetadataResponse'\n  | 'getCurrentChannelResponse'\n  | 'getCurrentContextResponse'\n  | 'getInfoResponse'\n  | 'getOrCreateChannelResponse'\n  | 'getUserChannelsResponse'\n  | 'intentListenerUnsubscribeResponse'\n  | 'intentResultResponse'\n  | 'joinUserChannelResponse'\n  | 'leaveCurrentChannelResponse'\n  | 'openResponse'\n  | 'privateChannelAddEventListenerResponse'\n  | 'privateChannelDisconnectResponse'\n  | 'privateChannelUnsubscribeEventListenerResponse'\n  | 'raiseIntentForContextResponse'\n  | 'raiseIntentResponse'\n  | 'raiseIntentResultResponse'\n  | 'clearContextResponse';\n\n/**\n * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n */\nexport interface AppRequestMessageMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that a request or response was received\n   * from. Please note that this may be set by an app or Desktop Agent proxy for debugging\n   * purposes but a Desktop Agent should make its own determination of the source of a message\n   * to avoid spoofing.\n   */\n  source?: AppIdentifier;\n  timestamp: Date;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\nexport type RequestMessageType =\n  | 'addContextListenerRequest'\n  | 'addEventListenerRequest'\n  | 'addIntentListenerRequest'\n  | 'broadcastRequest'\n  | 'contextListenerUnsubscribeRequest'\n  | 'createPrivateChannelRequest'\n  | 'eventListenerUnsubscribeRequest'\n  | 'findInstancesRequest'\n  | 'findIntentRequest'\n  | 'findIntentsByContextRequest'\n  | 'getAppMetadataRequest'\n  | 'getCurrentChannelRequest'\n  | 'getCurrentContextRequest'\n  | 'getInfoRequest'\n  | 'getOrCreateChannelRequest'\n  | 'getUserChannelsRequest'\n  | 'heartbeatAcknowledgementRequest'\n  | 'intentListenerUnsubscribeRequest'\n  | 'intentResultRequest'\n  | 'joinUserChannelRequest'\n  | 'leaveCurrentChannelRequest'\n  | 'openRequest'\n  | 'privateChannelAddEventListenerRequest'\n  | 'privateChannelDisconnectRequest'\n  | 'privateChannelUnsubscribeEventListenerRequest'\n  | 'raiseIntentForContextRequest'\n  | 'raiseIntentRequest'\n  | 'clearContextRequest';\n\n/**\n * An event message from the Desktop Agent to an app indicating that context has been\n * broadcast on a channel it is listening to, or specifically to this app instance if it was\n * launched via `fdc3.open` and context was passed.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface BroadcastEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: BroadcastEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'broadcastEvent';\n}\n\n/**\n * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n */\nexport interface BroadcastEventMeta {\n  eventUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface BroadcastEventPayload {\n  /**\n   * The Id of the channel that the broadcast was sent on. May be `null` if the context is\n   * being broadcast due to a call `fdc3.open` that passed context.\n   */\n  channelId: null | string;\n  /**\n   * The context object that was broadcast.\n   */\n  context: Context;\n  /**\n   * Details of the application instance that broadcast the context.\n   */\n  originatingApp?: AppIdentifier;\n}\n\n/**\n * The context object that was broadcast.\n *\n * The context object that is to be broadcast.\n *\n * The context object passed with the raised intent.\n *\n * If a Context object is passed in, this object will be provided to the opened application\n * via a contextListener. The Context argument is functionally equivalent to opening the\n * target app with no context and broadcasting the context directly to it.\n *\n * The `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by\n * FDC3 operations. As such, it is not really meant to be used on its own, but is imported\n * by more specific type definitions (standardized or custom) to provide the structure and\n * properties shared by all FDC3 context data types.\n *\n * The key element of FDC3 context types is their mandatory `type` property, which is used\n * to identify what type of data the object represents, and what shape it has.\n *\n * The FDC3 context type, and all derived types, define the minimum set of fields a context\n * data object of a particular type can be expected to have, but this can always be extended\n * with custom fields as appropriate.\n */\nexport interface Context {\n  /**\n   * Context data objects may include a set of equivalent key-value pairs that can be used to\n   * help applications identify and look up the context type they receive in their own domain.\n   * The idea behind this design is that applications can provide as many equivalent\n   * identifiers to a target application as possible, e.g. an instrument may be represented by\n   * an ISIN, CUSIP or Bloomberg identifier.\n   *\n   * Identifiers do not make sense for all types of data, so the `id` property is therefore\n   * optional, but some derived types may choose to require at least one identifier.\n   * Identifier values SHOULD always be of type string.\n   */\n  id?: { [key: string]: any };\n  /**\n   * Context data objects may include a name property that can be used for more information,\n   * or display purposes. Some derived types may require the name object as mandatory,\n   * depending on use case.\n   */\n  name?: string;\n  /**\n   * The type property is the only _required_ part of the FDC3 context data schema. The FDC3\n   * [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present\n   * to route shared context data appropriately.\n   *\n   * FDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data\n   * types they support in an FDC3 [App\n   * Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery\n   * and routing.\n   *\n   * Standardized FDC3 context types have well-known `type` properties prefixed with the\n   * `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and\n   * used by a particular organization, the convention is to prefix them with an\n   * organization-specific namespace, e.g. `blackrock.fund`.\n   *\n   * See the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more\n   * information about context data types.\n   */\n  type: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to broadcast context on a channel.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface BroadcastRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: BroadcastRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'broadcastRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface BroadcastRequestPayload {\n  /**\n   * The Id of the Channel that the broadcast was sent on.\n   */\n  channelId: string;\n  /**\n   * The context object that is to be broadcast.\n   */\n  context: Context;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a request to broadcast context on a channel.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface BroadcastResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'broadcastResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface BroadcastResponseResponsePayload {\n  error?: ResponsePayloadError;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that its current user\n * channel has changed.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface ChannelChangedEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: ChannelChangedEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'channelChangedEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface ChannelChangedEventPayload {\n  /**\n   * Deprecated - allowed for backwards compatibility.  The Id of the channel that the app was\n   * added to or `null` if it was removed from a channel.\n   */\n  newChannelId?: null | string;\n  /**\n   * The Id of the channel that the app was added to or `null` if it was removed from a\n   * channel.\n   */\n  currentChannelId?: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to clear context on a channel.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface ClearContextRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: ClearContextRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'clearContextRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface ClearContextRequestPayload {\n  /**\n   * The id of the channel to clear the context on.\n   */\n  channelId: string;\n  /**\n   * The type of context to clear for OR `null` indicating that all context types on the\n   * channel should be cleared.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a request to clear context on a channel.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface ClearContextResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'clearContextResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that context has been\n * cleared on a channel.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface ContextClearedEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: ContextClearedEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'contextClearedEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface ContextClearedEventPayload {\n  /**\n   * The Id of the channel that was cleared.\n   */\n  channelId: null | string;\n  /**\n   * The type of context that was cleared, or null if all types were cleared.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to unsubscribe a context listener.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface ContextListenerUnsubscribeRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: ContextListenerUnsubscribeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'contextListenerUnsubscribeRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface ContextListenerUnsubscribeRequestPayload {\n  listenerUUID: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a contextListenerUnsubscribe request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface ContextListenerUnsubscribeResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'contextListenerUnsubscribeResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to return a Channel with an auto-generated identity that is intended for private\n * communication between applications.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface CreatePrivateChannelRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: CreatePrivateChannelRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'createPrivateChannelRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface CreatePrivateChannelRequestPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a createPrivateChannel request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface CreatePrivateChannelResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: CreatePrivateChannelResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'createPrivateChannelResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface CreatePrivateChannelResponsePayload {\n  error?: PurpleError;\n  privateChannel?: Channel;\n}\n\n/**\n * Represents a context channel that applications can use to send and receive\n * context data.\n *\n * Please note that There are differences in behavior when you interact with a\n * User channel via the `DesktopAgent` interface and the `Channel` interface.\n * Specifically, when 'joining' a User channel or adding a context listener\n * when already joined to a channel via the `DesktopAgent` interface, existing\n * context (matching the type of the context listener) on the channel is\n * received by the context listener immediately. Whereas, when a context\n * listener is added via the Channel interface, context is not received\n * automatically, but may be retrieved manually via the `getCurrentContext()`\n * function.\n */\nexport interface Channel {\n  /**\n   * Channels may be visualized and selectable by users. DisplayMetadata may be used to\n   * provide hints on how to see them.\n   * For App channels, displayMetadata would typically not be present.\n   */\n  displayMetadata?: DisplayMetadata;\n  /**\n   * Constant that uniquely identifies this channel.\n   */\n  id: string;\n  /**\n   * Uniquely defines each channel type.\n   * Can be \"user\", \"app\" or \"private\".\n   */\n  type: Type;\n}\n\n/**\n * Channels may be visualized and selectable by users. DisplayMetadata may be used to\n * provide hints on how to see them.\n * For App channels, displayMetadata would typically not be present.\n *\n * A system channel will be global enough to have a presence across many apps. This gives us\n * some hints\n * to render them in a standard way. It is assumed it may have other properties too, but if\n * it has these,\n * this is their meaning.\n */\nexport interface DisplayMetadata {\n  /**\n   * The color that should be associated within this channel when displaying this channel in a\n   * UI, e.g: `0xFF0000`.\n   */\n  color?: string;\n  /**\n   * A URL of an image that can be used to display this channel.\n   */\n  glyph?: string;\n  /**\n   * A user-readable name for this channel, e.g: `\"Red\"`.\n   */\n  name?: string;\n}\n\n/**\n * Uniquely defines each channel type.\n * Can be \"user\", \"app\" or \"private\".\n */\nexport type Type = 'app' | 'private' | 'user';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to unsubscribe an event listener.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface EventListenerUnsubscribeRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: EventListenerUnsubscribeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'eventListenerUnsubscribeRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface EventListenerUnsubscribeRequestPayload {\n  listenerUUID: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to an eventListenerUnsubscribe request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface EventListenerUnsubscribeResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'eventListenerUnsubscribeResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Message from a channel selector UI to the DA proxy sent when the channel selection\n * changes.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceChannelSelected {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceChannelSelectedPayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceChannelSelected';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceChannelSelectedPayload {\n  /**\n   * The id of the channel that should be currently selected, or `null` if none should be\n   * selected.\n   */\n  selected: null | string;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Setup message sent by the DA proxy code in getAgent() to a channel selector UI in an\n * iframe with the channel definitions and current channel selection.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceChannels {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceChannelsPayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceChannels';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceChannelsPayload {\n  /**\n   * The id of the channel that should be currently selected, or `null` if none should be\n   * selected.\n   */\n  selected: null | string;\n  /**\n   * User Channel definitions.```````s\n   */\n  userChannels: Channel[];\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Message from a UI iframe to the DA proxy (setup by `getAgent()`) indicating that the user\n * is dragging the UI to a new location and providing the offset to apply to the location.\n * The DA proxy implementation should limit the location to the current bounds of the\n * window's viewport.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceDrag {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceDragPayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceDrag';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceDragPayload {\n  /**\n   * The offset to move the frame by.\n   */\n  mouseOffsets: MouseOffsets;\n}\n\n/**\n * The offset to move the frame by.\n */\nexport interface MouseOffsets {\n  x: number;\n  y: number;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Handshake message sent back to a user interface from the DA proxy code (setup by\n * `getAgent()`) over the `MessagePort` provided in the preceding Fdc3UserInterfaceHello\n * message, confirming that it is listening to the `MessagePort` for further communication.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceHandshake {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceHandshakePayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceHandshake';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceHandshakePayload {\n  /**\n   * The version of FDC3 API that the Desktop Agent will provide support for.\n   */\n  fdc3Version: string;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Hello message sent by a UI to the Desktop Agent proxy setup by `getAgent()` to indicate\n * it is ready to communicate, containing initial CSS to set on the iframe, and including an\n * appended `MessagePort` to be used for further communication.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceHello {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceHelloPayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceHello';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceHelloPayload {\n  /**\n   * Details about the UI implementation, such as vendor and version, for logging purposes.\n   */\n  implementationDetails: string;\n  /**\n   * A constrained set of styling properties that should be set on the user interface before\n   * it is displayed. Note `position` cannot be specified and should always be set to `fixed`.\n   */\n  initialCSS: InitialCSS;\n}\n\n/**\n * A constrained set of styling properties that should be set on the user interface before\n * it is displayed. Note `position` cannot be specified and should always be set to `fixed`.\n */\nexport interface InitialCSS {\n  /**\n   * The initial bottom property to apply to the iframe.\n   */\n  bottom?: string;\n  /**\n   * The initial height of the iframe.\n   */\n  height?: string;\n  /**\n   * The initial left property to apply to the iframe.\n   */\n  left?: string;\n  /**\n   * The maximum height to apply to the iframe.\n   */\n  maxHeight?: string;\n  /**\n   * The maximum with to apply to the iframe.\n   */\n  maxWidth?: string;\n  /**\n   * The initial right property to apply to the iframe.\n   */\n  right?: string;\n  /**\n   * The initial top property to apply to the iframe.\n   */\n  top?: string;\n  /**\n   * The transition property to apply to the iframe.\n   */\n  transition?: string;\n  /**\n   * The initial width of the iframe.\n   */\n  width?: string;\n  /**\n   * The initial zindex to apply to the iframe.\n   */\n  zIndex?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceMessage {\n  /**\n   * The message payload.\n   */\n  payload?: { [key: string]: any };\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: Fdc3UserInterfaceMessageType;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\nexport type Fdc3UserInterfaceMessageType =\n  | 'Fdc3UserInterfaceHello'\n  | 'Fdc3UserInterfaceHandshake'\n  | 'Fdc3UserInterfaceRestyle'\n  | 'Fdc3UserInterfaceDrag'\n  | 'Fdc3UserInterfaceResolve'\n  | 'Fdc3UserInterfaceResolveAction'\n  | 'Fdc3UserInterfaceChannels'\n  | 'Fdc3UserInterfaceChannelSelected';\n\n/**\n * Setup message sent by the DA proxy code in getAgent() to an intent resolver UI with the\n * resolver data to setup the UI.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceResolve {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceResolvePayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceResolve';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceResolvePayload {\n  /**\n   * An array of AppIntent objects defining the resolution options.\n   */\n  appIntents: AppIntent[];\n  context: Context;\n}\n\n/**\n * An interface that relates an intent to apps.\n *\n * Used if a raiseIntent request requires additional resolution (e.g. by showing an intent\n * resolver) before it can be handled.\n */\nexport interface AppIntent {\n  /**\n   * Details of applications that can resolve the intent.\n   */\n  apps: AppMetadata[];\n  /**\n   * Details of the intent whose relationship to resolving applications is being described.\n   */\n  intent: IntentMetadata;\n}\n\n/**\n * Details of the intent whose relationship to resolving applications is being described.\n *\n * Metadata describing an Intent.\n */\nexport interface IntentMetadata {\n  /**\n   * Display name for the intent.\n   */\n  displayName?: string;\n  /**\n   * The unique name of the intent that can be invoked by the raiseIntent call.\n   */\n  name: string;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Message from an intent resolver UI to DA proxy code in getAgent() reporting a user\n * action.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceResolveAction {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceResolveActionPayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceResolveAction';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceResolveActionPayload {\n  action: Action;\n  /**\n   * The App resolution option chosen.\n   */\n  appIdentifier?: AppIdentifier;\n  /**\n   * The intent resolved.\n   */\n  intent?: string;\n}\n\nexport type Action = 'hover' | 'click' | 'cancel';\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * Message from a UI frame to the DA proxy code (setup by `getAgent()`) with updated styling\n * information to apply to it. Can be used to implement a pop-open or close interaction or\n * other transition needed by a UI implementation.\n *\n * A message used to communicate with user interface frames injected by `getAgent()` for\n * displaying UI elements such as the intent resolver or channel selector. Used for messages\n * sent in either direction.\n */\nexport interface Fdc3UserInterfaceRestyle {\n  /**\n   * The message payload.\n   */\n  payload: Fdc3UserInterfaceRestylePayload;\n  /**\n   * Identifies the type of the message to or from the user interface frame.\n   */\n  type: 'Fdc3UserInterfaceRestyle';\n}\n\n/**\n * The message payload.\n */\nexport interface Fdc3UserInterfaceRestylePayload {\n  /**\n   * A constrained set of styling properties that should be applied to the frame. Note\n   * `position` cannot be set, and should always be `fixed`.\n   */\n  updatedCSS: UpdatedCSS;\n}\n\n/**\n * A constrained set of styling properties that should be applied to the frame. Note\n * `position` cannot be set, and should always be `fixed`.\n */\nexport interface UpdatedCSS {\n  /**\n   * The initial bottom property to apply to the iframe.\n   */\n  bottom?: string;\n  /**\n   * The updated height of the iframe.\n   */\n  height?: string;\n  /**\n   * The initial left property to apply to the iframe.\n   */\n  left?: string;\n  /**\n   * The updated maximum height to apply to the iframe.\n   */\n  maxHeight?: string;\n  /**\n   * The updated maximum with to apply to the iframe.\n   */\n  maxWidth?: string;\n  /**\n   * The initial right property to apply to the iframe.\n   */\n  right?: string;\n  /**\n   * The initial top property to apply to the iframe.\n   */\n  top?: string;\n  /**\n   * The updated transition property to apply to the iframe.\n   */\n  transition?: string;\n  /**\n   * The updated width of the iframe.\n   */\n  width?: string;\n  /**\n   * The updated zIndex to apply to the iframe.\n   */\n  zIndex?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message to or from the user interface frame.\n */\n\n/**\n * A request for details of instances of a particular app.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface FindInstancesRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindInstancesRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findInstancesRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindInstancesRequestPayload {\n  app: AppIdentifier;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a findInstances request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface FindInstancesResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: FindInstancesResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findInstancesResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n *\n * The message payload contains a flag indicating whether the API call was successful, plus\n * any return values for the FDC3 API function called, or indicating that the request\n * resulted in an error and including a standardized error message.\n */\nexport interface FindInstancesResponsePayload {\n  error?: FindInstancesErrors;\n  appIdentifiers?: AppMetadata[];\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n *\n * Unique identifier for a for an attempt to connect to a Desktop Agent. A Unique UUID\n * should be used in the first (WCP1Hello) message and should be quoted in all subsequent\n * messages to link them to the same connection attempt.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n *\n * Unique identifier for a `listener` object returned by a Desktop Agent to an app in\n * response to addContextListener, addIntentListener or one of the PrivateChannel event\n * listeners and used to identify it in messages (e.g. when unsubscribing).\n *\n * Unique identifier for an event message sent from a Desktop Agent to an app.\n *\n * Should be set if the raiseIntent request returned an error.\n */\nexport type FindInstancesErrors =\n  | 'MalformedContext'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'DesktopAgentNotFound'\n  | 'ResolverUnavailable'\n  | 'IntentDeliveryFailed'\n  | 'NoAppsFound'\n  | 'ResolverTimeout'\n  | 'TargetAppUnavailable'\n  | 'TargetInstanceUnavailable'\n  | 'UserCancelledResolution'\n  | 'IntentListenerConflict'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request for details of apps available to resolve a particular intent and context pair.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface FindIntentRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentRequestPayload {\n  context?: Context;\n  intent: string;\n  resultType?: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a findIntent request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface FindIntentResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: FindIntentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface FindIntentResponsePayload {\n  error?: FindInstancesErrors;\n  appIntent?: AppIntent;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request for details of intents and apps available to resolve them for a particular\n * context.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface FindIntentsByContextRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentsByContextRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentsByContextRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentsByContextRequestPayload {\n  context: Context;\n  resultType?: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a findIntentsByContext request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface FindIntentsByContextResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: FindIntentsByContextResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentsByContextResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface FindIntentsByContextResponsePayload {\n  error?: FindInstancesErrors;\n  appIntents?: AppIntent[];\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request for metadata about an app.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetAppMetadataRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetAppMetadataRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getAppMetadataRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetAppMetadataRequestPayload {\n  app: AppIdentifier;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getAppMetadata request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetAppMetadataResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetAppMetadataResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getAppMetadataResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetAppMetadataResponsePayload {\n  error?: FindInstancesErrors;\n  appMetadata?: AppMetadata;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to return the Channel object for the current User channel membership. Returns\n * `null` if the app is not joined to a channel.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetCurrentChannelRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetCurrentChannelRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getCurrentChannelRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetCurrentChannelRequestPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getCurrentChannel request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetCurrentChannelResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetCurrentChannelResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getCurrentChannelResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetCurrentChannelResponsePayload {\n  error?: ResponsePayloadError;\n  channel?: Channel | null;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to return the current context (either of a specified type or most recent\n * broadcast) of a specified Channel. Returns `null` if no context (of the requested type if\n * one was specified) is available in the channel.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetCurrentContextRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetCurrentContextRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getCurrentContextRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetCurrentContextRequestPayload {\n  /**\n   * The id of the channel to return the current context of.\n   */\n  channelId: string;\n  /**\n   * The type of context to return for OR `null` indicating that the most recently broadcast\n   * context on the channel should be returned.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getCurrentContext request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetCurrentContextResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetCurrentContextResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getCurrentContextResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetCurrentContextResponsePayload {\n  error?: PurpleError;\n  /**\n   * The most recently broadcast context object (of the specified type, if one was specified),\n   * or `null` if none was available in the channel.\n   */\n  context?: null | Context;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to retrieve information about the FDC3 Desktop Agent implementation and the\n * metadata of the calling application according to the Desktop Agent.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetInfoRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetInfoRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getInfoRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetInfoRequestPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getInfo request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetInfoResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetInfoResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getInfoResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetInfoResponsePayload {\n  error?: ResponsePayloadError;\n  implementationMetadata?: ImplementationMetadata;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to return a Channel with an auto-generated identity that is intended for private\n * communication between applications.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetOrCreateChannelRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetOrCreateChannelRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getOrCreateChannelRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetOrCreateChannelRequestPayload {\n  /**\n   * The id of the channel to return\n   */\n  channelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getOrCreateChannel request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetOrCreateChannelResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetOrCreateChannelResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getOrCreateChannelResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetOrCreateChannelResponsePayload {\n  error?: PurpleError;\n  channel?: Channel;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to retrieve a list of the User Channels available for the app to join.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface GetUserChannelsRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetUserChannelsRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getUserChannelsRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetUserChannelsRequestPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a getUserChannels request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface GetUserChannelsResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: GetUserChannelsResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getUserChannelsResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface GetUserChannelsResponsePayload {\n  error?: PurpleError;\n  userChannels?: Channel[];\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request that serves as an acknowledgement of a heartbeat event from the Desktop Agent\n * and indicates that an application window or frame is still alive.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface HeartbeatAcknowledgementRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: HeartbeatAcknowledgementRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'heartbeatAcknowledgementRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface HeartbeatAcknowledgementRequestPayload {\n  /**\n   * The eventUuid value of the HeartbeatEvent that the acknowledgement being sent relates to.\n   */\n  heartbeatEventUuid: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A heartbeat message from the Desktop Agent to an app indicating that the Desktop Agent is\n * alive and that the application should send a heartbeatResponseRequest to the agent in\n * response.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface HeartbeatEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: HeartbeatEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'heartbeatEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface HeartbeatEventPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that it has been selected to\n * resolve a raised intent and context.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface IntentEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: IntentEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'intentEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface IntentEventPayload {\n  /**\n   * The context object passed with the raised intent.\n   */\n  context: Context;\n  /**\n   * The intent that was raised.\n   */\n  intent: string;\n  /**\n   * Details of the application instance that raised the intent.\n   */\n  originatingApp?: AppIdentifier;\n  /**\n   * The requestUuid value of the raiseIntentRequest that the intentEvent being sent relates\n   * to.\n   */\n  raiseIntentRequestUuid: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to unsubscribe a context listener.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface IntentListenerUnsubscribeRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: IntentListenerUnsubscribeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'intentListenerUnsubscribeRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface IntentListenerUnsubscribeRequestPayload {\n  listenerUUID: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a intentListenerUnsubscribe request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface IntentListenerUnsubscribeResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'intentListenerUnsubscribeResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to deliver a result for an intent (which may include a `void` result that just\n * indicates that the handler has run, returning no result). The result is tied to the\n * intentEvent it relates to by quoting the `eventUuid` of the intentEvent in its payload.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface IntentResultRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: IntentResultRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'intentResultRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface IntentResultRequestPayload {\n  /**\n   * The eventUuid value of the intentEvent that the result being sent relates to.\n   */\n  intentEventUuid: string;\n  intentResult: IntentResult;\n  /**\n   * The requestUuid value of the raiseIntentRequest that the result being sent relates to.\n   */\n  raiseIntentRequestUuid: string;\n}\n\nexport interface IntentResult {\n  context?: Context;\n  channel?: Channel;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a request to deliver an intent result.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface IntentResultResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'intentResultResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to join the app to the specified User channel. On successfully joining a channel,\n * client code should make subsequent requests to get the current context of that channel\n * for all registered context listeners and then call their handlers with it.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface JoinUserChannelRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: JoinUserChannelRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'joinUserChannelRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface JoinUserChannelRequestPayload {\n  /**\n   * The id of the channel to join.\n   */\n  channelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a joinUserChannel request. On receipt of this response, client code should\n * make subsequent requests to get the current context of that channel for all registered\n * context listeners and then call their handlers with it.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface JoinUserChannelResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: JoinUserChannelResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'joinUserChannelResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface JoinUserChannelResponsePayload {\n  error?: PurpleError;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request to remove the app from any User channel membership.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface LeaveCurrentChannelRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: LeaveCurrentChannelRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'leaveCurrentChannelRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface LeaveCurrentChannelRequestPayload {}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a leaveCurrentChannel request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface LeaveCurrentChannelResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: LeaveCurrentChannelResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'leaveCurrentChannelResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface LeaveCurrentChannelResponsePayload {\n  error?: PurpleError;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to open an application.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface OpenRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: OpenRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'openRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface OpenRequestPayload {\n  app: AppIdentifier;\n  /**\n   * If a Context object is passed in, this object will be provided to the opened application\n   * via a contextListener. The Context argument is functionally equivalent to opening the\n   * target app with no context and broadcasting the context directly to it.\n   */\n  context?: Context;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a open request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface OpenResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: OpenResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'openResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface OpenResponsePayload {\n  error?: OpenErrorResponsePayload;\n  appIdentifier?: AppIdentifier;\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type OpenErrorResponsePayload =\n  | 'MalformedContext'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'AppNotFound'\n  | 'AppTimeout'\n  | 'DesktopAgentNotFound'\n  | 'ErrorOnLaunch'\n  | 'ResolverUnavailable'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to add an event listener to a specific PrivateChannel.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface PrivateChannelAddEventListenerRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelAddEventListenerRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'privateChannelAddEventListenerRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelAddEventListenerRequestPayload {\n  /**\n   * The type of PrivateChannel event that the listener should be applied to, or null for all\n   * event types.\n   */\n  listenerType: PrivateChannelEventType | null;\n  /**\n   * The Id of the PrivateChannel that the listener should be added to.\n   */\n  privateChannelId: string;\n}\n\n/**\n * Type defining valid type strings for Private Channel events.\n */\nexport type PrivateChannelEventType = 'addContextListener' | 'unsubscribe' | 'disconnect';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a privateChannelAddEventListener request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface PrivateChannelAddEventListenerResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: PrivateChannelAddEventListenerResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelAddEventListenerResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface PrivateChannelAddEventListenerResponsePayload {\n  error?: PurpleError;\n  listenerUUID?: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * Request that indicates that a participant will no longer interact with a specified\n * `PrivateChannel`.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface PrivateChannelDisconnectRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelDisconnectRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'privateChannelDisconnectRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelDisconnectRequestPayload {\n  /**\n   * The Id of the Channel that should be disconnected from\n   */\n  channelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a privateChannelDisconnect request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface PrivateChannelDisconnectResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: PrivateChannelDisconnectResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelDisconnectResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface PrivateChannelDisconnectResponsePayload {\n  error?: PurpleError;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that another app has added a\n * context listener to a specific PrivateChannel.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface PrivateChannelOnAddContextListenerEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: PrivateChannelOnAddContextListenerEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelOnAddContextListenerEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface PrivateChannelOnAddContextListenerEventPayload {\n  /**\n   * The type of the context listener added to the channel by another app, or null if it will\n   * listen to all types.\n   */\n  contextType: null | string;\n  /**\n   * The Id of the PrivateChannel that the listener was added to.\n   */\n  privateChannelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that another app has\n * disconnected from a specific PrivateChannel and will no longer interact with it.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface PrivateChannelOnDisconnectEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: PrivateChannelOnDisconnectEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelOnDisconnectEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface PrivateChannelOnDisconnectEventPayload {\n  /**\n   * The Id of the PrivateChannel that the app has disconnected from.\n   */\n  privateChannelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * An event message from the Desktop Agent to an app indicating that another app has\n * unsubscribed a context listener from a specific PrivateChannel.\n *\n * A message from a Desktop Agent to an FDC3-enabled app representing an event.\n */\nexport interface PrivateChannelOnUnsubscribeEvent {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\n   */\n  meta: BroadcastEventMeta;\n  /**\n   * The message payload contains details of the event that the app is being notified about.\n   */\n  payload: PrivateChannelOnUnsubscribeEventPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelOnUnsubscribeEvent';\n}\n\n/**\n * The message payload contains details of the event that the app is being notified about.\n */\nexport interface PrivateChannelOnUnsubscribeEventPayload {\n  /**\n   * The type of the context listener unsubscribed from the channel by another app, or null if\n   * it was listening to all types.\n   */\n  contextType: null | string;\n  /**\n   * The Id of the PrivateChannel that the listener was unsubscribed from.\n   */\n  privateChannelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to unsubscribe a context listener.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface PrivateChannelUnsubscribeEventListenerRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelUnsubscribeEventListenerRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'privateChannelUnsubscribeEventListenerRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelUnsubscribeEventListenerRequestPayload {\n  listenerUUID: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a privateChannelUnsubscribeEventListener request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface PrivateChannelUnsubscribeEventListenerResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: BroadcastResponseResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'privateChannelUnsubscribeEventListenerResponse';\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to raise an unspecified intent for a specified context.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface RaiseIntentForContextRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: RaiseIntentForContextRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'raiseIntentForContextRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface RaiseIntentForContextRequestPayload {\n  app?: AppIdentifier;\n  context: Context;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a raiseIntentForContext request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface RaiseIntentForContextResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   *\n   * There are 3 possible responses to a raiseIntentForContext request, each of which sets a\n   * single property in the payload: Success (`intentResolution`), Needs further resolution\n   * (`appIntents`) or Error (`error`).\n   */\n  payload: RaiseIntentForContextResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentForContextResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n *\n * There are 3 possible responses to a raiseIntentForContext request, each of which sets a\n * single property in the payload: Success (`intentResolution`), Needs further resolution\n * (`appIntents`) or Error (`error`).\n *\n * Response to a raiseIntentForContext request that needs additional resolution (i.e. show\n * an intent resolver UI).\n *\n * Used if a raiseIntent request resulted in an error.\n */\nexport interface RaiseIntentForContextResponsePayload {\n  /**\n   * Should be set if the raiseIntent request returned an error.\n   */\n  error?: FindInstancesErrors;\n  /**\n   * Used if the raiseIntent request was successfully resolved.\n   */\n  intentResolution?: IntentResolution;\n  /**\n   * Used if a raiseIntentForContext request requires additional resolution (e.g. by showing\n   * an intent resolver) before it can be handled.\n   */\n  appIntents?: AppIntent[];\n}\n\n/**\n * Used if the raiseIntent request was successfully resolved.\n *\n * IntentResolution provides a standard format for data returned upon resolving an intent.\n *\n * ```javascript\n * //resolve a \"Chain\" type intent\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n *\n * //resolve a \"Client-Service\" type intent with a data response or a Channel\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n * try {\n * const result = await resolution.getResult();\n * if (result && result.broadcast) {\n * console.log(`${resolution.source} returned a channel with id ${result.id}`);\n * } else if (result){\n * console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n * } else {\n * console.error(`${resolution.source} didn't return data`\n * }\n * } catch(error) {\n * console.error(`${resolution.source} returned an error: ${error}`);\n * }\n *\n * // Use metadata about the resolving app instance to target a further intent\n * await agent.raiseIntent(\"intentName\", context, resolution.source);\n * ```\n */\nexport interface IntentResolution {\n  /**\n   * The intent that was raised. May be used to determine which intent the user\n   * chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  intent: string;\n  /**\n   * Identifier for the app instance that was selected (or started) to resolve the intent.\n   * `source.instanceId` MUST be set, indicating the specific app instance that\n   * received the intent.\n   */\n  source: AppIdentifier;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A request to raise an intent for a context.\n *\n * A request message from an FDC3-enabled app to a Desktop Agent.\n */\nexport interface RaiseIntentRequest {\n  /**\n   * Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\n   */\n  meta: AddContextListenerRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: RaiseIntentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'raiseIntentRequest';\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface RaiseIntentRequestPayload {\n  app?: AppIdentifier;\n  context: Context;\n  intent: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\n\n/**\n * A response to a raiseIntent request.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface RaiseIntentResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   *\n   * There are 3 possible responses to a raiseIntent request, each of which sets a single\n   * property in the payload: Success (`intentResolution`), Needs further resolution\n   * (`appIntent`) or Error (`error`).\n   */\n  payload: RaiseIntentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n *\n * There are 3 possible responses to a raiseIntent request, each of which sets a single\n * property in the payload: Success (`intentResolution`), Needs further resolution\n * (`appIntent`) or Error (`error`).\n *\n * Response to a raiseIntent request that needs additional resolution (i.e. show an intent\n * resolver UI).\n *\n * Used if a raiseIntent request resulted in an error.\n */\nexport interface RaiseIntentResponsePayload {\n  /**\n   * Should be set if the raiseIntent request returned an error.\n   */\n  error?: FindInstancesErrors;\n  /**\n   * Used if the raiseIntent request was successfully resolved.\n   */\n  intentResolution?: IntentResolution;\n  /**\n   * Used if a raiseIntent request requires additional resolution (e.g. by showing an intent\n   * resolver) before it can be handled.\n   */\n  appIntent?: AppIntent;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n/**\n * A secondary response to a request to raise an intent used to deliver the intent result.\n * This message should quote the original requestUuid of the raiseIntentRequest message in\n * its `meta.requestUuid` field.\n *\n * A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the\n * payload contains an `error` property, the request was unsuccessful.\n */\nexport interface RaiseIntentResultResponse {\n  /**\n   * Metadata for messages sent by a Desktop Agent to an app in response to an API call.\n   */\n  meta: AddContextListenerResponseMeta;\n  /**\n   * A payload for a response to an API call that will contain any return values or an `error`\n   * property containing a standardized error message indicating that the request was\n   * unsuccessful.\n   */\n  payload: RaiseIntentResultResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResultResponse';\n}\n\n/**\n * A payload for a response to an API call that will contain any return values or an `error`\n * property containing a standardized error message indicating that the request was\n * unsuccessful.\n */\nexport interface RaiseIntentResultResponsePayload {\n  error?: ResponsePayloadError;\n  intentResult?: IntentResult;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\n\n// Converts JSON strings to/from your types\n// and asserts the results of JSON.parse at runtime\nexport class Convert {\n  public static toWebConnectionProtocol1Hello(json: string): WebConnectionProtocol1Hello {\n    return cast(JSON.parse(json), r('WebConnectionProtocol1Hello'));\n  }\n\n  public static webConnectionProtocol1HelloToJson(value: WebConnectionProtocol1Hello): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol1Hello')), null, 2);\n  }\n\n  public static toWebConnectionProtocol2LoadURL(json: string): WebConnectionProtocol2LoadURL {\n    return cast(JSON.parse(json), r('WebConnectionProtocol2LoadURL'));\n  }\n\n  public static webConnectionProtocol2LoadURLToJson(value: WebConnectionProtocol2LoadURL): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol2LoadURL')), null, 2);\n  }\n\n  public static toWebConnectionProtocol3Handshake(json: string): WebConnectionProtocol3Handshake {\n    return cast(JSON.parse(json), r('WebConnectionProtocol3Handshake'));\n  }\n\n  public static webConnectionProtocol3HandshakeToJson(value: WebConnectionProtocol3Handshake): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol3Handshake')), null, 2);\n  }\n\n  public static toWebConnectionProtocol4ValidateAppIdentity(json: string): WebConnectionProtocol4ValidateAppIdentity {\n    return cast(JSON.parse(json), r('WebConnectionProtocol4ValidateAppIdentity'));\n  }\n\n  public static webConnectionProtocol4ValidateAppIdentityToJson(\n    value: WebConnectionProtocol4ValidateAppIdentity\n  ): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol4ValidateAppIdentity')), null, 2);\n  }\n\n  public static toWebConnectionProtocol5ValidateAppIdentityFailedResponse(\n    json: string\n  ): WebConnectionProtocol5ValidateAppIdentityFailedResponse {\n    return cast(JSON.parse(json), r('WebConnectionProtocol5ValidateAppIdentityFailedResponse'));\n  }\n\n  public static webConnectionProtocol5ValidateAppIdentityFailedResponseToJson(\n    value: WebConnectionProtocol5ValidateAppIdentityFailedResponse\n  ): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol5ValidateAppIdentityFailedResponse')), null, 2);\n  }\n\n  public static toWebConnectionProtocol5ValidateAppIdentitySuccessResponse(\n    json: string\n  ): WebConnectionProtocol5ValidateAppIdentitySuccessResponse {\n    return cast(JSON.parse(json), r('WebConnectionProtocol5ValidateAppIdentitySuccessResponse'));\n  }\n\n  public static webConnectionProtocol5ValidateAppIdentitySuccessResponseToJson(\n    value: WebConnectionProtocol5ValidateAppIdentitySuccessResponse\n  ): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol5ValidateAppIdentitySuccessResponse')), null, 2);\n  }\n\n  public static toWebConnectionProtocol6Goodbye(json: string): WebConnectionProtocol6Goodbye {\n    return cast(JSON.parse(json), r('WebConnectionProtocol6Goodbye'));\n  }\n\n  public static webConnectionProtocol6GoodbyeToJson(value: WebConnectionProtocol6Goodbye): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocol6Goodbye')), null, 2);\n  }\n\n  public static toWebConnectionProtocolMessage(json: string): WebConnectionProtocolMessage {\n    return cast(JSON.parse(json), r('WebConnectionProtocolMessage'));\n  }\n\n  public static webConnectionProtocolMessageToJson(value: WebConnectionProtocolMessage): string {\n    return JSON.stringify(uncast(value, r('WebConnectionProtocolMessage')), null, 2);\n  }\n\n  public static toAddContextListenerRequest(json: string): AddContextListenerRequest {\n    return cast(JSON.parse(json), r('AddContextListenerRequest'));\n  }\n\n  public static addContextListenerRequestToJson(value: AddContextListenerRequest): string {\n    return JSON.stringify(uncast(value, r('AddContextListenerRequest')), null, 2);\n  }\n\n  public static toAddContextListenerResponse(json: string): AddContextListenerResponse {\n    return cast(JSON.parse(json), r('AddContextListenerResponse'));\n  }\n\n  public static addContextListenerResponseToJson(value: AddContextListenerResponse): string {\n    return JSON.stringify(uncast(value, r('AddContextListenerResponse')), null, 2);\n  }\n\n  public static toAddEventListenerRequest(json: string): AddEventListenerRequest {\n    return cast(JSON.parse(json), r('AddEventListenerRequest'));\n  }\n\n  public static addEventListenerRequestToJson(value: AddEventListenerRequest): string {\n    return JSON.stringify(uncast(value, r('AddEventListenerRequest')), null, 2);\n  }\n\n  public static toAddEventListenerResponse(json: string): AddEventListenerResponse {\n    return cast(JSON.parse(json), r('AddEventListenerResponse'));\n  }\n\n  public static addEventListenerResponseToJson(value: AddEventListenerResponse): string {\n    return JSON.stringify(uncast(value, r('AddEventListenerResponse')), null, 2);\n  }\n\n  public static toAddIntentListenerRequest(json: string): AddIntentListenerRequest {\n    return cast(JSON.parse(json), r('AddIntentListenerRequest'));\n  }\n\n  public static addIntentListenerRequestToJson(value: AddIntentListenerRequest): string {\n    return JSON.stringify(uncast(value, r('AddIntentListenerRequest')), null, 2);\n  }\n\n  public static toAddIntentListenerResponse(json: string): AddIntentListenerResponse {\n    return cast(JSON.parse(json), r('AddIntentListenerResponse'));\n  }\n\n  public static addIntentListenerResponseToJson(value: AddIntentListenerResponse): string {\n    return JSON.stringify(uncast(value, r('AddIntentListenerResponse')), null, 2);\n  }\n\n  public static toAgentEventMessage(json: string): AgentEventMessage {\n    return cast(JSON.parse(json), r('AgentEventMessage'));\n  }\n\n  public static agentEventMessageToJson(value: AgentEventMessage): string {\n    return JSON.stringify(uncast(value, r('AgentEventMessage')), null, 2);\n  }\n\n  public static toAgentResponseMessage(json: string): AgentResponseMessage {\n    return cast(JSON.parse(json), r('AgentResponseMessage'));\n  }\n\n  public static agentResponseMessageToJson(value: AgentResponseMessage): string {\n    return JSON.stringify(uncast(value, r('AgentResponseMessage')), null, 2);\n  }\n\n  public static toAppRequestMessage(json: string): AppRequestMessage {\n    return cast(JSON.parse(json), r('AppRequestMessage'));\n  }\n\n  public static appRequestMessageToJson(value: AppRequestMessage): string {\n    return JSON.stringify(uncast(value, r('AppRequestMessage')), null, 2);\n  }\n\n  public static toBroadcastEvent(json: string): BroadcastEvent {\n    return cast(JSON.parse(json), r('BroadcastEvent'));\n  }\n\n  public static broadcastEventToJson(value: BroadcastEvent): string {\n    return JSON.stringify(uncast(value, r('BroadcastEvent')), null, 2);\n  }\n\n  public static toBroadcastRequest(json: string): BroadcastRequest {\n    return cast(JSON.parse(json), r('BroadcastRequest'));\n  }\n\n  public static broadcastRequestToJson(value: BroadcastRequest): string {\n    return JSON.stringify(uncast(value, r('BroadcastRequest')), null, 2);\n  }\n\n  public static toBroadcastResponse(json: string): BroadcastResponse {\n    return cast(JSON.parse(json), r('BroadcastResponse'));\n  }\n\n  public static broadcastResponseToJson(value: BroadcastResponse): string {\n    return JSON.stringify(uncast(value, r('BroadcastResponse')), null, 2);\n  }\n\n  public static toChannelChangedEvent(json: string): ChannelChangedEvent {\n    return cast(JSON.parse(json), r('ChannelChangedEvent'));\n  }\n\n  public static channelChangedEventToJson(value: ChannelChangedEvent): string {\n    return JSON.stringify(uncast(value, r('ChannelChangedEvent')), null, 2);\n  }\n\n  public static toClearContextRequest(json: string): ClearContextRequest {\n    return cast(JSON.parse(json), r('ClearContextRequest'));\n  }\n\n  public static clearContextRequestToJson(value: ClearContextRequest): string {\n    return JSON.stringify(uncast(value, r('ClearContextRequest')), null, 2);\n  }\n\n  public static toClearContextResponse(json: string): ClearContextResponse {\n    return cast(JSON.parse(json), r('ClearContextResponse'));\n  }\n\n  public static clearContextResponseToJson(value: ClearContextResponse): string {\n    return JSON.stringify(uncast(value, r('ClearContextResponse')), null, 2);\n  }\n\n  public static toContextClearedEvent(json: string): ContextClearedEvent {\n    return cast(JSON.parse(json), r('ContextClearedEvent'));\n  }\n\n  public static contextClearedEventToJson(value: ContextClearedEvent): string {\n    return JSON.stringify(uncast(value, r('ContextClearedEvent')), null, 2);\n  }\n\n  public static toContextListenerUnsubscribeRequest(json: string): ContextListenerUnsubscribeRequest {\n    return cast(JSON.parse(json), r('ContextListenerUnsubscribeRequest'));\n  }\n\n  public static contextListenerUnsubscribeRequestToJson(value: ContextListenerUnsubscribeRequest): string {\n    return JSON.stringify(uncast(value, r('ContextListenerUnsubscribeRequest')), null, 2);\n  }\n\n  public static toContextListenerUnsubscribeResponse(json: string): ContextListenerUnsubscribeResponse {\n    return cast(JSON.parse(json), r('ContextListenerUnsubscribeResponse'));\n  }\n\n  public static contextListenerUnsubscribeResponseToJson(value: ContextListenerUnsubscribeResponse): string {\n    return JSON.stringify(uncast(value, r('ContextListenerUnsubscribeResponse')), null, 2);\n  }\n\n  public static toCreatePrivateChannelRequest(json: string): CreatePrivateChannelRequest {\n    return cast(JSON.parse(json), r('CreatePrivateChannelRequest'));\n  }\n\n  public static createPrivateChannelRequestToJson(value: CreatePrivateChannelRequest): string {\n    return JSON.stringify(uncast(value, r('CreatePrivateChannelRequest')), null, 2);\n  }\n\n  public static toCreatePrivateChannelResponse(json: string): CreatePrivateChannelResponse {\n    return cast(JSON.parse(json), r('CreatePrivateChannelResponse'));\n  }\n\n  public static createPrivateChannelResponseToJson(value: CreatePrivateChannelResponse): string {\n    return JSON.stringify(uncast(value, r('CreatePrivateChannelResponse')), null, 2);\n  }\n\n  public static toEventListenerUnsubscribeRequest(json: string): EventListenerUnsubscribeRequest {\n    return cast(JSON.parse(json), r('EventListenerUnsubscribeRequest'));\n  }\n\n  public static eventListenerUnsubscribeRequestToJson(value: EventListenerUnsubscribeRequest): string {\n    return JSON.stringify(uncast(value, r('EventListenerUnsubscribeRequest')), null, 2);\n  }\n\n  public static toEventListenerUnsubscribeResponse(json: string): EventListenerUnsubscribeResponse {\n    return cast(JSON.parse(json), r('EventListenerUnsubscribeResponse'));\n  }\n\n  public static eventListenerUnsubscribeResponseToJson(value: EventListenerUnsubscribeResponse): string {\n    return JSON.stringify(uncast(value, r('EventListenerUnsubscribeResponse')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceChannelSelected(json: string): Fdc3UserInterfaceChannelSelected {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceChannelSelected'));\n  }\n\n  public static fdc3UserInterfaceChannelSelectedToJson(value: Fdc3UserInterfaceChannelSelected): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceChannelSelected')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceChannels(json: string): Fdc3UserInterfaceChannels {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceChannels'));\n  }\n\n  public static fdc3UserInterfaceChannelsToJson(value: Fdc3UserInterfaceChannels): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceChannels')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceDrag(json: string): Fdc3UserInterfaceDrag {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceDrag'));\n  }\n\n  public static fdc3UserInterfaceDragToJson(value: Fdc3UserInterfaceDrag): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceDrag')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceHandshake(json: string): Fdc3UserInterfaceHandshake {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceHandshake'));\n  }\n\n  public static fdc3UserInterfaceHandshakeToJson(value: Fdc3UserInterfaceHandshake): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceHandshake')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceHello(json: string): Fdc3UserInterfaceHello {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceHello'));\n  }\n\n  public static fdc3UserInterfaceHelloToJson(value: Fdc3UserInterfaceHello): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceHello')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceMessage(json: string): Fdc3UserInterfaceMessage {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceMessage'));\n  }\n\n  public static fdc3UserInterfaceMessageToJson(value: Fdc3UserInterfaceMessage): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceMessage')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceResolve(json: string): Fdc3UserInterfaceResolve {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceResolve'));\n  }\n\n  public static fdc3UserInterfaceResolveToJson(value: Fdc3UserInterfaceResolve): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceResolve')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceResolveAction(json: string): Fdc3UserInterfaceResolveAction {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceResolveAction'));\n  }\n\n  public static fdc3UserInterfaceResolveActionToJson(value: Fdc3UserInterfaceResolveAction): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceResolveAction')), null, 2);\n  }\n\n  public static toFdc3UserInterfaceRestyle(json: string): Fdc3UserInterfaceRestyle {\n    return cast(JSON.parse(json), r('Fdc3UserInterfaceRestyle'));\n  }\n\n  public static fdc3UserInterfaceRestyleToJson(value: Fdc3UserInterfaceRestyle): string {\n    return JSON.stringify(uncast(value, r('Fdc3UserInterfaceRestyle')), null, 2);\n  }\n\n  public static toFindInstancesRequest(json: string): FindInstancesRequest {\n    return cast(JSON.parse(json), r('FindInstancesRequest'));\n  }\n\n  public static findInstancesRequestToJson(value: FindInstancesRequest): string {\n    return JSON.stringify(uncast(value, r('FindInstancesRequest')), null, 2);\n  }\n\n  public static toFindInstancesResponse(json: string): FindInstancesResponse {\n    return cast(JSON.parse(json), r('FindInstancesResponse'));\n  }\n\n  public static findInstancesResponseToJson(value: FindInstancesResponse): string {\n    return JSON.stringify(uncast(value, r('FindInstancesResponse')), null, 2);\n  }\n\n  public static toFindIntentRequest(json: string): FindIntentRequest {\n    return cast(JSON.parse(json), r('FindIntentRequest'));\n  }\n\n  public static findIntentRequestToJson(value: FindIntentRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentRequest')), null, 2);\n  }\n\n  public static toFindIntentResponse(json: string): FindIntentResponse {\n    return cast(JSON.parse(json), r('FindIntentResponse'));\n  }\n\n  public static findIntentResponseToJson(value: FindIntentResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentResponse')), null, 2);\n  }\n\n  public static toFindIntentsByContextRequest(json: string): FindIntentsByContextRequest {\n    return cast(JSON.parse(json), r('FindIntentsByContextRequest'));\n  }\n\n  public static findIntentsByContextRequestToJson(value: FindIntentsByContextRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextRequest')), null, 2);\n  }\n\n  public static toFindIntentsByContextResponse(json: string): FindIntentsByContextResponse {\n    return cast(JSON.parse(json), r('FindIntentsByContextResponse'));\n  }\n\n  public static findIntentsByContextResponseToJson(value: FindIntentsByContextResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextResponse')), null, 2);\n  }\n\n  public static toGetAppMetadataRequest(json: string): GetAppMetadataRequest {\n    return cast(JSON.parse(json), r('GetAppMetadataRequest'));\n  }\n\n  public static getAppMetadataRequestToJson(value: GetAppMetadataRequest): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataRequest')), null, 2);\n  }\n\n  public static toGetAppMetadataResponse(json: string): GetAppMetadataResponse {\n    return cast(JSON.parse(json), r('GetAppMetadataResponse'));\n  }\n\n  public static getAppMetadataResponseToJson(value: GetAppMetadataResponse): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataResponse')), null, 2);\n  }\n\n  public static toGetCurrentChannelRequest(json: string): GetCurrentChannelRequest {\n    return cast(JSON.parse(json), r('GetCurrentChannelRequest'));\n  }\n\n  public static getCurrentChannelRequestToJson(value: GetCurrentChannelRequest): string {\n    return JSON.stringify(uncast(value, r('GetCurrentChannelRequest')), null, 2);\n  }\n\n  public static toGetCurrentChannelResponse(json: string): GetCurrentChannelResponse {\n    return cast(JSON.parse(json), r('GetCurrentChannelResponse'));\n  }\n\n  public static getCurrentChannelResponseToJson(value: GetCurrentChannelResponse): string {\n    return JSON.stringify(uncast(value, r('GetCurrentChannelResponse')), null, 2);\n  }\n\n  public static toGetCurrentContextRequest(json: string): GetCurrentContextRequest {\n    return cast(JSON.parse(json), r('GetCurrentContextRequest'));\n  }\n\n  public static getCurrentContextRequestToJson(value: GetCurrentContextRequest): string {\n    return JSON.stringify(uncast(value, r('GetCurrentContextRequest')), null, 2);\n  }\n\n  public static toGetCurrentContextResponse(json: string): GetCurrentContextResponse {\n    return cast(JSON.parse(json), r('GetCurrentContextResponse'));\n  }\n\n  public static getCurrentContextResponseToJson(value: GetCurrentContextResponse): string {\n    return JSON.stringify(uncast(value, r('GetCurrentContextResponse')), null, 2);\n  }\n\n  public static toGetInfoRequest(json: string): GetInfoRequest {\n    return cast(JSON.parse(json), r('GetInfoRequest'));\n  }\n\n  public static getInfoRequestToJson(value: GetInfoRequest): string {\n    return JSON.stringify(uncast(value, r('GetInfoRequest')), null, 2);\n  }\n\n  public static toGetInfoResponse(json: string): GetInfoResponse {\n    return cast(JSON.parse(json), r('GetInfoResponse'));\n  }\n\n  public static getInfoResponseToJson(value: GetInfoResponse): string {\n    return JSON.stringify(uncast(value, r('GetInfoResponse')), null, 2);\n  }\n\n  public static toGetOrCreateChannelRequest(json: string): GetOrCreateChannelRequest {\n    return cast(JSON.parse(json), r('GetOrCreateChannelRequest'));\n  }\n\n  public static getOrCreateChannelRequestToJson(value: GetOrCreateChannelRequest): string {\n    return JSON.stringify(uncast(value, r('GetOrCreateChannelRequest')), null, 2);\n  }\n\n  public static toGetOrCreateChannelResponse(json: string): GetOrCreateChannelResponse {\n    return cast(JSON.parse(json), r('GetOrCreateChannelResponse'));\n  }\n\n  public static getOrCreateChannelResponseToJson(value: GetOrCreateChannelResponse): string {\n    return JSON.stringify(uncast(value, r('GetOrCreateChannelResponse')), null, 2);\n  }\n\n  public static toGetUserChannelsRequest(json: string): GetUserChannelsRequest {\n    return cast(JSON.parse(json), r('GetUserChannelsRequest'));\n  }\n\n  public static getUserChannelsRequestToJson(value: GetUserChannelsRequest): string {\n    return JSON.stringify(uncast(value, r('GetUserChannelsRequest')), null, 2);\n  }\n\n  public static toGetUserChannelsResponse(json: string): GetUserChannelsResponse {\n    return cast(JSON.parse(json), r('GetUserChannelsResponse'));\n  }\n\n  public static getUserChannelsResponseToJson(value: GetUserChannelsResponse): string {\n    return JSON.stringify(uncast(value, r('GetUserChannelsResponse')), null, 2);\n  }\n\n  public static toHeartbeatAcknowledgementRequest(json: string): HeartbeatAcknowledgementRequest {\n    return cast(JSON.parse(json), r('HeartbeatAcknowledgementRequest'));\n  }\n\n  public static heartbeatAcknowledgementRequestToJson(value: HeartbeatAcknowledgementRequest): string {\n    return JSON.stringify(uncast(value, r('HeartbeatAcknowledgementRequest')), null, 2);\n  }\n\n  public static toHeartbeatEvent(json: string): HeartbeatEvent {\n    return cast(JSON.parse(json), r('HeartbeatEvent'));\n  }\n\n  public static heartbeatEventToJson(value: HeartbeatEvent): string {\n    return JSON.stringify(uncast(value, r('HeartbeatEvent')), null, 2);\n  }\n\n  public static toIntentEvent(json: string): IntentEvent {\n    return cast(JSON.parse(json), r('IntentEvent'));\n  }\n\n  public static intentEventToJson(value: IntentEvent): string {\n    return JSON.stringify(uncast(value, r('IntentEvent')), null, 2);\n  }\n\n  public static toIntentListenerUnsubscribeRequest(json: string): IntentListenerUnsubscribeRequest {\n    return cast(JSON.parse(json), r('IntentListenerUnsubscribeRequest'));\n  }\n\n  public static intentListenerUnsubscribeRequestToJson(value: IntentListenerUnsubscribeRequest): string {\n    return JSON.stringify(uncast(value, r('IntentListenerUnsubscribeRequest')), null, 2);\n  }\n\n  public static toIntentListenerUnsubscribeResponse(json: string): IntentListenerUnsubscribeResponse {\n    return cast(JSON.parse(json), r('IntentListenerUnsubscribeResponse'));\n  }\n\n  public static intentListenerUnsubscribeResponseToJson(value: IntentListenerUnsubscribeResponse): string {\n    return JSON.stringify(uncast(value, r('IntentListenerUnsubscribeResponse')), null, 2);\n  }\n\n  public static toIntentResultRequest(json: string): IntentResultRequest {\n    return cast(JSON.parse(json), r('IntentResultRequest'));\n  }\n\n  public static intentResultRequestToJson(value: IntentResultRequest): string {\n    return JSON.stringify(uncast(value, r('IntentResultRequest')), null, 2);\n  }\n\n  public static toIntentResultResponse(json: string): IntentResultResponse {\n    return cast(JSON.parse(json), r('IntentResultResponse'));\n  }\n\n  public static intentResultResponseToJson(value: IntentResultResponse): string {\n    return JSON.stringify(uncast(value, r('IntentResultResponse')), null, 2);\n  }\n\n  public static toJoinUserChannelRequest(json: string): JoinUserChannelRequest {\n    return cast(JSON.parse(json), r('JoinUserChannelRequest'));\n  }\n\n  public static joinUserChannelRequestToJson(value: JoinUserChannelRequest): string {\n    return JSON.stringify(uncast(value, r('JoinUserChannelRequest')), null, 2);\n  }\n\n  public static toJoinUserChannelResponse(json: string): JoinUserChannelResponse {\n    return cast(JSON.parse(json), r('JoinUserChannelResponse'));\n  }\n\n  public static joinUserChannelResponseToJson(value: JoinUserChannelResponse): string {\n    return JSON.stringify(uncast(value, r('JoinUserChannelResponse')), null, 2);\n  }\n\n  public static toLeaveCurrentChannelRequest(json: string): LeaveCurrentChannelRequest {\n    return cast(JSON.parse(json), r('LeaveCurrentChannelRequest'));\n  }\n\n  public static leaveCurrentChannelRequestToJson(value: LeaveCurrentChannelRequest): string {\n    return JSON.stringify(uncast(value, r('LeaveCurrentChannelRequest')), null, 2);\n  }\n\n  public static toLeaveCurrentChannelResponse(json: string): LeaveCurrentChannelResponse {\n    return cast(JSON.parse(json), r('LeaveCurrentChannelResponse'));\n  }\n\n  public static leaveCurrentChannelResponseToJson(value: LeaveCurrentChannelResponse): string {\n    return JSON.stringify(uncast(value, r('LeaveCurrentChannelResponse')), null, 2);\n  }\n\n  public static toOpenRequest(json: string): OpenRequest {\n    return cast(JSON.parse(json), r('OpenRequest'));\n  }\n\n  public static openRequestToJson(value: OpenRequest): string {\n    return JSON.stringify(uncast(value, r('OpenRequest')), null, 2);\n  }\n\n  public static toOpenResponse(json: string): OpenResponse {\n    return cast(JSON.parse(json), r('OpenResponse'));\n  }\n\n  public static openResponseToJson(value: OpenResponse): string {\n    return JSON.stringify(uncast(value, r('OpenResponse')), null, 2);\n  }\n\n  public static toPrivateChannelAddEventListenerRequest(json: string): PrivateChannelAddEventListenerRequest {\n    return cast(JSON.parse(json), r('PrivateChannelAddEventListenerRequest'));\n  }\n\n  public static privateChannelAddEventListenerRequestToJson(value: PrivateChannelAddEventListenerRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelAddEventListenerRequest')), null, 2);\n  }\n\n  public static toPrivateChannelAddEventListenerResponse(json: string): PrivateChannelAddEventListenerResponse {\n    return cast(JSON.parse(json), r('PrivateChannelAddEventListenerResponse'));\n  }\n\n  public static privateChannelAddEventListenerResponseToJson(value: PrivateChannelAddEventListenerResponse): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelAddEventListenerResponse')), null, 2);\n  }\n\n  public static toPrivateChannelDisconnectRequest(json: string): PrivateChannelDisconnectRequest {\n    return cast(JSON.parse(json), r('PrivateChannelDisconnectRequest'));\n  }\n\n  public static privateChannelDisconnectRequestToJson(value: PrivateChannelDisconnectRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelDisconnectRequest')), null, 2);\n  }\n\n  public static toPrivateChannelDisconnectResponse(json: string): PrivateChannelDisconnectResponse {\n    return cast(JSON.parse(json), r('PrivateChannelDisconnectResponse'));\n  }\n\n  public static privateChannelDisconnectResponseToJson(value: PrivateChannelDisconnectResponse): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelDisconnectResponse')), null, 2);\n  }\n\n  public static toPrivateChannelOnAddContextListenerEvent(json: string): PrivateChannelOnAddContextListenerEvent {\n    return cast(JSON.parse(json), r('PrivateChannelOnAddContextListenerEvent'));\n  }\n\n  public static privateChannelOnAddContextListenerEventToJson(value: PrivateChannelOnAddContextListenerEvent): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnAddContextListenerEvent')), null, 2);\n  }\n\n  public static toPrivateChannelOnDisconnectEvent(json: string): PrivateChannelOnDisconnectEvent {\n    return cast(JSON.parse(json), r('PrivateChannelOnDisconnectEvent'));\n  }\n\n  public static privateChannelOnDisconnectEventToJson(value: PrivateChannelOnDisconnectEvent): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnDisconnectEvent')), null, 2);\n  }\n\n  public static toPrivateChannelOnUnsubscribeEvent(json: string): PrivateChannelOnUnsubscribeEvent {\n    return cast(JSON.parse(json), r('PrivateChannelOnUnsubscribeEvent'));\n  }\n\n  public static privateChannelOnUnsubscribeEventToJson(value: PrivateChannelOnUnsubscribeEvent): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnUnsubscribeEvent')), null, 2);\n  }\n\n  public static toPrivateChannelUnsubscribeEventListenerRequest(\n    json: string\n  ): PrivateChannelUnsubscribeEventListenerRequest {\n    return cast(JSON.parse(json), r('PrivateChannelUnsubscribeEventListenerRequest'));\n  }\n\n  public static privateChannelUnsubscribeEventListenerRequestToJson(\n    value: PrivateChannelUnsubscribeEventListenerRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelUnsubscribeEventListenerRequest')), null, 2);\n  }\n\n  public static toPrivateChannelUnsubscribeEventListenerResponse(\n    json: string\n  ): PrivateChannelUnsubscribeEventListenerResponse {\n    return cast(JSON.parse(json), r('PrivateChannelUnsubscribeEventListenerResponse'));\n  }\n\n  public static privateChannelUnsubscribeEventListenerResponseToJson(\n    value: PrivateChannelUnsubscribeEventListenerResponse\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelUnsubscribeEventListenerResponse')), null, 2);\n  }\n\n  public static toRaiseIntentForContextRequest(json: string): RaiseIntentForContextRequest {\n    return cast(JSON.parse(json), r('RaiseIntentForContextRequest'));\n  }\n\n  public static raiseIntentForContextRequestToJson(value: RaiseIntentForContextRequest): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentForContextRequest')), null, 2);\n  }\n\n  public static toRaiseIntentForContextResponse(json: string): RaiseIntentForContextResponse {\n    return cast(JSON.parse(json), r('RaiseIntentForContextResponse'));\n  }\n\n  public static raiseIntentForContextResponseToJson(value: RaiseIntentForContextResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentForContextResponse')), null, 2);\n  }\n\n  public static toRaiseIntentRequest(json: string): RaiseIntentRequest {\n    return cast(JSON.parse(json), r('RaiseIntentRequest'));\n  }\n\n  public static raiseIntentRequestToJson(value: RaiseIntentRequest): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentRequest')), null, 2);\n  }\n\n  public static toRaiseIntentResponse(json: string): RaiseIntentResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResponse'));\n  }\n\n  public static raiseIntentResponseToJson(value: RaiseIntentResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResponse')), null, 2);\n  }\n\n  public static toRaiseIntentResultResponse(json: string): RaiseIntentResultResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResultResponse'));\n  }\n\n  public static raiseIntentResultResponseToJson(value: RaiseIntentResultResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResultResponse')), null, 2);\n  }\n}\n\nfunction invalidValue(typ: any, val: any, key: any, parent: any = ''): never {\n  const prettyTyp = prettyTypeName(typ);\n  const parentText = parent ? ` on ${parent}` : '';\n  const keyText = key ? ` for key \"${key}\"` : '';\n  throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);\n}\n\nfunction prettyTypeName(typ: any): string {\n  if (Array.isArray(typ)) {\n    if (typ.length === 2 && typ[0] === undefined) {\n      return `an optional ${prettyTypeName(typ[1])}`;\n    } else {\n      return `one of [${typ\n        .map(a => {\n          return prettyTypeName(a);\n        })\n        .join(', ')}]`;\n    }\n  } else if (typeof typ === 'object' && typ.literal !== undefined) {\n    return typ.literal;\n  } else {\n    return typeof typ;\n  }\n}\n\nfunction jsonToJSProps(typ: any): any {\n  if (typ.jsonToJS === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.json] = { key: p.js, typ: p.typ }));\n    typ.jsonToJS = map;\n  }\n  return typ.jsonToJS;\n}\n\nfunction jsToJSONProps(typ: any): any {\n  if (typ.jsToJSON === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.js] = { key: p.json, typ: p.typ }));\n    typ.jsToJSON = map;\n  }\n  return typ.jsToJSON;\n}\n\nfunction transform(val: any, typ: any, getProps: any, key: any = '', parent: any = ''): any {\n  function transformPrimitive(typ: string, val: any): any {\n    if (typeof typ === typeof val) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n\n  function transformUnion(typs: any[], val: any): any {\n    // val must validate against one typ in typs\n    const l = typs.length;\n    for (let i = 0; i < l; i++) {\n      const typ = typs[i];\n      try {\n        return transform(val, typ, getProps);\n      } catch (_) {}\n    }\n    return invalidValue(typs, val, key, parent);\n  }\n\n  function transformEnum(cases: string[], val: any): any {\n    if (cases.indexOf(val) !== -1) return val;\n    return invalidValue(\n      cases.map(a => {\n        return l(a);\n      }),\n      val,\n      key,\n      parent\n    );\n  }\n\n  function transformArray(typ: any, val: any): any {\n    // val must be an array with no invalid elements\n    if (!Array.isArray(val)) return invalidValue(l('array'), val, key, parent);\n    return val.map(el => transform(el, typ, getProps));\n  }\n\n  function transformDate(val: any): any {\n    if (val === null) {\n      return null;\n    }\n    const d = new Date(val);\n    if (isNaN(d.valueOf())) {\n      return invalidValue(l('Date'), val, key, parent);\n    }\n    return d;\n  }\n\n  function transformObject(props: { [k: string]: any }, additional: any, val: any): any {\n    if (val === null || typeof val !== 'object' || Array.isArray(val)) {\n      return invalidValue(l(ref || 'object'), val, key, parent);\n    }\n    const result: any = {};\n    Object.getOwnPropertyNames(props).forEach(key => {\n      const prop = props[key];\n      const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;\n      result[prop.key] = transform(v, prop.typ, getProps, key, ref);\n    });\n    Object.getOwnPropertyNames(val).forEach(key => {\n      if (!Object.prototype.hasOwnProperty.call(props, key)) {\n        result[key] = transform(val[key], additional, getProps, key, ref);\n      }\n    });\n    return result;\n  }\n\n  if (typ === 'any') return val;\n  if (typ === null) {\n    if (val === null) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n  if (typ === false) return invalidValue(typ, val, key, parent);\n  let ref: any = undefined;\n  while (typeof typ === 'object' && typ.ref !== undefined) {\n    ref = typ.ref;\n    typ = typeMap[typ.ref];\n  }\n  if (Array.isArray(typ)) return transformEnum(typ, val);\n  if (typeof typ === 'object') {\n    return typ.hasOwnProperty('unionMembers')\n      ? transformUnion(typ.unionMembers, val)\n      : typ.hasOwnProperty('arrayItems')\n        ? transformArray(typ.arrayItems, val)\n        : typ.hasOwnProperty('props')\n          ? transformObject(getProps(typ), typ.additional, val)\n          : invalidValue(typ, val, key, parent);\n  }\n  // Numbers can be parsed by Date but shouldn't be.\n  if (typ === Date && typeof val !== 'number') return transformDate(val);\n  return transformPrimitive(typ, val);\n}\n\nfunction cast<T>(val: any, typ: any): T {\n  return transform(val, typ, jsonToJSProps);\n}\n\nfunction uncast<T>(val: T, typ: any): any {\n  return transform(val, typ, jsToJSONProps);\n}\n\nfunction l(typ: any) {\n  return { literal: typ };\n}\n\nfunction a(typ: any) {\n  return { arrayItems: typ };\n}\n\nfunction u(...typs: any[]) {\n  return { unionMembers: typs };\n}\n\nfunction o(props: any[], additional: any) {\n  return { props, additional };\n}\n\nfunction m(additional: any) {\n  return { props: [], additional };\n}\n\nfunction r(name: string) {\n  return { ref: name };\n}\n\nconst typeMap: any = {\n  WebConnectionProtocol1Hello: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol1HelloPayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol1HelloType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol1HelloMeta: o(\n    [\n      { json: 'connectionAttemptUuid', js: 'connectionAttemptUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  WebConnectionProtocol1HelloPayload: o(\n    [\n      { json: 'actualUrl', js: 'actualUrl', typ: '' },\n      { json: 'channelSelector', js: 'channelSelector', typ: u(undefined, true) },\n      { json: 'fdc3Version', js: 'fdc3Version', typ: '' },\n      { json: 'identityUrl', js: 'identityUrl', typ: '' },\n      { json: 'intentResolver', js: 'intentResolver', typ: u(undefined, true) },\n    ],\n    false\n  ),\n  WebConnectionProtocol2LoadURL: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol2LoadURLPayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol2LoadURLType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol2LoadURLPayload: o([{ json: 'iframeUrl', js: 'iframeUrl', typ: '' }], false),\n  WebConnectionProtocol3Handshake: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol3HandshakePayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol3HandshakeType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol3HandshakePayload: o(\n    [\n      { json: 'appLaunchTimeout', js: 'appLaunchTimeout', typ: u(undefined, 3.14) },\n      { json: 'channelSelectorUrl', js: 'channelSelectorUrl', typ: u(true, '') },\n      { json: 'fdc3Version', js: 'fdc3Version', typ: '' },\n      { json: 'intentResolverUrl', js: 'intentResolverUrl', typ: u(true, '') },\n      { json: 'messageExchangeTimeout', js: 'messageExchangeTimeout', typ: u(undefined, 3.14) },\n    ],\n    false\n  ),\n  WebConnectionProtocol4ValidateAppIdentity: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol4ValidateAppIdentityPayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol4ValidateAppIdentityType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol4ValidateAppIdentityPayload: o(\n    [\n      { json: 'actualUrl', js: 'actualUrl', typ: '' },\n      { json: 'identityUrl', js: 'identityUrl', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n      { json: 'instanceUuid', js: 'instanceUuid', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  WebConnectionProtocol5ValidateAppIdentityFailedResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol5ValidateAppIdentityFailedResponsePayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol5ValidateAppIdentityFailedResponseType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol5ValidateAppIdentityFailedResponsePayload: o(\n    [{ json: 'message', js: 'message', typ: u(undefined, '') }],\n    false\n  ),\n  WebConnectionProtocol5ValidateAppIdentitySuccessResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol1HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('WebConnectionProtocol5ValidateAppIdentitySuccessResponsePayload') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol5ValidateAppIdentitySuccessResponseType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol5ValidateAppIdentitySuccessResponsePayload: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'implementationMetadata', js: 'implementationMetadata', typ: r('ImplementationMetadata') },\n      { json: 'instanceId', js: 'instanceId', typ: '' },\n      { json: 'instanceUuid', js: 'instanceUuid', typ: '' },\n    ],\n    false\n  ),\n  ImplementationMetadata: o(\n    [\n      { json: 'appMetadata', js: 'appMetadata', typ: r('AppMetadata') },\n      { json: 'fdc3Version', js: 'fdc3Version', typ: '' },\n      { json: 'optionalFeatures', js: 'optionalFeatures', typ: r('OptionalFeatures') },\n      { json: 'provider', js: 'provider', typ: '' },\n      { json: 'providerVersion', js: 'providerVersion', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  AppMetadata: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'description', js: 'description', typ: u(undefined, '') },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'icons', js: 'icons', typ: u(undefined, a(r('Icon'))) },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n      { json: 'instanceMetadata', js: 'instanceMetadata', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, u(null, '')) },\n      { json: 'screenshots', js: 'screenshots', typ: u(undefined, a(r('Image'))) },\n      { json: 'title', js: 'title', typ: u(undefined, '') },\n      { json: 'tooltip', js: 'tooltip', typ: u(undefined, '') },\n      { json: 'version', js: 'version', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  Icon: o(\n    [\n      { json: 'size', js: 'size', typ: u(undefined, '') },\n      { json: 'src', js: 'src', typ: '' },\n      { json: 'type', js: 'type', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  Image: o(\n    [\n      { json: 'label', js: 'label', typ: u(undefined, '') },\n      { json: 'size', js: 'size', typ: u(undefined, '') },\n      { json: 'src', js: 'src', typ: '' },\n      { json: 'type', js: 'type', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  OptionalFeatures: o(\n    [\n      { json: 'DesktopAgentBridging', js: 'DesktopAgentBridging', typ: true },\n      { json: 'OriginatingAppMetadata', js: 'OriginatingAppMetadata', typ: true },\n      { json: 'UserChannelMembershipAPIs', js: 'UserChannelMembershipAPIs', typ: true },\n    ],\n    false\n  ),\n  WebConnectionProtocol6Goodbye: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('WebConnectionProtocol6GoodbyeMeta') },\n      { json: 'type', js: 'type', typ: r('WebConnectionProtocol6GoodbyeType') },\n    ],\n    false\n  ),\n  WebConnectionProtocol6GoodbyeMeta: o([{ json: 'timestamp', js: 'timestamp', typ: Date }], false),\n  WebConnectionProtocolMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStepMetadata') },\n      { json: 'payload', js: 'payload', typ: u(undefined, m('any')) },\n      { json: 'type', js: 'type', typ: r('ConnectionStepMessageType') },\n    ],\n    false\n  ),\n  ConnectionStepMetadata: o(\n    [\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n      { json: 'connectionAttemptUuid', js: 'connectionAttemptUuid', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  AddContextListenerRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('AddContextListenerRequestPayload') },\n      { json: 'type', js: 'type', typ: r('AddContextListenerRequestType') },\n    ],\n    false\n  ),\n  AddContextListenerRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  AppIdentifier: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  AddContextListenerRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: u(null, '') },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  AddContextListenerResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('AddContextListenerResponsePayload') },\n      { json: 'type', js: 'type', typ: r('AddContextListenerResponseType') },\n    ],\n    false\n  ),\n  AddContextListenerResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  AddContextListenerResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'listenerUUID', js: 'listenerUUID', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  AddEventListenerRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('AddEventListenerRequestPayload') },\n      { json: 'type', js: 'type', typ: r('AddEventListenerRequestType') },\n    ],\n    false\n  ),\n  AddEventListenerRequestPayload: o([{ json: 'type', js: 'type', typ: u(r('FDC3EventType'), null) }], false),\n  AddEventListenerResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('AddEventListenerResponsePayload') },\n      { json: 'type', js: 'type', typ: r('AddEventListenerResponseType') },\n    ],\n    false\n  ),\n  AddEventListenerResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) },\n      { json: 'listenerUUID', js: 'listenerUUID', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  AddIntentListenerRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('AddIntentListenerRequestPayload') },\n      { json: 'type', js: 'type', typ: r('AddIntentListenerRequestType') },\n    ],\n    false\n  ),\n  AddIntentListenerRequestPayload: o([{ json: 'intent', js: 'intent', typ: '' }], false),\n  AddIntentListenerResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('PayloadObject') },\n      { json: 'type', js: 'type', typ: r('AddIntentListenerResponseType') },\n    ],\n    false\n  ),\n  PayloadObject: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FluffyError')) },\n      { json: 'listenerUUID', js: 'listenerUUID', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  AgentEventMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentEventMessageMeta') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: r('EventMessageType') },\n    ],\n    false\n  ),\n  AgentEventMessageMeta: o(\n    [\n      { json: 'eventUuid', js: 'eventUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  AgentResponseMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentResponseMessageMeta') },\n      { json: 'payload', js: 'payload', typ: r('AgentResponseMessageResponsePayload') },\n      { json: 'type', js: 'type', typ: r('ResponseMessageType') },\n    ],\n    false\n  ),\n  AgentResponseMessageMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  AgentResponseMessageResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) }],\n    'any'\n  ),\n  AppRequestMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AppRequestMessageMeta') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: r('RequestMessageType') },\n    ],\n    false\n  ),\n  AppRequestMessageMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  BroadcastEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastEventPayload') },\n      { json: 'type', js: 'type', typ: r('BroadcastEventType') },\n    ],\n    false\n  ),\n  BroadcastEventMeta: o(\n    [\n      { json: 'eventUuid', js: 'eventUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  BroadcastEventPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: u(null, '') },\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'originatingApp', js: 'originatingApp', typ: u(undefined, r('AppIdentifier')) },\n    ],\n    false\n  ),\n  Context: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    'any'\n  ),\n  BroadcastRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastRequestPayload') },\n      { json: 'type', js: 'type', typ: r('BroadcastRequestType') },\n    ],\n    false\n  ),\n  BroadcastRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  BroadcastResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('BroadcastResponseType') },\n    ],\n    false\n  ),\n  BroadcastResponseResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) }],\n    'any'\n  ),\n  ChannelChangedEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('ChannelChangedEventPayload') },\n      { json: 'type', js: 'type', typ: r('ChannelChangedEventType') },\n    ],\n    false\n  ),\n  ChannelChangedEventPayload: o(\n    [\n      { json: 'newChannelId', js: 'newChannelId', typ: u(undefined, u(null, '')) },\n      { json: 'currentChannelId', js: 'currentChannelId', typ: u(undefined, u(null, '')) },\n    ],\n    false\n  ),\n  ClearContextRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('ClearContextRequestPayload') },\n      { json: 'type', js: 'type', typ: r('ClearContextRequestType') },\n    ],\n    false\n  ),\n  ClearContextRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  ClearContextResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('ClearContextResponseType') },\n    ],\n    false\n  ),\n  ContextClearedEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('ContextClearedEventPayload') },\n      { json: 'type', js: 'type', typ: r('ContextClearedEventType') },\n    ],\n    false\n  ),\n  ContextClearedEventPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: u(null, '') },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  ContextListenerUnsubscribeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('ContextListenerUnsubscribeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('ContextListenerUnsubscribeRequestType') },\n    ],\n    false\n  ),\n  ContextListenerUnsubscribeRequestPayload: o([{ json: 'listenerUUID', js: 'listenerUUID', typ: '' }], false),\n  ContextListenerUnsubscribeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('ContextListenerUnsubscribeResponseType') },\n    ],\n    false\n  ),\n  CreatePrivateChannelRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('CreatePrivateChannelRequestPayload') },\n      { json: 'type', js: 'type', typ: r('CreatePrivateChannelRequestType') },\n    ],\n    false\n  ),\n  CreatePrivateChannelRequestPayload: o([], false),\n  CreatePrivateChannelResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('CreatePrivateChannelResponsePayload') },\n      { json: 'type', js: 'type', typ: r('CreatePrivateChannelResponseType') },\n    ],\n    false\n  ),\n  CreatePrivateChannelResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'privateChannel', js: 'privateChannel', typ: u(undefined, r('Channel')) },\n    ],\n    false\n  ),\n  Channel: o(\n    [\n      { json: 'displayMetadata', js: 'displayMetadata', typ: u(undefined, r('DisplayMetadata')) },\n      { json: 'id', js: 'id', typ: '' },\n      { json: 'type', js: 'type', typ: r('Type') },\n    ],\n    false\n  ),\n  DisplayMetadata: o(\n    [\n      { json: 'color', js: 'color', typ: u(undefined, '') },\n      { json: 'glyph', js: 'glyph', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  EventListenerUnsubscribeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('EventListenerUnsubscribeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('EventListenerUnsubscribeRequestType') },\n    ],\n    false\n  ),\n  EventListenerUnsubscribeRequestPayload: o([{ json: 'listenerUUID', js: 'listenerUUID', typ: '' }], false),\n  EventListenerUnsubscribeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('EventListenerUnsubscribeResponseType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceChannelSelected: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceChannelSelectedPayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceChannelSelectedType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceChannelSelectedPayload: o([{ json: 'selected', js: 'selected', typ: u(null, '') }], false),\n  Fdc3UserInterfaceChannels: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceChannelsPayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceChannelsType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceChannelsPayload: o(\n    [\n      { json: 'selected', js: 'selected', typ: u(null, '') },\n      { json: 'userChannels', js: 'userChannels', typ: a(r('Channel')) },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceDrag: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceDragPayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceDragType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceDragPayload: o([{ json: 'mouseOffsets', js: 'mouseOffsets', typ: r('MouseOffsets') }], false),\n  MouseOffsets: o(\n    [\n      { json: 'x', js: 'x', typ: 0 },\n      { json: 'y', js: 'y', typ: 0 },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceHandshake: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceHandshakePayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceHandshakeType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceHandshakePayload: o([{ json: 'fdc3Version', js: 'fdc3Version', typ: '' }], false),\n  Fdc3UserInterfaceHello: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceHelloPayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceHelloType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceHelloPayload: o(\n    [\n      { json: 'implementationDetails', js: 'implementationDetails', typ: '' },\n      { json: 'initialCSS', js: 'initialCSS', typ: r('InitialCSS') },\n    ],\n    false\n  ),\n  InitialCSS: o(\n    [\n      { json: 'bottom', js: 'bottom', typ: u(undefined, '') },\n      { json: 'height', js: 'height', typ: u(undefined, '') },\n      { json: 'left', js: 'left', typ: u(undefined, '') },\n      { json: 'maxHeight', js: 'maxHeight', typ: u(undefined, '') },\n      { json: 'maxWidth', js: 'maxWidth', typ: u(undefined, '') },\n      { json: 'right', js: 'right', typ: u(undefined, '') },\n      { json: 'top', js: 'top', typ: u(undefined, '') },\n      { json: 'transition', js: 'transition', typ: u(undefined, '') },\n      { json: 'width', js: 'width', typ: u(undefined, '') },\n      { json: 'zIndex', js: 'zIndex', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  Fdc3UserInterfaceMessage: o(\n    [\n      { json: 'payload', js: 'payload', typ: u(undefined, m('any')) },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceMessageType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceResolve: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceResolvePayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceResolveType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceResolvePayload: o(\n    [\n      { json: 'appIntents', js: 'appIntents', typ: a(r('AppIntent')) },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  AppIntent: o(\n    [\n      { json: 'apps', js: 'apps', typ: a(r('AppMetadata')) },\n      { json: 'intent', js: 'intent', typ: r('IntentMetadata') },\n    ],\n    false\n  ),\n  IntentMetadata: o(\n    [\n      { json: 'displayName', js: 'displayName', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: '' },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceResolveAction: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceResolveActionPayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceResolveActionType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceResolveActionPayload: o(\n    [\n      { json: 'action', js: 'action', typ: r('Action') },\n      { json: 'appIdentifier', js: 'appIdentifier', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'intent', js: 'intent', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceRestyle: o(\n    [\n      { json: 'payload', js: 'payload', typ: r('Fdc3UserInterfaceRestylePayload') },\n      { json: 'type', js: 'type', typ: r('Fdc3UserInterfaceRestyleType') },\n    ],\n    false\n  ),\n  Fdc3UserInterfaceRestylePayload: o([{ json: 'updatedCSS', js: 'updatedCSS', typ: r('UpdatedCSS') }], false),\n  UpdatedCSS: o(\n    [\n      { json: 'bottom', js: 'bottom', typ: u(undefined, '') },\n      { json: 'height', js: 'height', typ: u(undefined, '') },\n      { json: 'left', js: 'left', typ: u(undefined, '') },\n      { json: 'maxHeight', js: 'maxHeight', typ: u(undefined, '') },\n      { json: 'maxWidth', js: 'maxWidth', typ: u(undefined, '') },\n      { json: 'right', js: 'right', typ: u(undefined, '') },\n      { json: 'top', js: 'top', typ: u(undefined, '') },\n      { json: 'transition', js: 'transition', typ: u(undefined, '') },\n      { json: 'width', js: 'width', typ: u(undefined, '') },\n      { json: 'zIndex', js: 'zIndex', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FindInstancesRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesRequestType') },\n    ],\n    false\n  ),\n  FindInstancesRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppIdentifier') }], false),\n  FindInstancesResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesResponseType') },\n    ],\n    false\n  ),\n  FindInstancesResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'appIdentifiers', js: 'appIdentifiers', typ: u(undefined, a(r('AppMetadata'))) },\n    ],\n    false\n  ),\n  FindIntentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentRequestType') },\n    ],\n    false\n  ),\n  FindIntentRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentResponseType') },\n    ],\n    false\n  ),\n  FindIntentResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'appIntent', js: 'appIntent', typ: u(undefined, r('AppIntent')) },\n    ],\n    false\n  ),\n  FindIntentsByContextRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextRequestType') },\n    ],\n    false\n  ),\n  FindIntentsByContextRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentsByContextResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextResponseType') },\n    ],\n    false\n  ),\n  FindIntentsByContextResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'appIntents', js: 'appIntents', typ: u(undefined, a(r('AppIntent'))) },\n    ],\n    false\n  ),\n  GetAppMetadataRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataRequestType') },\n    ],\n    false\n  ),\n  GetAppMetadataRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppIdentifier') }], false),\n  GetAppMetadataResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataResponseType') },\n    ],\n    false\n  ),\n  GetAppMetadataResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'appMetadata', js: 'appMetadata', typ: u(undefined, r('AppMetadata')) },\n    ],\n    false\n  ),\n  GetCurrentChannelRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetCurrentChannelRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetCurrentChannelRequestType') },\n    ],\n    false\n  ),\n  GetCurrentChannelRequestPayload: o([], false),\n  GetCurrentChannelResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetCurrentChannelResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetCurrentChannelResponseType') },\n    ],\n    false\n  ),\n  GetCurrentChannelResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) },\n      { json: 'channel', js: 'channel', typ: u(undefined, u(r('Channel'), null)) },\n    ],\n    false\n  ),\n  GetCurrentContextRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetCurrentContextRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetCurrentContextRequestType') },\n    ],\n    false\n  ),\n  GetCurrentContextRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  GetCurrentContextResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetCurrentContextResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetCurrentContextResponseType') },\n    ],\n    false\n  ),\n  GetCurrentContextResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'context', js: 'context', typ: u(undefined, u(null, r('Context'))) },\n    ],\n    false\n  ),\n  GetInfoRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetInfoRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetInfoRequestType') },\n    ],\n    false\n  ),\n  GetInfoRequestPayload: o([], false),\n  GetInfoResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetInfoResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetInfoResponseType') },\n    ],\n    false\n  ),\n  GetInfoResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) },\n      { json: 'implementationMetadata', js: 'implementationMetadata', typ: u(undefined, r('ImplementationMetadata')) },\n    ],\n    false\n  ),\n  GetOrCreateChannelRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetOrCreateChannelRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetOrCreateChannelRequestType') },\n    ],\n    false\n  ),\n  GetOrCreateChannelRequestPayload: o([{ json: 'channelId', js: 'channelId', typ: '' }], false),\n  GetOrCreateChannelResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetOrCreateChannelResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetOrCreateChannelResponseType') },\n    ],\n    false\n  ),\n  GetOrCreateChannelResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'channel', js: 'channel', typ: u(undefined, r('Channel')) },\n    ],\n    false\n  ),\n  GetUserChannelsRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetUserChannelsRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetUserChannelsRequestType') },\n    ],\n    false\n  ),\n  GetUserChannelsRequestPayload: o([], false),\n  GetUserChannelsResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetUserChannelsResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetUserChannelsResponseType') },\n    ],\n    false\n  ),\n  GetUserChannelsResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'userChannels', js: 'userChannels', typ: u(undefined, a(r('Channel'))) },\n    ],\n    false\n  ),\n  HeartbeatAcknowledgementRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('HeartbeatAcknowledgementRequestPayload') },\n      { json: 'type', js: 'type', typ: r('HeartbeatAcknowledgementRequestType') },\n    ],\n    false\n  ),\n  HeartbeatAcknowledgementRequestPayload: o([{ json: 'heartbeatEventUuid', js: 'heartbeatEventUuid', typ: '' }], false),\n  HeartbeatEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('HeartbeatEventPayload') },\n      { json: 'type', js: 'type', typ: r('HeartbeatEventType') },\n    ],\n    false\n  ),\n  HeartbeatEventPayload: o([], false),\n  IntentEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('IntentEventPayload') },\n      { json: 'type', js: 'type', typ: r('IntentEventType') },\n    ],\n    false\n  ),\n  IntentEventPayload: o(\n    [\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'originatingApp', js: 'originatingApp', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'raiseIntentRequestUuid', js: 'raiseIntentRequestUuid', typ: '' },\n    ],\n    false\n  ),\n  IntentListenerUnsubscribeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('IntentListenerUnsubscribeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('IntentListenerUnsubscribeRequestType') },\n    ],\n    false\n  ),\n  IntentListenerUnsubscribeRequestPayload: o([{ json: 'listenerUUID', js: 'listenerUUID', typ: '' }], false),\n  IntentListenerUnsubscribeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('IntentListenerUnsubscribeResponseType') },\n    ],\n    false\n  ),\n  IntentResultRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('IntentResultRequestPayload') },\n      { json: 'type', js: 'type', typ: r('IntentResultRequestType') },\n    ],\n    false\n  ),\n  IntentResultRequestPayload: o(\n    [\n      { json: 'intentEventUuid', js: 'intentEventUuid', typ: '' },\n      { json: 'intentResult', js: 'intentResult', typ: r('IntentResult') },\n      { json: 'raiseIntentRequestUuid', js: 'raiseIntentRequestUuid', typ: '' },\n    ],\n    false\n  ),\n  IntentResult: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n      { json: 'channel', js: 'channel', typ: u(undefined, r('Channel')) },\n    ],\n    false\n  ),\n  IntentResultResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('IntentResultResponseType') },\n    ],\n    false\n  ),\n  JoinUserChannelRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('JoinUserChannelRequestPayload') },\n      { json: 'type', js: 'type', typ: r('JoinUserChannelRequestType') },\n    ],\n    false\n  ),\n  JoinUserChannelRequestPayload: o([{ json: 'channelId', js: 'channelId', typ: '' }], false),\n  JoinUserChannelResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('JoinUserChannelResponsePayload') },\n      { json: 'type', js: 'type', typ: r('JoinUserChannelResponseType') },\n    ],\n    false\n  ),\n  JoinUserChannelResponsePayload: o([{ json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) }], false),\n  LeaveCurrentChannelRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('LeaveCurrentChannelRequestPayload') },\n      { json: 'type', js: 'type', typ: r('LeaveCurrentChannelRequestType') },\n    ],\n    false\n  ),\n  LeaveCurrentChannelRequestPayload: o([], false),\n  LeaveCurrentChannelResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('LeaveCurrentChannelResponsePayload') },\n      { json: 'type', js: 'type', typ: r('LeaveCurrentChannelResponseType') },\n    ],\n    false\n  ),\n  LeaveCurrentChannelResponsePayload: o([{ json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) }], false),\n  OpenRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenRequestPayload') },\n      { json: 'type', js: 'type', typ: r('OpenRequestType') },\n    ],\n    false\n  ),\n  OpenRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: r('AppIdentifier') },\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n    ],\n    false\n  ),\n  OpenResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenResponsePayload') },\n      { json: 'type', js: 'type', typ: r('OpenResponseType') },\n    ],\n    false\n  ),\n  OpenResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('OpenErrorResponsePayload')) },\n      { json: 'appIdentifier', js: 'appIdentifier', typ: u(undefined, r('AppIdentifier')) },\n    ],\n    false\n  ),\n  PrivateChannelAddEventListenerRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelAddEventListenerRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelAddEventListenerRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelAddEventListenerRequestPayload: o(\n    [\n      { json: 'listenerType', js: 'listenerType', typ: u(r('PrivateChannelEventType'), null) },\n      { json: 'privateChannelId', js: 'privateChannelId', typ: '' },\n    ],\n    false\n  ),\n  PrivateChannelAddEventListenerResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelAddEventListenerResponsePayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelAddEventListenerResponseType') },\n    ],\n    false\n  ),\n  PrivateChannelAddEventListenerResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) },\n      { json: 'listenerUUID', js: 'listenerUUID', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  PrivateChannelDisconnectRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelDisconnectRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelDisconnectRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelDisconnectRequestPayload: o([{ json: 'channelId', js: 'channelId', typ: '' }], false),\n  PrivateChannelDisconnectResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelDisconnectResponsePayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelDisconnectResponseType') },\n    ],\n    false\n  ),\n  PrivateChannelDisconnectResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: u(undefined, r('PurpleError')) }],\n    false\n  ),\n  PrivateChannelOnAddContextListenerEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnAddContextListenerEventPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnAddContextListenerEventType') },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerEventPayload: o(\n    [\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n      { json: 'privateChannelId', js: 'privateChannelId', typ: '' },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnDisconnectEventPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnDisconnectEventType') },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectEventPayload: o([{ json: 'privateChannelId', js: 'privateChannelId', typ: '' }], false),\n  PrivateChannelOnUnsubscribeEvent: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastEventMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnUnsubscribeEventPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnUnsubscribeEventType') },\n    ],\n    false\n  ),\n  PrivateChannelOnUnsubscribeEventPayload: o(\n    [\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n      { json: 'privateChannelId', js: 'privateChannelId', typ: '' },\n    ],\n    false\n  ),\n  PrivateChannelUnsubscribeEventListenerRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelUnsubscribeEventListenerRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelUnsubscribeEventListenerRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelUnsubscribeEventListenerRequestPayload: o(\n    [{ json: 'listenerUUID', js: 'listenerUUID', typ: '' }],\n    false\n  ),\n  PrivateChannelUnsubscribeEventListenerResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastResponseResponsePayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelUnsubscribeEventListenerResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentForContextRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentForContextRequestPayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentForContextRequestType') },\n    ],\n    false\n  ),\n  RaiseIntentForContextRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  RaiseIntentForContextResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentForContextResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentForContextResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentForContextResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'intentResolution', js: 'intentResolution', typ: u(undefined, r('IntentResolution')) },\n      { json: 'appIntents', js: 'appIntents', typ: u(undefined, a(r('AppIntent'))) },\n    ],\n    false\n  ),\n  IntentResolution: o(\n    [\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'source', js: 'source', typ: r('AppIdentifier') },\n    ],\n    false\n  ),\n  RaiseIntentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentRequestType') },\n    ],\n    false\n  ),\n  RaiseIntentRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: u(undefined, r('AppIdentifier')) },\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'intent', js: 'intent', typ: '' },\n    ],\n    false\n  ),\n  RaiseIntentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('FindInstancesErrors')) },\n      { json: 'intentResolution', js: 'intentResolution', typ: u(undefined, r('IntentResolution')) },\n      { json: 'appIntent', js: 'appIntent', typ: u(undefined, r('AppIntent')) },\n    ],\n    false\n  ),\n  RaiseIntentResultResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResultResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResultResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResultResponsePayload: o(\n    [\n      { json: 'error', js: 'error', typ: u(undefined, r('ResponsePayloadError')) },\n      { json: 'intentResult', js: 'intentResult', typ: u(undefined, r('IntentResult')) },\n    ],\n    false\n  ),\n  WebConnectionProtocol1HelloType: ['WCP1Hello'],\n  WebConnectionProtocol2LoadURLType: ['WCP2LoadUrl'],\n  WebConnectionProtocol3HandshakeType: ['WCP3Handshake'],\n  WebConnectionProtocol4ValidateAppIdentityType: ['WCP4ValidateAppIdentity'],\n  WebConnectionProtocol5ValidateAppIdentityFailedResponseType: ['WCP5ValidateAppIdentityFailedResponse'],\n  WebConnectionProtocol5ValidateAppIdentitySuccessResponseType: ['WCP5ValidateAppIdentityResponse'],\n  WebConnectionProtocol6GoodbyeType: ['WCP6Goodbye'],\n  ConnectionStepMessageType: [\n    'WCP1Hello',\n    'WCP2LoadUrl',\n    'WCP3Handshake',\n    'WCP4ValidateAppIdentity',\n    'WCP5ValidateAppIdentityFailedResponse',\n    'WCP5ValidateAppIdentityResponse',\n    'WCP6Goodbye',\n  ],\n  AddContextListenerRequestType: ['addContextListenerRequest'],\n  PurpleError: [\n    'ApiTimeout',\n    'AccessDenied',\n    'CreationFailed',\n    'InvalidArguments',\n    'MalformedContext',\n    'NoChannelFound',\n  ],\n  AddContextListenerResponseType: ['addContextListenerResponse'],\n  FDC3EventType: ['USER_CHANNEL_CHANGED'],\n  AddEventListenerRequestType: ['addEventListenerRequest'],\n  ResponsePayloadError: [\n    'ApiTimeout',\n    'AccessDenied',\n    'AgentDisconnected',\n    'AppNotFound',\n    'AppTimeout',\n    'CreationFailed',\n    'DesktopAgentNotFound',\n    'ErrorOnLaunch',\n    'IntentDeliveryFailed',\n    'IntentHandlerRejected',\n    'IntentListenerConflict',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NoAppsFound',\n    'NoChannelFound',\n    'NoResultReturned',\n    'NotConnectedToBridge',\n    'ResolverTimeout',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n    'TargetAppUnavailable',\n    'TargetInstanceUnavailable',\n    'UserCancelledResolution',\n  ],\n  AddEventListenerResponseType: ['addEventListenerResponse'],\n  AddIntentListenerRequestType: ['addIntentListenerRequest'],\n  FluffyError: [\n    'ApiTimeout',\n    'DesktopAgentNotFound',\n    'IntentDeliveryFailed',\n    'IntentListenerConflict',\n    'InvalidArguments',\n    'MalformedContext',\n    'NoAppsFound',\n    'ResolverTimeout',\n    'ResolverUnavailable',\n    'TargetAppUnavailable',\n    'TargetInstanceUnavailable',\n    'UserCancelledResolution',\n  ],\n  AddIntentListenerResponseType: ['addIntentListenerResponse'],\n  EventMessageType: [\n    'addEventListenerEvent',\n    'broadcastEvent',\n    'channelChangedEvent',\n    'contextClearedEvent',\n    'heartbeatEvent',\n    'intentEvent',\n    'privateChannelOnAddContextListenerEvent',\n    'privateChannelOnDisconnectEvent',\n    'privateChannelOnUnsubscribeEvent',\n  ],\n  ResponseMessageType: [\n    'addContextListenerResponse',\n    'addEventListenerResponse',\n    'addIntentListenerResponse',\n    'broadcastResponse',\n    'clearContextResponse',\n    'contextListenerUnsubscribeResponse',\n    'createPrivateChannelResponse',\n    'eventListenerUnsubscribeResponse',\n    'findInstancesResponse',\n    'findIntentResponse',\n    'findIntentsByContextResponse',\n    'getAppMetadataResponse',\n    'getCurrentChannelResponse',\n    'getCurrentContextResponse',\n    'getInfoResponse',\n    'getOrCreateChannelResponse',\n    'getUserChannelsResponse',\n    'intentListenerUnsubscribeResponse',\n    'intentResultResponse',\n    'joinUserChannelResponse',\n    'leaveCurrentChannelResponse',\n    'openResponse',\n    'privateChannelAddEventListenerResponse',\n    'privateChannelDisconnectResponse',\n    'privateChannelUnsubscribeEventListenerResponse',\n    'raiseIntentForContextResponse',\n    'raiseIntentResponse',\n    'raiseIntentResultResponse',\n  ],\n  RequestMessageType: [\n    'addContextListenerRequest',\n    'addEventListenerRequest',\n    'addIntentListenerRequest',\n    'broadcastRequest',\n    'clearContextRequest',\n    'contextListenerUnsubscribeRequest',\n    'createPrivateChannelRequest',\n    'eventListenerUnsubscribeRequest',\n    'findInstancesRequest',\n    'findIntentRequest',\n    'findIntentsByContextRequest',\n    'getAppMetadataRequest',\n    'getCurrentChannelRequest',\n    'getCurrentContextRequest',\n    'getInfoRequest',\n    'getOrCreateChannelRequest',\n    'getUserChannelsRequest',\n    'heartbeatAcknowledgementRequest',\n    'intentListenerUnsubscribeRequest',\n    'intentResultRequest',\n    'joinUserChannelRequest',\n    'leaveCurrentChannelRequest',\n    'openRequest',\n    'privateChannelAddEventListenerRequest',\n    'privateChannelDisconnectRequest',\n    'privateChannelUnsubscribeEventListenerRequest',\n    'raiseIntentForContextRequest',\n    'raiseIntentRequest',\n  ],\n  BroadcastEventType: ['broadcastEvent'],\n  BroadcastRequestType: ['broadcastRequest'],\n  BroadcastResponseType: ['broadcastResponse'],\n  ChannelChangedEventType: ['channelChangedEvent'],\n  ClearContextRequestType: ['clearContextRequest'],\n  ClearContextResponseType: ['clearContextResponse'],\n  ContextClearedEventType: ['contextClearedEvent'],\n  ContextListenerUnsubscribeRequestType: ['contextListenerUnsubscribeRequest'],\n  ContextListenerUnsubscribeResponseType: ['contextListenerUnsubscribeResponse'],\n  CreatePrivateChannelRequestType: ['createPrivateChannelRequest'],\n  Type: ['app', 'private', 'user'],\n  CreatePrivateChannelResponseType: ['createPrivateChannelResponse'],\n  EventListenerUnsubscribeRequestType: ['eventListenerUnsubscribeRequest'],\n  EventListenerUnsubscribeResponseType: ['eventListenerUnsubscribeResponse'],\n  Fdc3UserInterfaceChannelSelectedType: ['Fdc3UserInterfaceChannelSelected'],\n  Fdc3UserInterfaceChannelsType: ['Fdc3UserInterfaceChannels'],\n  Fdc3UserInterfaceDragType: ['Fdc3UserInterfaceDrag'],\n  Fdc3UserInterfaceHandshakeType: ['Fdc3UserInterfaceHandshake'],\n  Fdc3UserInterfaceHelloType: ['Fdc3UserInterfaceHello'],\n  Fdc3UserInterfaceMessageType: [\n    'Fdc3UserInterfaceChannelSelected',\n    'Fdc3UserInterfaceChannels',\n    'Fdc3UserInterfaceDrag',\n    'Fdc3UserInterfaceHandshake',\n    'Fdc3UserInterfaceHello',\n    'Fdc3UserInterfaceResolve',\n    'Fdc3UserInterfaceResolveAction',\n    'Fdc3UserInterfaceRestyle',\n  ],\n  Fdc3UserInterfaceResolveType: ['Fdc3UserInterfaceResolve'],\n  Action: ['cancel', 'click', 'hover'],\n  Fdc3UserInterfaceResolveActionType: ['Fdc3UserInterfaceResolveAction'],\n  Fdc3UserInterfaceRestyleType: ['Fdc3UserInterfaceRestyle'],\n  FindInstancesRequestType: ['findInstancesRequest'],\n  FindInstancesErrors: [\n    'ApiTimeout',\n    'AgentDisconnected',\n    'DesktopAgentNotFound',\n    'IntentDeliveryFailed',\n    'IntentListenerConflict',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NoAppsFound',\n    'NotConnectedToBridge',\n    'ResolverTimeout',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n    'TargetAppUnavailable',\n    'TargetInstanceUnavailable',\n    'UserCancelledResolution',\n  ],\n  FindInstancesResponseType: ['findInstancesResponse'],\n  FindIntentRequestType: ['findIntentRequest'],\n  FindIntentResponseType: ['findIntentResponse'],\n  FindIntentsByContextRequestType: ['findIntentsByContextRequest'],\n  FindIntentsByContextResponseType: ['findIntentsByContextResponse'],\n  GetAppMetadataRequestType: ['getAppMetadataRequest'],\n  GetAppMetadataResponseType: ['getAppMetadataResponse'],\n  GetCurrentChannelRequestType: ['getCurrentChannelRequest'],\n  GetCurrentChannelResponseType: ['getCurrentChannelResponse'],\n  GetCurrentContextRequestType: ['getCurrentContextRequest'],\n  GetCurrentContextResponseType: ['getCurrentContextResponse'],\n  GetInfoRequestType: ['getInfoRequest'],\n  GetInfoResponseType: ['getInfoResponse'],\n  GetOrCreateChannelRequestType: ['getOrCreateChannelRequest'],\n  GetOrCreateChannelResponseType: ['getOrCreateChannelResponse'],\n  GetUserChannelsRequestType: ['getUserChannelsRequest'],\n  GetUserChannelsResponseType: ['getUserChannelsResponse'],\n  HeartbeatAcknowledgementRequestType: ['heartbeatAcknowledgementRequest'],\n  HeartbeatEventType: ['heartbeatEvent'],\n  IntentEventType: ['intentEvent'],\n  IntentListenerUnsubscribeRequestType: ['intentListenerUnsubscribeRequest'],\n  IntentListenerUnsubscribeResponseType: ['intentListenerUnsubscribeResponse'],\n  IntentResultRequestType: ['intentResultRequest'],\n  IntentResultResponseType: ['intentResultResponse'],\n  JoinUserChannelRequestType: ['joinUserChannelRequest'],\n  JoinUserChannelResponseType: ['joinUserChannelResponse'],\n  LeaveCurrentChannelRequestType: ['leaveCurrentChannelRequest'],\n  LeaveCurrentChannelResponseType: ['leaveCurrentChannelResponse'],\n  OpenRequestType: ['openRequest'],\n  OpenErrorResponsePayload: [\n    'ApiTimeout',\n    'AgentDisconnected',\n    'AppNotFound',\n    'AppTimeout',\n    'DesktopAgentNotFound',\n    'ErrorOnLaunch',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NotConnectedToBridge',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n  ],\n  OpenResponseType: ['openResponse'],\n  PrivateChannelEventType: ['addContextListener', 'disconnect', 'unsubscribe'],\n  PrivateChannelAddEventListenerRequestType: ['privateChannelAddEventListenerRequest'],\n  PrivateChannelAddEventListenerResponseType: ['privateChannelAddEventListenerResponse'],\n  PrivateChannelDisconnectRequestType: ['privateChannelDisconnectRequest'],\n  PrivateChannelDisconnectResponseType: ['privateChannelDisconnectResponse'],\n  PrivateChannelOnAddContextListenerEventType: ['privateChannelOnAddContextListenerEvent'],\n  PrivateChannelOnDisconnectEventType: ['privateChannelOnDisconnectEvent'],\n  PrivateChannelOnUnsubscribeEventType: ['privateChannelOnUnsubscribeEvent'],\n  PrivateChannelUnsubscribeEventListenerRequestType: ['privateChannelUnsubscribeEventListenerRequest'],\n  PrivateChannelUnsubscribeEventListenerResponseType: ['privateChannelUnsubscribeEventListenerResponse'],\n  RaiseIntentForContextRequestType: ['raiseIntentForContextRequest'],\n  RaiseIntentForContextResponseType: ['raiseIntentForContextResponse'],\n  RaiseIntentRequestType: ['raiseIntentRequest'],\n  RaiseIntentResponseType: ['raiseIntentResponse'],\n  RaiseIntentResultResponseType: ['raiseIntentResultResponse'],\n};\n\nexport type AppRequestMessage =\n  | AddContextListenerRequest\n  | AddEventListenerRequest\n  | AddIntentListenerRequest\n  | BroadcastRequest\n  | ClearContextRequest\n  | ContextListenerUnsubscribeRequest\n  | CreatePrivateChannelRequest\n  | EventListenerUnsubscribeRequest\n  | FindInstancesRequest\n  | FindIntentRequest\n  | FindIntentsByContextRequest\n  | GetAppMetadataRequest\n  | GetCurrentChannelRequest\n  | GetCurrentContextRequest\n  | GetInfoRequest\n  | GetOrCreateChannelRequest\n  | GetUserChannelsRequest\n  | HeartbeatAcknowledgementRequest\n  | IntentListenerUnsubscribeRequest\n  | IntentResultRequest\n  | JoinUserChannelRequest\n  | LeaveCurrentChannelRequest\n  | OpenRequest\n  | PrivateChannelAddEventListenerRequest\n  | PrivateChannelDisconnectRequest\n  | PrivateChannelUnsubscribeEventListenerRequest\n  | RaiseIntentForContextRequest\n  | RaiseIntentRequest;\n\nexport type AgentResponseMessage =\n  | AddContextListenerResponse\n  | AddEventListenerResponse\n  | AddIntentListenerResponse\n  | BroadcastResponse\n  | ClearContextResponse\n  | ContextListenerUnsubscribeResponse\n  | CreatePrivateChannelResponse\n  | EventListenerUnsubscribeResponse\n  | FindInstancesResponse\n  | FindIntentResponse\n  | FindIntentsByContextResponse\n  | GetAppMetadataResponse\n  | GetCurrentChannelResponse\n  | GetCurrentContextResponse\n  | GetInfoResponse\n  | GetOrCreateChannelResponse\n  | GetUserChannelsResponse\n  | IntentListenerUnsubscribeResponse\n  | IntentResultResponse\n  | JoinUserChannelResponse\n  | LeaveCurrentChannelResponse\n  | OpenResponse\n  | PrivateChannelAddEventListenerResponse\n  | PrivateChannelDisconnectResponse\n  | PrivateChannelUnsubscribeEventListenerResponse\n  | RaiseIntentForContextResponse\n  | RaiseIntentResponse\n  | RaiseIntentResultResponse;\n\nexport type AgentEventMessage =\n  | BroadcastEvent\n  | ChannelChangedEvent\n  | ContextClearedEvent\n  | HeartbeatEvent\n  | IntentEvent\n  | PrivateChannelOnAddContextListenerEvent\n  | PrivateChannelOnDisconnectEvent\n  | PrivateChannelOnUnsubscribeEvent;\n\n/**\n * Returns true if the value has a type property with value 'WCP1Hello'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol1Hello(value: any): value is WebConnectionProtocol1Hello {\n  return value != null && value.type === 'WCP1Hello';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol1Hello. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol1Hello(value: any): value is WebConnectionProtocol1Hello {\n  try {\n    Convert.webConnectionProtocol1HelloToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL1_HELLO_TYPE = 'WebConnectionProtocol1Hello';\n\n/**\n * Returns true if the value has a type property with value 'WCP2LoadUrl'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol2LoadURL(value: any): value is WebConnectionProtocol2LoadURL {\n  return value != null && value.type === 'WCP2LoadUrl';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol2LoadURL. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol2LoadURL(value: any): value is WebConnectionProtocol2LoadURL {\n  try {\n    Convert.webConnectionProtocol2LoadURLToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL2_LOAD_U_R_L_TYPE = 'WebConnectionProtocol2LoadURL';\n\n/**\n * Returns true if the value has a type property with value 'WCP3Handshake'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol3Handshake(value: any): value is WebConnectionProtocol3Handshake {\n  return value != null && value.type === 'WCP3Handshake';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol3Handshake. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol3Handshake(value: any): value is WebConnectionProtocol3Handshake {\n  try {\n    Convert.webConnectionProtocol3HandshakeToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL3_HANDSHAKE_TYPE = 'WebConnectionProtocol3Handshake';\n\n/**\n * Returns true if the value has a type property with value 'WCP4ValidateAppIdentity'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol4ValidateAppIdentity(\n  value: any\n): value is WebConnectionProtocol4ValidateAppIdentity {\n  return value != null && value.type === 'WCP4ValidateAppIdentity';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol4ValidateAppIdentity. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol4ValidateAppIdentity(\n  value: any\n): value is WebConnectionProtocol4ValidateAppIdentity {\n  try {\n    Convert.webConnectionProtocol4ValidateAppIdentityToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL4_VALIDATE_APP_IDENTITY_TYPE = 'WebConnectionProtocol4ValidateAppIdentity';\n\n/**\n * Returns true if the value has a type property with value 'WCP5ValidateAppIdentityFailedResponse'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol5ValidateAppIdentityFailedResponse(\n  value: any\n): value is WebConnectionProtocol5ValidateAppIdentityFailedResponse {\n  return value != null && value.type === 'WCP5ValidateAppIdentityFailedResponse';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol5ValidateAppIdentityFailedResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol5ValidateAppIdentityFailedResponse(\n  value: any\n): value is WebConnectionProtocol5ValidateAppIdentityFailedResponse {\n  try {\n    Convert.webConnectionProtocol5ValidateAppIdentityFailedResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL5_VALIDATE_APP_IDENTITY_FAILED_RESPONSE_TYPE =\n  'WebConnectionProtocol5ValidateAppIdentityFailedResponse';\n\n/**\n * Returns true if the value has a type property with value 'WCP5ValidateAppIdentityResponse'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol5ValidateAppIdentitySuccessResponse(\n  value: any\n): value is WebConnectionProtocol5ValidateAppIdentitySuccessResponse {\n  return value != null && value.type === 'WCP5ValidateAppIdentityResponse';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol5ValidateAppIdentitySuccessResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol5ValidateAppIdentitySuccessResponse(\n  value: any\n): value is WebConnectionProtocol5ValidateAppIdentitySuccessResponse {\n  try {\n    Convert.webConnectionProtocol5ValidateAppIdentitySuccessResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL5_VALIDATE_APP_IDENTITY_SUCCESS_RESPONSE_TYPE =\n  'WebConnectionProtocol5ValidateAppIdentitySuccessResponse';\n\n/**\n * Returns true if the value has a type property with value 'WCP6Goodbye'. This is a fast check that does not check the format of the message\n */\nexport function isWebConnectionProtocol6Goodbye(value: any): value is WebConnectionProtocol6Goodbye {\n  return value != null && value.type === 'WCP6Goodbye';\n}\n\n/**\n * Returns true if value is a valid WebConnectionProtocol6Goodbye. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocol6Goodbye(value: any): value is WebConnectionProtocol6Goodbye {\n  try {\n    Convert.webConnectionProtocol6GoodbyeToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL6_GOODBYE_TYPE = 'WebConnectionProtocol6Goodbye';\n\n/**\n * Returns true if value is a valid WebConnectionProtocolMessage. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidWebConnectionProtocolMessage(value: any): value is WebConnectionProtocolMessage {\n  try {\n    Convert.webConnectionProtocolMessageToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const WEB_CONNECTION_PROTOCOL_MESSAGE_TYPE = 'WebConnectionProtocolMessage';\n\n/**\n * Returns true if the value has a type property with value 'addContextListenerRequest'. This is a fast check that does not check the format of the message\n */\nexport function isAddContextListenerRequest(value: any): value is AddContextListenerRequest {\n  return value != null && value.type === 'addContextListenerRequest';\n}\n\n/**\n * Returns true if value is a valid AddContextListenerRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddContextListenerRequest(value: any): value is AddContextListenerRequest {\n  try {\n    Convert.addContextListenerRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_CONTEXT_LISTENER_REQUEST_TYPE = 'AddContextListenerRequest';\n\n/**\n * Returns true if the value has a type property with value 'addContextListenerResponse'. This is a fast check that does not check the format of the message\n */\nexport function isAddContextListenerResponse(value: any): value is AddContextListenerResponse {\n  return value != null && value.type === 'addContextListenerResponse';\n}\n\n/**\n * Returns true if value is a valid AddContextListenerResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddContextListenerResponse(value: any): value is AddContextListenerResponse {\n  try {\n    Convert.addContextListenerResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_CONTEXT_LISTENER_RESPONSE_TYPE = 'AddContextListenerResponse';\n\n/**\n * Returns true if the value has a type property with value 'addEventListenerRequest'. This is a fast check that does not check the format of the message\n */\nexport function isAddEventListenerRequest(value: any): value is AddEventListenerRequest {\n  return value != null && value.type === 'addEventListenerRequest';\n}\n\n/**\n * Returns true if value is a valid AddEventListenerRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddEventListenerRequest(value: any): value is AddEventListenerRequest {\n  try {\n    Convert.addEventListenerRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_EVENT_LISTENER_REQUEST_TYPE = 'AddEventListenerRequest';\n\n/**\n * Returns true if the value has a type property with value 'addEventListenerResponse'. This is a fast check that does not check the format of the message\n */\nexport function isAddEventListenerResponse(value: any): value is AddEventListenerResponse {\n  return value != null && value.type === 'addEventListenerResponse';\n}\n\n/**\n * Returns true if value is a valid AddEventListenerResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddEventListenerResponse(value: any): value is AddEventListenerResponse {\n  try {\n    Convert.addEventListenerResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_EVENT_LISTENER_RESPONSE_TYPE = 'AddEventListenerResponse';\n\n/**\n * Returns true if the value has a type property with value 'addIntentListenerRequest'. This is a fast check that does not check the format of the message\n */\nexport function isAddIntentListenerRequest(value: any): value is AddIntentListenerRequest {\n  return value != null && value.type === 'addIntentListenerRequest';\n}\n\n/**\n * Returns true if value is a valid AddIntentListenerRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddIntentListenerRequest(value: any): value is AddIntentListenerRequest {\n  try {\n    Convert.addIntentListenerRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_INTENT_LISTENER_REQUEST_TYPE = 'AddIntentListenerRequest';\n\n/**\n * Returns true if the value has a type property with value 'addIntentListenerResponse'. This is a fast check that does not check the format of the message\n */\nexport function isAddIntentListenerResponse(value: any): value is AddIntentListenerResponse {\n  return value != null && value.type === 'addIntentListenerResponse';\n}\n\n/**\n * Returns true if value is a valid AddIntentListenerResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidAddIntentListenerResponse(value: any): value is AddIntentListenerResponse {\n  try {\n    Convert.addIntentListenerResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const ADD_INTENT_LISTENER_RESPONSE_TYPE = 'AddIntentListenerResponse';\n\n/**\n * Returns true if the value has a type property with value 'broadcastEvent'. This is a fast check that does not check the format of the message\n */\nexport function isBroadcastEvent(value: any): value is BroadcastEvent {\n  return value != null && value.type === 'broadcastEvent';\n}\n\n/**\n * Returns true if value is a valid BroadcastEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidBroadcastEvent(value: any): value is BroadcastEvent {\n  try {\n    Convert.broadcastEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const BROADCAST_EVENT_TYPE = 'BroadcastEvent';\n\n/**\n * Returns true if the value has a type property with value 'broadcastRequest'. This is a fast check that does not check the format of the message\n */\nexport function isBroadcastRequest(value: any): value is BroadcastRequest {\n  return value != null && value.type === 'broadcastRequest';\n}\n\n/**\n * Returns true if value is a valid BroadcastRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidBroadcastRequest(value: any): value is BroadcastRequest {\n  try {\n    Convert.broadcastRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const BROADCAST_REQUEST_TYPE = 'BroadcastRequest';\n\n/**\n * Returns true if the value has a type property with value 'broadcastResponse'. This is a fast check that does not check the format of the message\n */\nexport function isBroadcastResponse(value: any): value is BroadcastResponse {\n  return value != null && value.type === 'broadcastResponse';\n}\n\n/**\n * Returns true if value is a valid BroadcastResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidBroadcastResponse(value: any): value is BroadcastResponse {\n  try {\n    Convert.broadcastResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const BROADCAST_RESPONSE_TYPE = 'BroadcastResponse';\n\n/**\n * Returns true if the value has a type property with value 'channelChangedEvent'. This is a fast check that does not check the format of the message\n */\nexport function isChannelChangedEvent(value: any): value is ChannelChangedEvent {\n  return value != null && value.type === 'channelChangedEvent';\n}\n\n/**\n * Returns true if value is a valid ChannelChangedEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidChannelChangedEvent(value: any): value is ChannelChangedEvent {\n  try {\n    Convert.channelChangedEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CHANNEL_CHANGED_EVENT_TYPE = 'ChannelChangedEvent';\n\n/**\n * Returns true if the value has a type property with value 'clearContextRequest'. This is a fast check that does not check the format of the message\n */\nexport function isClearContextRequest(value: any): value is ClearContextRequest {\n  return value != null && value.type === 'clearContextRequest';\n}\n\n/**\n * Returns true if value is a valid ClearContextRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidClearContextRequest(value: any): value is ClearContextRequest {\n  try {\n    Convert.clearContextRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CLEAR_CONTEXT_REQUEST_TYPE = 'ClearContextRequest';\n\n/**\n * Returns true if the value has a type property with value 'clearContextResponse'. This is a fast check that does not check the format of the message\n */\nexport function isClearContextResponse(value: any): value is ClearContextResponse {\n  return value != null && value.type === 'clearContextResponse';\n}\n\n/**\n * Returns true if value is a valid ClearContextResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidClearContextResponse(value: any): value is ClearContextResponse {\n  try {\n    Convert.clearContextResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CLEAR_CONTEXT_RESPONSE_TYPE = 'ClearContextResponse';\n\n/**\n * Returns true if the value has a type property with value 'contextClearedEvent'. This is a fast check that does not check the format of the message\n */\nexport function isContextClearedEvent(value: any): value is ContextClearedEvent {\n  return value != null && value.type === 'contextClearedEvent';\n}\n\n/**\n * Returns true if value is a valid ContextClearedEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidContextClearedEvent(value: any): value is ContextClearedEvent {\n  try {\n    Convert.contextClearedEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CONTEXT_CLEARED_EVENT_TYPE = 'ContextClearedEvent';\n\n/**\n * Returns true if the value has a type property with value 'contextListenerUnsubscribeRequest'. This is a fast check that does not check the format of the message\n */\nexport function isContextListenerUnsubscribeRequest(value: any): value is ContextListenerUnsubscribeRequest {\n  return value != null && value.type === 'contextListenerUnsubscribeRequest';\n}\n\n/**\n * Returns true if value is a valid ContextListenerUnsubscribeRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidContextListenerUnsubscribeRequest(value: any): value is ContextListenerUnsubscribeRequest {\n  try {\n    Convert.contextListenerUnsubscribeRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CONTEXT_LISTENER_UNSUBSCRIBE_REQUEST_TYPE = 'ContextListenerUnsubscribeRequest';\n\n/**\n * Returns true if the value has a type property with value 'contextListenerUnsubscribeResponse'. This is a fast check that does not check the format of the message\n */\nexport function isContextListenerUnsubscribeResponse(value: any): value is ContextListenerUnsubscribeResponse {\n  return value != null && value.type === 'contextListenerUnsubscribeResponse';\n}\n\n/**\n * Returns true if value is a valid ContextListenerUnsubscribeResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidContextListenerUnsubscribeResponse(value: any): value is ContextListenerUnsubscribeResponse {\n  try {\n    Convert.contextListenerUnsubscribeResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CONTEXT_LISTENER_UNSUBSCRIBE_RESPONSE_TYPE = 'ContextListenerUnsubscribeResponse';\n\n/**\n * Returns true if the value has a type property with value 'createPrivateChannelRequest'. This is a fast check that does not check the format of the message\n */\nexport function isCreatePrivateChannelRequest(value: any): value is CreatePrivateChannelRequest {\n  return value != null && value.type === 'createPrivateChannelRequest';\n}\n\n/**\n * Returns true if value is a valid CreatePrivateChannelRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidCreatePrivateChannelRequest(value: any): value is CreatePrivateChannelRequest {\n  try {\n    Convert.createPrivateChannelRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CREATE_PRIVATE_CHANNEL_REQUEST_TYPE = 'CreatePrivateChannelRequest';\n\n/**\n * Returns true if the value has a type property with value 'createPrivateChannelResponse'. This is a fast check that does not check the format of the message\n */\nexport function isCreatePrivateChannelResponse(value: any): value is CreatePrivateChannelResponse {\n  return value != null && value.type === 'createPrivateChannelResponse';\n}\n\n/**\n * Returns true if value is a valid CreatePrivateChannelResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidCreatePrivateChannelResponse(value: any): value is CreatePrivateChannelResponse {\n  try {\n    Convert.createPrivateChannelResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const CREATE_PRIVATE_CHANNEL_RESPONSE_TYPE = 'CreatePrivateChannelResponse';\n\n/**\n * Returns true if the value has a type property with value 'eventListenerUnsubscribeRequest'. This is a fast check that does not check the format of the message\n */\nexport function isEventListenerUnsubscribeRequest(value: any): value is EventListenerUnsubscribeRequest {\n  return value != null && value.type === 'eventListenerUnsubscribeRequest';\n}\n\n/**\n * Returns true if value is a valid EventListenerUnsubscribeRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidEventListenerUnsubscribeRequest(value: any): value is EventListenerUnsubscribeRequest {\n  try {\n    Convert.eventListenerUnsubscribeRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const EVENT_LISTENER_UNSUBSCRIBE_REQUEST_TYPE = 'EventListenerUnsubscribeRequest';\n\n/**\n * Returns true if the value has a type property with value 'eventListenerUnsubscribeResponse'. This is a fast check that does not check the format of the message\n */\nexport function isEventListenerUnsubscribeResponse(value: any): value is EventListenerUnsubscribeResponse {\n  return value != null && value.type === 'eventListenerUnsubscribeResponse';\n}\n\n/**\n * Returns true if value is a valid EventListenerUnsubscribeResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidEventListenerUnsubscribeResponse(value: any): value is EventListenerUnsubscribeResponse {\n  try {\n    Convert.eventListenerUnsubscribeResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const EVENT_LISTENER_UNSUBSCRIBE_RESPONSE_TYPE = 'EventListenerUnsubscribeResponse';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceChannelSelected'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceChannelSelected(value: any): value is Fdc3UserInterfaceChannelSelected {\n  return value != null && value.type === 'Fdc3UserInterfaceChannelSelected';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceChannelSelected. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceChannelSelected(value: any): value is Fdc3UserInterfaceChannelSelected {\n  try {\n    Convert.fdc3UserInterfaceChannelSelectedToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_CHANNEL_SELECTED_TYPE = 'Fdc3UserInterfaceChannelSelected';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceChannels'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceChannels(value: any): value is Fdc3UserInterfaceChannels {\n  return value != null && value.type === 'Fdc3UserInterfaceChannels';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceChannels. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceChannels(value: any): value is Fdc3UserInterfaceChannels {\n  try {\n    Convert.fdc3UserInterfaceChannelsToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_CHANNELS_TYPE = 'Fdc3UserInterfaceChannels';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceDrag'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceDrag(value: any): value is Fdc3UserInterfaceDrag {\n  return value != null && value.type === 'Fdc3UserInterfaceDrag';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceDrag. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceDrag(value: any): value is Fdc3UserInterfaceDrag {\n  try {\n    Convert.fdc3UserInterfaceDragToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_DRAG_TYPE = 'Fdc3UserInterfaceDrag';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceHandshake'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceHandshake(value: any): value is Fdc3UserInterfaceHandshake {\n  return value != null && value.type === 'Fdc3UserInterfaceHandshake';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceHandshake. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceHandshake(value: any): value is Fdc3UserInterfaceHandshake {\n  try {\n    Convert.fdc3UserInterfaceHandshakeToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_HANDSHAKE_TYPE = 'Fdc3UserInterfaceHandshake';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceHello'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceHello(value: any): value is Fdc3UserInterfaceHello {\n  return value != null && value.type === 'Fdc3UserInterfaceHello';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceHello. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceHello(value: any): value is Fdc3UserInterfaceHello {\n  try {\n    Convert.fdc3UserInterfaceHelloToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_HELLO_TYPE = 'Fdc3UserInterfaceHello';\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceMessage. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceMessage(value: any): value is Fdc3UserInterfaceMessage {\n  try {\n    Convert.fdc3UserInterfaceMessageToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_MESSAGE_TYPE = 'Fdc3UserInterfaceMessage';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceResolve'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceResolve(value: any): value is Fdc3UserInterfaceResolve {\n  return value != null && value.type === 'Fdc3UserInterfaceResolve';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceResolve. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceResolve(value: any): value is Fdc3UserInterfaceResolve {\n  try {\n    Convert.fdc3UserInterfaceResolveToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_RESOLVE_TYPE = 'Fdc3UserInterfaceResolve';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceResolveAction'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceResolveAction(value: any): value is Fdc3UserInterfaceResolveAction {\n  return value != null && value.type === 'Fdc3UserInterfaceResolveAction';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceResolveAction. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceResolveAction(value: any): value is Fdc3UserInterfaceResolveAction {\n  try {\n    Convert.fdc3UserInterfaceResolveActionToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_RESOLVE_ACTION_TYPE = 'Fdc3UserInterfaceResolveAction';\n\n/**\n * Returns true if the value has a type property with value 'Fdc3UserInterfaceRestyle'. This is a fast check that does not check the format of the message\n */\nexport function isFdc3UserInterfaceRestyle(value: any): value is Fdc3UserInterfaceRestyle {\n  return value != null && value.type === 'Fdc3UserInterfaceRestyle';\n}\n\n/**\n * Returns true if value is a valid Fdc3UserInterfaceRestyle. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFdc3UserInterfaceRestyle(value: any): value is Fdc3UserInterfaceRestyle {\n  try {\n    Convert.fdc3UserInterfaceRestyleToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FDC3_USER_INTERFACE_RESTYLE_TYPE = 'Fdc3UserInterfaceRestyle';\n\n/**\n * Returns true if the value has a type property with value 'findInstancesRequest'. This is a fast check that does not check the format of the message\n */\nexport function isFindInstancesRequest(value: any): value is FindInstancesRequest {\n  return value != null && value.type === 'findInstancesRequest';\n}\n\n/**\n * Returns true if value is a valid FindInstancesRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindInstancesRequest(value: any): value is FindInstancesRequest {\n  try {\n    Convert.findInstancesRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INSTANCES_REQUEST_TYPE = 'FindInstancesRequest';\n\n/**\n * Returns true if the value has a type property with value 'findInstancesResponse'. This is a fast check that does not check the format of the message\n */\nexport function isFindInstancesResponse(value: any): value is FindInstancesResponse {\n  return value != null && value.type === 'findInstancesResponse';\n}\n\n/**\n * Returns true if value is a valid FindInstancesResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindInstancesResponse(value: any): value is FindInstancesResponse {\n  try {\n    Convert.findInstancesResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INSTANCES_RESPONSE_TYPE = 'FindInstancesResponse';\n\n/**\n * Returns true if the value has a type property with value 'findIntentRequest'. This is a fast check that does not check the format of the message\n */\nexport function isFindIntentRequest(value: any): value is FindIntentRequest {\n  return value != null && value.type === 'findIntentRequest';\n}\n\n/**\n * Returns true if value is a valid FindIntentRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindIntentRequest(value: any): value is FindIntentRequest {\n  try {\n    Convert.findIntentRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INTENT_REQUEST_TYPE = 'FindIntentRequest';\n\n/**\n * Returns true if the value has a type property with value 'findIntentResponse'. This is a fast check that does not check the format of the message\n */\nexport function isFindIntentResponse(value: any): value is FindIntentResponse {\n  return value != null && value.type === 'findIntentResponse';\n}\n\n/**\n * Returns true if value is a valid FindIntentResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindIntentResponse(value: any): value is FindIntentResponse {\n  try {\n    Convert.findIntentResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INTENT_RESPONSE_TYPE = 'FindIntentResponse';\n\n/**\n * Returns true if the value has a type property with value 'findIntentsByContextRequest'. This is a fast check that does not check the format of the message\n */\nexport function isFindIntentsByContextRequest(value: any): value is FindIntentsByContextRequest {\n  return value != null && value.type === 'findIntentsByContextRequest';\n}\n\n/**\n * Returns true if value is a valid FindIntentsByContextRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindIntentsByContextRequest(value: any): value is FindIntentsByContextRequest {\n  try {\n    Convert.findIntentsByContextRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INTENTS_BY_CONTEXT_REQUEST_TYPE = 'FindIntentsByContextRequest';\n\n/**\n * Returns true if the value has a type property with value 'findIntentsByContextResponse'. This is a fast check that does not check the format of the message\n */\nexport function isFindIntentsByContextResponse(value: any): value is FindIntentsByContextResponse {\n  return value != null && value.type === 'findIntentsByContextResponse';\n}\n\n/**\n * Returns true if value is a valid FindIntentsByContextResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidFindIntentsByContextResponse(value: any): value is FindIntentsByContextResponse {\n  try {\n    Convert.findIntentsByContextResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const FIND_INTENTS_BY_CONTEXT_RESPONSE_TYPE = 'FindIntentsByContextResponse';\n\n/**\n * Returns true if the value has a type property with value 'getAppMetadataRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetAppMetadataRequest(value: any): value is GetAppMetadataRequest {\n  return value != null && value.type === 'getAppMetadataRequest';\n}\n\n/**\n * Returns true if value is a valid GetAppMetadataRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetAppMetadataRequest(value: any): value is GetAppMetadataRequest {\n  try {\n    Convert.getAppMetadataRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_APP_METADATA_REQUEST_TYPE = 'GetAppMetadataRequest';\n\n/**\n * Returns true if the value has a type property with value 'getAppMetadataResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetAppMetadataResponse(value: any): value is GetAppMetadataResponse {\n  return value != null && value.type === 'getAppMetadataResponse';\n}\n\n/**\n * Returns true if value is a valid GetAppMetadataResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetAppMetadataResponse(value: any): value is GetAppMetadataResponse {\n  try {\n    Convert.getAppMetadataResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_APP_METADATA_RESPONSE_TYPE = 'GetAppMetadataResponse';\n\n/**\n * Returns true if the value has a type property with value 'getCurrentChannelRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetCurrentChannelRequest(value: any): value is GetCurrentChannelRequest {\n  return value != null && value.type === 'getCurrentChannelRequest';\n}\n\n/**\n * Returns true if value is a valid GetCurrentChannelRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetCurrentChannelRequest(value: any): value is GetCurrentChannelRequest {\n  try {\n    Convert.getCurrentChannelRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_CURRENT_CHANNEL_REQUEST_TYPE = 'GetCurrentChannelRequest';\n\n/**\n * Returns true if the value has a type property with value 'getCurrentChannelResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetCurrentChannelResponse(value: any): value is GetCurrentChannelResponse {\n  return value != null && value.type === 'getCurrentChannelResponse';\n}\n\n/**\n * Returns true if value is a valid GetCurrentChannelResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetCurrentChannelResponse(value: any): value is GetCurrentChannelResponse {\n  try {\n    Convert.getCurrentChannelResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_CURRENT_CHANNEL_RESPONSE_TYPE = 'GetCurrentChannelResponse';\n\n/**\n * Returns true if the value has a type property with value 'getCurrentContextRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetCurrentContextRequest(value: any): value is GetCurrentContextRequest {\n  return value != null && value.type === 'getCurrentContextRequest';\n}\n\n/**\n * Returns true if value is a valid GetCurrentContextRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetCurrentContextRequest(value: any): value is GetCurrentContextRequest {\n  try {\n    Convert.getCurrentContextRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_CURRENT_CONTEXT_REQUEST_TYPE = 'GetCurrentContextRequest';\n\n/**\n * Returns true if the value has a type property with value 'getCurrentContextResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetCurrentContextResponse(value: any): value is GetCurrentContextResponse {\n  return value != null && value.type === 'getCurrentContextResponse';\n}\n\n/**\n * Returns true if value is a valid GetCurrentContextResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetCurrentContextResponse(value: any): value is GetCurrentContextResponse {\n  try {\n    Convert.getCurrentContextResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_CURRENT_CONTEXT_RESPONSE_TYPE = 'GetCurrentContextResponse';\n\n/**\n * Returns true if the value has a type property with value 'getInfoRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetInfoRequest(value: any): value is GetInfoRequest {\n  return value != null && value.type === 'getInfoRequest';\n}\n\n/**\n * Returns true if value is a valid GetInfoRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetInfoRequest(value: any): value is GetInfoRequest {\n  try {\n    Convert.getInfoRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_INFO_REQUEST_TYPE = 'GetInfoRequest';\n\n/**\n * Returns true if the value has a type property with value 'getInfoResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetInfoResponse(value: any): value is GetInfoResponse {\n  return value != null && value.type === 'getInfoResponse';\n}\n\n/**\n * Returns true if value is a valid GetInfoResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetInfoResponse(value: any): value is GetInfoResponse {\n  try {\n    Convert.getInfoResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_INFO_RESPONSE_TYPE = 'GetInfoResponse';\n\n/**\n * Returns true if the value has a type property with value 'getOrCreateChannelRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetOrCreateChannelRequest(value: any): value is GetOrCreateChannelRequest {\n  return value != null && value.type === 'getOrCreateChannelRequest';\n}\n\n/**\n * Returns true if value is a valid GetOrCreateChannelRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetOrCreateChannelRequest(value: any): value is GetOrCreateChannelRequest {\n  try {\n    Convert.getOrCreateChannelRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_OR_CREATE_CHANNEL_REQUEST_TYPE = 'GetOrCreateChannelRequest';\n\n/**\n * Returns true if the value has a type property with value 'getOrCreateChannelResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetOrCreateChannelResponse(value: any): value is GetOrCreateChannelResponse {\n  return value != null && value.type === 'getOrCreateChannelResponse';\n}\n\n/**\n * Returns true if value is a valid GetOrCreateChannelResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetOrCreateChannelResponse(value: any): value is GetOrCreateChannelResponse {\n  try {\n    Convert.getOrCreateChannelResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_OR_CREATE_CHANNEL_RESPONSE_TYPE = 'GetOrCreateChannelResponse';\n\n/**\n * Returns true if the value has a type property with value 'getUserChannelsRequest'. This is a fast check that does not check the format of the message\n */\nexport function isGetUserChannelsRequest(value: any): value is GetUserChannelsRequest {\n  return value != null && value.type === 'getUserChannelsRequest';\n}\n\n/**\n * Returns true if value is a valid GetUserChannelsRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetUserChannelsRequest(value: any): value is GetUserChannelsRequest {\n  try {\n    Convert.getUserChannelsRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_USER_CHANNELS_REQUEST_TYPE = 'GetUserChannelsRequest';\n\n/**\n * Returns true if the value has a type property with value 'getUserChannelsResponse'. This is a fast check that does not check the format of the message\n */\nexport function isGetUserChannelsResponse(value: any): value is GetUserChannelsResponse {\n  return value != null && value.type === 'getUserChannelsResponse';\n}\n\n/**\n * Returns true if value is a valid GetUserChannelsResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidGetUserChannelsResponse(value: any): value is GetUserChannelsResponse {\n  try {\n    Convert.getUserChannelsResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const GET_USER_CHANNELS_RESPONSE_TYPE = 'GetUserChannelsResponse';\n\n/**\n * Returns true if the value has a type property with value 'heartbeatAcknowledgementRequest'. This is a fast check that does not check the format of the message\n */\nexport function isHeartbeatAcknowledgementRequest(value: any): value is HeartbeatAcknowledgementRequest {\n  return value != null && value.type === 'heartbeatAcknowledgementRequest';\n}\n\n/**\n * Returns true if value is a valid HeartbeatAcknowledgementRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidHeartbeatAcknowledgementRequest(value: any): value is HeartbeatAcknowledgementRequest {\n  try {\n    Convert.heartbeatAcknowledgementRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const HEARTBEAT_ACKNOWLEDGEMENT_REQUEST_TYPE = 'HeartbeatAcknowledgementRequest';\n\n/**\n * Returns true if the value has a type property with value 'heartbeatEvent'. This is a fast check that does not check the format of the message\n */\nexport function isHeartbeatEvent(value: any): value is HeartbeatEvent {\n  return value != null && value.type === 'heartbeatEvent';\n}\n\n/**\n * Returns true if value is a valid HeartbeatEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidHeartbeatEvent(value: any): value is HeartbeatEvent {\n  try {\n    Convert.heartbeatEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const HEARTBEAT_EVENT_TYPE = 'HeartbeatEvent';\n\n/**\n * Returns true if the value has a type property with value 'intentEvent'. This is a fast check that does not check the format of the message\n */\nexport function isIntentEvent(value: any): value is IntentEvent {\n  return value != null && value.type === 'intentEvent';\n}\n\n/**\n * Returns true if value is a valid IntentEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidIntentEvent(value: any): value is IntentEvent {\n  try {\n    Convert.intentEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const INTENT_EVENT_TYPE = 'IntentEvent';\n\n/**\n * Returns true if the value has a type property with value 'intentListenerUnsubscribeRequest'. This is a fast check that does not check the format of the message\n */\nexport function isIntentListenerUnsubscribeRequest(value: any): value is IntentListenerUnsubscribeRequest {\n  return value != null && value.type === 'intentListenerUnsubscribeRequest';\n}\n\n/**\n * Returns true if value is a valid IntentListenerUnsubscribeRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidIntentListenerUnsubscribeRequest(value: any): value is IntentListenerUnsubscribeRequest {\n  try {\n    Convert.intentListenerUnsubscribeRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const INTENT_LISTENER_UNSUBSCRIBE_REQUEST_TYPE = 'IntentListenerUnsubscribeRequest';\n\n/**\n * Returns true if the value has a type property with value 'intentListenerUnsubscribeResponse'. This is a fast check that does not check the format of the message\n */\nexport function isIntentListenerUnsubscribeResponse(value: any): value is IntentListenerUnsubscribeResponse {\n  return value != null && value.type === 'intentListenerUnsubscribeResponse';\n}\n\n/**\n * Returns true if value is a valid IntentListenerUnsubscribeResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidIntentListenerUnsubscribeResponse(value: any): value is IntentListenerUnsubscribeResponse {\n  try {\n    Convert.intentListenerUnsubscribeResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const INTENT_LISTENER_UNSUBSCRIBE_RESPONSE_TYPE = 'IntentListenerUnsubscribeResponse';\n\n/**\n * Returns true if the value has a type property with value 'intentResultRequest'. This is a fast check that does not check the format of the message\n */\nexport function isIntentResultRequest(value: any): value is IntentResultRequest {\n  return value != null && value.type === 'intentResultRequest';\n}\n\n/**\n * Returns true if value is a valid IntentResultRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidIntentResultRequest(value: any): value is IntentResultRequest {\n  try {\n    Convert.intentResultRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const INTENT_RESULT_REQUEST_TYPE = 'IntentResultRequest';\n\n/**\n * Returns true if the value has a type property with value 'intentResultResponse'. This is a fast check that does not check the format of the message\n */\nexport function isIntentResultResponse(value: any): value is IntentResultResponse {\n  return value != null && value.type === 'intentResultResponse';\n}\n\n/**\n * Returns true if value is a valid IntentResultResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidIntentResultResponse(value: any): value is IntentResultResponse {\n  try {\n    Convert.intentResultResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const INTENT_RESULT_RESPONSE_TYPE = 'IntentResultResponse';\n\n/**\n * Returns true if the value has a type property with value 'joinUserChannelRequest'. This is a fast check that does not check the format of the message\n */\nexport function isJoinUserChannelRequest(value: any): value is JoinUserChannelRequest {\n  return value != null && value.type === 'joinUserChannelRequest';\n}\n\n/**\n * Returns true if value is a valid JoinUserChannelRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidJoinUserChannelRequest(value: any): value is JoinUserChannelRequest {\n  try {\n    Convert.joinUserChannelRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const JOIN_USER_CHANNEL_REQUEST_TYPE = 'JoinUserChannelRequest';\n\n/**\n * Returns true if the value has a type property with value 'joinUserChannelResponse'. This is a fast check that does not check the format of the message\n */\nexport function isJoinUserChannelResponse(value: any): value is JoinUserChannelResponse {\n  return value != null && value.type === 'joinUserChannelResponse';\n}\n\n/**\n * Returns true if value is a valid JoinUserChannelResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidJoinUserChannelResponse(value: any): value is JoinUserChannelResponse {\n  try {\n    Convert.joinUserChannelResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const JOIN_USER_CHANNEL_RESPONSE_TYPE = 'JoinUserChannelResponse';\n\n/**\n * Returns true if the value has a type property with value 'leaveCurrentChannelRequest'. This is a fast check that does not check the format of the message\n */\nexport function isLeaveCurrentChannelRequest(value: any): value is LeaveCurrentChannelRequest {\n  return value != null && value.type === 'leaveCurrentChannelRequest';\n}\n\n/**\n * Returns true if value is a valid LeaveCurrentChannelRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidLeaveCurrentChannelRequest(value: any): value is LeaveCurrentChannelRequest {\n  try {\n    Convert.leaveCurrentChannelRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const LEAVE_CURRENT_CHANNEL_REQUEST_TYPE = 'LeaveCurrentChannelRequest';\n\n/**\n * Returns true if the value has a type property with value 'leaveCurrentChannelResponse'. This is a fast check that does not check the format of the message\n */\nexport function isLeaveCurrentChannelResponse(value: any): value is LeaveCurrentChannelResponse {\n  return value != null && value.type === 'leaveCurrentChannelResponse';\n}\n\n/**\n * Returns true if value is a valid LeaveCurrentChannelResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidLeaveCurrentChannelResponse(value: any): value is LeaveCurrentChannelResponse {\n  try {\n    Convert.leaveCurrentChannelResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const LEAVE_CURRENT_CHANNEL_RESPONSE_TYPE = 'LeaveCurrentChannelResponse';\n\n/**\n * Returns true if the value has a type property with value 'openRequest'. This is a fast check that does not check the format of the message\n */\nexport function isOpenRequest(value: any): value is OpenRequest {\n  return value != null && value.type === 'openRequest';\n}\n\n/**\n * Returns true if value is a valid OpenRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidOpenRequest(value: any): value is OpenRequest {\n  try {\n    Convert.openRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const OPEN_REQUEST_TYPE = 'OpenRequest';\n\n/**\n * Returns true if the value has a type property with value 'openResponse'. This is a fast check that does not check the format of the message\n */\nexport function isOpenResponse(value: any): value is OpenResponse {\n  return value != null && value.type === 'openResponse';\n}\n\n/**\n * Returns true if value is a valid OpenResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidOpenResponse(value: any): value is OpenResponse {\n  try {\n    Convert.openResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const OPEN_RESPONSE_TYPE = 'OpenResponse';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelAddEventListenerRequest'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelAddEventListenerRequest(value: any): value is PrivateChannelAddEventListenerRequest {\n  return value != null && value.type === 'privateChannelAddEventListenerRequest';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelAddEventListenerRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelAddEventListenerRequest(\n  value: any\n): value is PrivateChannelAddEventListenerRequest {\n  try {\n    Convert.privateChannelAddEventListenerRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_ADD_EVENT_LISTENER_REQUEST_TYPE = 'PrivateChannelAddEventListenerRequest';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelAddEventListenerResponse'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelAddEventListenerResponse(value: any): value is PrivateChannelAddEventListenerResponse {\n  return value != null && value.type === 'privateChannelAddEventListenerResponse';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelAddEventListenerResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelAddEventListenerResponse(\n  value: any\n): value is PrivateChannelAddEventListenerResponse {\n  try {\n    Convert.privateChannelAddEventListenerResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_ADD_EVENT_LISTENER_RESPONSE_TYPE = 'PrivateChannelAddEventListenerResponse';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelDisconnectRequest'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelDisconnectRequest(value: any): value is PrivateChannelDisconnectRequest {\n  return value != null && value.type === 'privateChannelDisconnectRequest';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelDisconnectRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelDisconnectRequest(value: any): value is PrivateChannelDisconnectRequest {\n  try {\n    Convert.privateChannelDisconnectRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_DISCONNECT_REQUEST_TYPE = 'PrivateChannelDisconnectRequest';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelDisconnectResponse'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelDisconnectResponse(value: any): value is PrivateChannelDisconnectResponse {\n  return value != null && value.type === 'privateChannelDisconnectResponse';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelDisconnectResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelDisconnectResponse(value: any): value is PrivateChannelDisconnectResponse {\n  try {\n    Convert.privateChannelDisconnectResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_DISCONNECT_RESPONSE_TYPE = 'PrivateChannelDisconnectResponse';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelOnAddContextListenerEvent'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelOnAddContextListenerEvent(\n  value: any\n): value is PrivateChannelOnAddContextListenerEvent {\n  return value != null && value.type === 'privateChannelOnAddContextListenerEvent';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelOnAddContextListenerEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelOnAddContextListenerEvent(\n  value: any\n): value is PrivateChannelOnAddContextListenerEvent {\n  try {\n    Convert.privateChannelOnAddContextListenerEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_ON_ADD_CONTEXT_LISTENER_EVENT_TYPE = 'PrivateChannelOnAddContextListenerEvent';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelOnDisconnectEvent'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelOnDisconnectEvent(value: any): value is PrivateChannelOnDisconnectEvent {\n  return value != null && value.type === 'privateChannelOnDisconnectEvent';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelOnDisconnectEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelOnDisconnectEvent(value: any): value is PrivateChannelOnDisconnectEvent {\n  try {\n    Convert.privateChannelOnDisconnectEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_ON_DISCONNECT_EVENT_TYPE = 'PrivateChannelOnDisconnectEvent';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelOnUnsubscribeEvent'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelOnUnsubscribeEvent(value: any): value is PrivateChannelOnUnsubscribeEvent {\n  return value != null && value.type === 'privateChannelOnUnsubscribeEvent';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelOnUnsubscribeEvent. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelOnUnsubscribeEvent(value: any): value is PrivateChannelOnUnsubscribeEvent {\n  try {\n    Convert.privateChannelOnUnsubscribeEventToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_ON_UNSUBSCRIBE_EVENT_TYPE = 'PrivateChannelOnUnsubscribeEvent';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelUnsubscribeEventListenerRequest'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelUnsubscribeEventListenerRequest(\n  value: any\n): value is PrivateChannelUnsubscribeEventListenerRequest {\n  return value != null && value.type === 'privateChannelUnsubscribeEventListenerRequest';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelUnsubscribeEventListenerRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelUnsubscribeEventListenerRequest(\n  value: any\n): value is PrivateChannelUnsubscribeEventListenerRequest {\n  try {\n    Convert.privateChannelUnsubscribeEventListenerRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_UNSUBSCRIBE_EVENT_LISTENER_REQUEST_TYPE = 'PrivateChannelUnsubscribeEventListenerRequest';\n\n/**\n * Returns true if the value has a type property with value 'privateChannelUnsubscribeEventListenerResponse'. This is a fast check that does not check the format of the message\n */\nexport function isPrivateChannelUnsubscribeEventListenerResponse(\n  value: any\n): value is PrivateChannelUnsubscribeEventListenerResponse {\n  return value != null && value.type === 'privateChannelUnsubscribeEventListenerResponse';\n}\n\n/**\n * Returns true if value is a valid PrivateChannelUnsubscribeEventListenerResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidPrivateChannelUnsubscribeEventListenerResponse(\n  value: any\n): value is PrivateChannelUnsubscribeEventListenerResponse {\n  try {\n    Convert.privateChannelUnsubscribeEventListenerResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const PRIVATE_CHANNEL_UNSUBSCRIBE_EVENT_LISTENER_RESPONSE_TYPE =\n  'PrivateChannelUnsubscribeEventListenerResponse';\n\n/**\n * Returns true if the value has a type property with value 'raiseIntentForContextRequest'. This is a fast check that does not check the format of the message\n */\nexport function isRaiseIntentForContextRequest(value: any): value is RaiseIntentForContextRequest {\n  return value != null && value.type === 'raiseIntentForContextRequest';\n}\n\n/**\n * Returns true if value is a valid RaiseIntentForContextRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidRaiseIntentForContextRequest(value: any): value is RaiseIntentForContextRequest {\n  try {\n    Convert.raiseIntentForContextRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const RAISE_INTENT_FOR_CONTEXT_REQUEST_TYPE = 'RaiseIntentForContextRequest';\n\n/**\n * Returns true if the value has a type property with value 'raiseIntentForContextResponse'. This is a fast check that does not check the format of the message\n */\nexport function isRaiseIntentForContextResponse(value: any): value is RaiseIntentForContextResponse {\n  return value != null && value.type === 'raiseIntentForContextResponse';\n}\n\n/**\n * Returns true if value is a valid RaiseIntentForContextResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidRaiseIntentForContextResponse(value: any): value is RaiseIntentForContextResponse {\n  try {\n    Convert.raiseIntentForContextResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const RAISE_INTENT_FOR_CONTEXT_RESPONSE_TYPE = 'RaiseIntentForContextResponse';\n\n/**\n * Returns true if the value has a type property with value 'raiseIntentRequest'. This is a fast check that does not check the format of the message\n */\nexport function isRaiseIntentRequest(value: any): value is RaiseIntentRequest {\n  return value != null && value.type === 'raiseIntentRequest';\n}\n\n/**\n * Returns true if value is a valid RaiseIntentRequest. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidRaiseIntentRequest(value: any): value is RaiseIntentRequest {\n  try {\n    Convert.raiseIntentRequestToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const RAISE_INTENT_REQUEST_TYPE = 'RaiseIntentRequest';\n\n/**\n * Returns true if the value has a type property with value 'raiseIntentResponse'. This is a fast check that does not check the format of the message\n */\nexport function isRaiseIntentResponse(value: any): value is RaiseIntentResponse {\n  return value != null && value.type === 'raiseIntentResponse';\n}\n\n/**\n * Returns true if value is a valid RaiseIntentResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidRaiseIntentResponse(value: any): value is RaiseIntentResponse {\n  try {\n    Convert.raiseIntentResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const RAISE_INTENT_RESPONSE_TYPE = 'RaiseIntentResponse';\n\n/**\n * Returns true if the value has a type property with value 'raiseIntentResultResponse'. This is a fast check that does not check the format of the message\n */\nexport function isRaiseIntentResultResponse(value: any): value is RaiseIntentResultResponse {\n  return value != null && value.type === 'raiseIntentResultResponse';\n}\n\n/**\n * Returns true if value is a valid RaiseIntentResultResponse. This checks the type against the json schema for the message and will be slower\n */\nexport function isValidRaiseIntentResultResponse(value: any): value is RaiseIntentResultResponse {\n  try {\n    Convert.raiseIntentResultResponseToJson(value);\n    return true;\n  } catch (_e: any) {\n    return false;\n  }\n}\n\nexport const RAISE_INTENT_RESULT_RESPONSE_TYPE = 'RaiseIntentResultResponse';\n"
  },
  {
    "path": "packages/fdc3-schema/generated/bridging/BridgingTypes.ts",
    "content": "// To parse this data:\n//\n//   import { Convert, AgentErrorResponseMessage, AgentRequestMessage, AgentResponseMessage, BridgeErrorResponseMessage, BridgeRequestMessage, BridgeResponseMessage, BroadcastAgentRequest, BroadcastBridgeRequest, ConnectionStepMessage, ConnectionStep2Hello, ConnectionStep3Handshake, ConnectionStep4AuthenticationFailed, ConnectionStep6ConnectedAgentsUpdate, FindInstancesAgentErrorResponse, FindInstancesAgentRequest, FindInstancesAgentResponse, FindInstancesBridgeErrorResponse, FindInstancesBridgeRequest, FindInstancesBridgeResponse, FindIntentAgentErrorResponse, FindIntentAgentRequest, FindIntentAgentResponse, FindIntentBridgeErrorResponse, FindIntentBridgeRequest, FindIntentBridgeResponse, FindIntentsByContextAgentErrorResponse, FindIntentsByContextAgentRequest, FindIntentsByContextAgentResponse, FindIntentsByContextBridgeErrorResponse, FindIntentsByContextBridgeRequest, FindIntentsByContextBridgeResponse, GetAppMetadataAgentErrorResponse, GetAppMetadataAgentRequest, GetAppMetadataAgentResponse, GetAppMetadataBridgeErrorResponse, GetAppMetadataBridgeRequest, GetAppMetadataBridgeResponse, OpenAgentErrorResponse, OpenAgentRequest, OpenAgentResponse, OpenBridgeErrorResponse, OpenBridgeRequest, OpenBridgeResponse, PrivateChannelBroadcastAgentRequest, PrivateChannelBroadcastBridgeRequest, PrivateChannelEventListenerAddedAgentRequest, PrivateChannelEventListenerAddedBridgeRequest, PrivateChannelEventListenerRemovedAgentRequest, PrivateChannelEventListenerRemovedBridgeRequest, PrivateChannelOnAddContextListenerAgentRequest, PrivateChannelOnAddContextListenerBridgeRequest, PrivateChannelOnDisconnectAgentRequest, PrivateChannelOnDisconnectBridgeRequest, PrivateChannelOnUnsubscribeAgentRequest, PrivateChannelOnUnsubscribeBridgeRequest, RaiseIntentAgentErrorResponse, RaiseIntentAgentRequest, RaiseIntentAgentResponse, RaiseIntentBridgeErrorResponse, RaiseIntentBridgeRequest, RaiseIntentBridgeResponse, RaiseIntentResultAgentErrorResponse, RaiseIntentResultAgentResponse, RaiseIntentResultBridgeErrorResponse, RaiseIntentResultBridgeResponse } from \"./file\";\n//\n//   const agentErrorResponseMessage = Convert.toAgentErrorResponseMessage(json);\n//   const agentRequestMessage = Convert.toAgentRequestMessage(json);\n//   const agentResponseMessage = Convert.toAgentResponseMessage(json);\n//   const bridgeErrorResponseMessage = Convert.toBridgeErrorResponseMessage(json);\n//   const bridgeRequestMessage = Convert.toBridgeRequestMessage(json);\n//   const bridgeResponseMessage = Convert.toBridgeResponseMessage(json);\n//   const broadcastAgentRequest = Convert.toBroadcastAgentRequest(json);\n//   const broadcastBridgeRequest = Convert.toBroadcastBridgeRequest(json);\n//   const bridgeCommonDefinitions = Convert.toBridgeCommonDefinitions(json);\n//   const connectionStepMessage = Convert.toConnectionStepMessage(json);\n//   const connectionStep2Hello = Convert.toConnectionStep2Hello(json);\n//   const connectionStep3Handshake = Convert.toConnectionStep3Handshake(json);\n//   const connectionStep4AuthenticationFailed = Convert.toConnectionStep4AuthenticationFailed(json);\n//   const connectionStep6ConnectedAgentsUpdate = Convert.toConnectionStep6ConnectedAgentsUpdate(json);\n//   const findInstancesAgentErrorResponse = Convert.toFindInstancesAgentErrorResponse(json);\n//   const findInstancesAgentRequest = Convert.toFindInstancesAgentRequest(json);\n//   const findInstancesAgentResponse = Convert.toFindInstancesAgentResponse(json);\n//   const findInstancesBridgeErrorResponse = Convert.toFindInstancesBridgeErrorResponse(json);\n//   const findInstancesBridgeRequest = Convert.toFindInstancesBridgeRequest(json);\n//   const findInstancesBridgeResponse = Convert.toFindInstancesBridgeResponse(json);\n//   const findIntentAgentErrorResponse = Convert.toFindIntentAgentErrorResponse(json);\n//   const findIntentAgentRequest = Convert.toFindIntentAgentRequest(json);\n//   const findIntentAgentResponse = Convert.toFindIntentAgentResponse(json);\n//   const findIntentBridgeErrorResponse = Convert.toFindIntentBridgeErrorResponse(json);\n//   const findIntentBridgeRequest = Convert.toFindIntentBridgeRequest(json);\n//   const findIntentBridgeResponse = Convert.toFindIntentBridgeResponse(json);\n//   const findIntentsByContextAgentErrorResponse = Convert.toFindIntentsByContextAgentErrorResponse(json);\n//   const findIntentsByContextAgentRequest = Convert.toFindIntentsByContextAgentRequest(json);\n//   const findIntentsByContextAgentResponse = Convert.toFindIntentsByContextAgentResponse(json);\n//   const findIntentsByContextBridgeErrorResponse = Convert.toFindIntentsByContextBridgeErrorResponse(json);\n//   const findIntentsByContextBridgeRequest = Convert.toFindIntentsByContextBridgeRequest(json);\n//   const findIntentsByContextBridgeResponse = Convert.toFindIntentsByContextBridgeResponse(json);\n//   const getAppMetadataAgentErrorResponse = Convert.toGetAppMetadataAgentErrorResponse(json);\n//   const getAppMetadataAgentRequest = Convert.toGetAppMetadataAgentRequest(json);\n//   const getAppMetadataAgentResponse = Convert.toGetAppMetadataAgentResponse(json);\n//   const getAppMetadataBridgeErrorResponse = Convert.toGetAppMetadataBridgeErrorResponse(json);\n//   const getAppMetadataBridgeRequest = Convert.toGetAppMetadataBridgeRequest(json);\n//   const getAppMetadataBridgeResponse = Convert.toGetAppMetadataBridgeResponse(json);\n//   const openAgentErrorResponse = Convert.toOpenAgentErrorResponse(json);\n//   const openAgentRequest = Convert.toOpenAgentRequest(json);\n//   const openAgentResponse = Convert.toOpenAgentResponse(json);\n//   const openBridgeErrorResponse = Convert.toOpenBridgeErrorResponse(json);\n//   const openBridgeRequest = Convert.toOpenBridgeRequest(json);\n//   const openBridgeResponse = Convert.toOpenBridgeResponse(json);\n//   const privateChannelBroadcastAgentRequest = Convert.toPrivateChannelBroadcastAgentRequest(json);\n//   const privateChannelBroadcastBridgeRequest = Convert.toPrivateChannelBroadcastBridgeRequest(json);\n//   const privateChannelEventListenerAddedAgentRequest = Convert.toPrivateChannelEventListenerAddedAgentRequest(json);\n//   const privateChannelEventListenerAddedBridgeRequest = Convert.toPrivateChannelEventListenerAddedBridgeRequest(json);\n//   const privateChannelEventListenerRemovedAgentRequest = Convert.toPrivateChannelEventListenerRemovedAgentRequest(json);\n//   const privateChannelEventListenerRemovedBridgeRequest = Convert.toPrivateChannelEventListenerRemovedBridgeRequest(json);\n//   const privateChannelOnAddContextListenerAgentRequest = Convert.toPrivateChannelOnAddContextListenerAgentRequest(json);\n//   const privateChannelOnAddContextListenerBridgeRequest = Convert.toPrivateChannelOnAddContextListenerBridgeRequest(json);\n//   const privateChannelOnDisconnectAgentRequest = Convert.toPrivateChannelOnDisconnectAgentRequest(json);\n//   const privateChannelOnDisconnectBridgeRequest = Convert.toPrivateChannelOnDisconnectBridgeRequest(json);\n//   const privateChannelOnUnsubscribeAgentRequest = Convert.toPrivateChannelOnUnsubscribeAgentRequest(json);\n//   const privateChannelOnUnsubscribeBridgeRequest = Convert.toPrivateChannelOnUnsubscribeBridgeRequest(json);\n//   const raiseIntentAgentErrorResponse = Convert.toRaiseIntentAgentErrorResponse(json);\n//   const raiseIntentAgentRequest = Convert.toRaiseIntentAgentRequest(json);\n//   const raiseIntentAgentResponse = Convert.toRaiseIntentAgentResponse(json);\n//   const raiseIntentBridgeErrorResponse = Convert.toRaiseIntentBridgeErrorResponse(json);\n//   const raiseIntentBridgeRequest = Convert.toRaiseIntentBridgeRequest(json);\n//   const raiseIntentBridgeResponse = Convert.toRaiseIntentBridgeResponse(json);\n//   const raiseIntentResultAgentErrorResponse = Convert.toRaiseIntentResultAgentErrorResponse(json);\n//   const raiseIntentResultAgentResponse = Convert.toRaiseIntentResultAgentResponse(json);\n//   const raiseIntentResultBridgeErrorResponse = Convert.toRaiseIntentResultBridgeErrorResponse(json);\n//   const raiseIntentResultBridgeResponse = Convert.toRaiseIntentResultBridgeResponse(json);\n//\n// These functions will throw an error if the JSON doesn't\n// match the expected interface, even if the JSON is valid.\n\n/**\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface AgentErrorResponseMessage {\n  meta: AgentResponseMetadata;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: ErrorResponseMessagePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: ResponseMessageType;\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface AgentResponseMetadata {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface ErrorResponseMessagePayload {\n  error: ResponseErrorDetail;\n  [property: string]: any;\n}\n\n/**\n * Array of error message strings for responses that were not returned to the bridge before\n * the timeout or because an error occurred. Should be the same length as the `errorSources`\n * array and ordered the same. May be omitted if all sources responded without errors.\n *\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type ResponseErrorDetail =\n  | 'AccessDenied'\n  | 'CreationFailed'\n  | 'MalformedContext'\n  | 'NoChannelFound'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'AppNotFound'\n  | 'AppTimeout'\n  | 'DesktopAgentNotFound'\n  | 'ErrorOnLaunch'\n  | 'ResolverUnavailable'\n  | 'IntentDeliveryFailed'\n  | 'NoAppsFound'\n  | 'ResolverTimeout'\n  | 'TargetAppUnavailable'\n  | 'TargetInstanceUnavailable'\n  | 'UserCancelledResolution'\n  | 'IntentListenerConflict'\n  | 'IntentHandlerRejected'\n  | 'NoResultReturned'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n */\nexport type ResponseMessageType =\n  | 'findInstancesResponse'\n  | 'findIntentResponse'\n  | 'findIntentsByContextResponse'\n  | 'getAppMetadataResponse'\n  | 'openResponse'\n  | 'raiseIntentResponse'\n  | 'raiseIntentResultResponse';\n\n/**\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface AgentRequestMessage {\n  meta: AgentRequestMetadata;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: { [key: string]: any };\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: RequestMessageType;\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface AgentRequestMetadata {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceIdentifier;\n  timestamp: Date;\n}\n\n/**\n * Optional field that represents the destination that the request should be routed to. Must\n * be set by the Desktop Agent for API calls that include a target app parameter and must\n * include the name of the Desktop Agent hosting the target application.\n *\n * Represents identifiers that MUST include the Desktop Agent name and MAY identify a\n * specific app or instance.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n * be set by the bridge.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface BridgeParticipantIdentifier {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself.\n *\n * Field that represents the source application that a request or response was received\n * from, or the source Desktop Agent if it issued the request or response itself.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n */\nexport interface SourceIdentifier {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId?: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   *\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   */\n  desktopAgent?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n */\nexport type RequestMessageType =\n  | 'broadcastRequest'\n  | 'findInstancesRequest'\n  | 'findIntentRequest'\n  | 'findIntentsByContextRequest'\n  | 'getAppMetadataRequest'\n  | 'openRequest'\n  | 'PrivateChannel.broadcast'\n  | 'PrivateChannel.eventListenerAdded'\n  | 'PrivateChannel.eventListenerRemoved'\n  | 'PrivateChannel.onAddContextListener'\n  | 'PrivateChannel.onDisconnect'\n  | 'PrivateChannel.onUnsubscribe'\n  | 'raiseIntentRequest';\n\n/**\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface AgentResponseMessage {\n  meta: AgentResponseMetadata;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: { [key: string]: any };\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: ResponseMessageType;\n}\n\n/**\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface BridgeErrorResponseMessage {\n  meta: BridgeErrorResponseMessageMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: ResponseErrorMessagePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: string;\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface BridgeErrorResponseMessageMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n */\nexport interface DesktopAgentIdentifier {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   */\n  desktopAgent: string;\n  [property: string]: any;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface ResponseErrorMessagePayload {\n  error?: ResponseErrorDetail;\n  [property: string]: any;\n}\n\n/**\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface BridgeRequestMessage {\n  meta: BridgeRequestMetadata;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: { [key: string]: any };\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: string;\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface BridgeRequestMetadata {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: BridgeParticipantIdentifier;\n  timestamp: Date;\n}\n\n/**\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface BridgeResponseMessage {\n  meta: BridgeResponseMessageMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: { [key: string]: any };\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: string;\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface BridgeResponseMessageMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * A request to broadcast context on a channel.\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface BroadcastAgentRequest {\n  meta: BroadcastAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: BroadcastAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'broadcastRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface BroadcastAgentRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself.\n *\n * Field that represents the source application that a request or response was received\n * from, or the source Desktop Agent if it issued the request or response itself.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n */\nexport interface SourceObject {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   *\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   */\n  desktopAgent?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface BroadcastAgentRequestPayload {\n  /**\n   * The Id of the Channel that the broadcast was sent on.\n   */\n  channelId: string;\n  /**\n   * The context object that is to be broadcast.\n   */\n  context: Context;\n}\n\n/**\n * The context object that is to be broadcast.\n *\n * The context object that was the payload of a broadcast message.\n *\n * The `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by\n * FDC3 operations. As such, it is not really meant to be used on its own, but is imported\n * by more specific type definitions (standardized or custom) to provide the structure and\n * properties shared by all FDC3 context data types.\n *\n * The key element of FDC3 context types is their mandatory `type` property, which is used\n * to identify what type of data the object represents, and what shape it has.\n *\n * The FDC3 context type, and all derived types, define the minimum set of fields a context\n * data object of a particular type can be expected to have, but this can always be extended\n * with custom fields as appropriate.\n */\nexport interface Context {\n  /**\n   * Context data objects may include a set of equivalent key-value pairs that can be used to\n   * help applications identify and look up the context type they receive in their own domain.\n   * The idea behind this design is that applications can provide as many equivalent\n   * identifiers to a target application as possible, e.g. an instrument may be represented by\n   * an ISIN, CUSIP or Bloomberg identifier.\n   *\n   * Identifiers do not make sense for all types of data, so the `id` property is therefore\n   * optional, but some derived types may choose to require at least one identifier.\n   * Identifier values SHOULD always be of type string.\n   */\n  id?: { [key: string]: any };\n  /**\n   * Context data objects may include a name property that can be used for more information,\n   * or display purposes. Some derived types may require the name object as mandatory,\n   * depending on use case.\n   */\n  name?: string;\n  /**\n   * The type property is the only _required_ part of the FDC3 context data schema. The FDC3\n   * [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present\n   * to route shared context data appropriately.\n   *\n   * FDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data\n   * types they support in an FDC3 [App\n   * Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery\n   * and routing.\n   *\n   * Standardized FDC3 context types have well-known `type` properties prefixed with the\n   * `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and\n   * used by a particular organization, the convention is to prefix them with an\n   * organization-specific namespace, e.g. `blackrock.fund`.\n   *\n   * See the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more\n   * information about context data types.\n   */\n  type: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to broadcast context on a channel.\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface BroadcastBridgeRequest {\n  meta: BroadcastBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: BroadcastBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'broadcastRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface BroadcastBridgeRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n *\n * Optional field that represents the destination that the request should be routed to. Must\n * be set by the Desktop Agent for API calls that include a target app parameter and must\n * include the name of the Desktop Agent hosting the target application.\n *\n * Represents identifiers that MUST include the Desktop Agent name and MAY identify a\n * specific app or instance.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n * be set by the bridge.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n */\nexport interface MetaSource {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   *\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   */\n  desktopAgent: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface BroadcastBridgeRequestPayload {\n  /**\n   * The Id of the Channel that the broadcast was sent on.\n   */\n  channelId: string;\n  /**\n   * The context object that is to be broadcast.\n   */\n  context: Context;\n}\n\n/**\n * A message used during the connection flow for a Desktop Agent to the Bridge. Used for\n * messages sent in either direction.\n */\nexport interface ConnectionStepMessage {\n  meta: ConnectionStepMetadata;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: { [key: string]: any };\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: ConnectionStepMessageType;\n}\n\n/**\n * Metadata for this connection step message.\n */\nexport interface ConnectionStepMetadata {\n  requestUuid?: string;\n  responseUuid?: string;\n  timestamp: Date;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\nexport type ConnectionStepMessageType = 'hello' | 'handshake' | 'authenticationFailed' | 'connectedAgentsUpdate';\n\n/**\n * Hello message sent by the Bridge to anyone connecting to the Bridge (enables\n * identification as a bridge and confirmation of whether authentication is required)\n *\n * A message used during the connection flow for a Desktop Agent to the Bridge. Used for\n * messages sent in either direction.\n */\nexport interface ConnectionStep2Hello {\n  meta: ConnectionStep2HelloMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: ConnectionStep2HelloPayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'hello';\n}\n\n/**\n * Metadata for this connection step message.\n */\nexport interface ConnectionStep2HelloMeta {\n  timestamp: Date;\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface ConnectionStep2HelloPayload {\n  /**\n   * A flag indicating whether the Desktop Agent Bridge requires authentication or not.\n   */\n  authRequired: boolean;\n  /**\n   * An optional Desktop Agent Bridge JWT authentication token if the Desktop Agent want to\n   * authenticate a bridge.\n   */\n  authToken?: string;\n  /**\n   * The version of the Bridge\n   */\n  desktopAgentBridgeVersion: string;\n  /**\n   * The FDC3 versions supported by the Bridge\n   */\n  supportedFDC3Versions: string[];\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Handshake message sent by the Desktop Agent to the Bridge (including requested name,\n * channel state and authentication data)\n *\n * A message used during the connection flow for a Desktop Agent to the Bridge. Used for\n * messages sent in either direction.\n */\nexport interface ConnectionStep3Handshake {\n  meta: ConnectionStep3HandshakeMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: ConnectionStep3HandshakePayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'handshake';\n}\n\n/**\n * Metadata for this connection step message.\n */\nexport interface ConnectionStep3HandshakeMeta {\n  requestUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface ConnectionStep3HandshakePayload {\n  authToken?: string;\n  /**\n   * The current state of the Desktop Agent's App and User channels (exclude any Private\n   * channels), as a mapping of channel id to an array of Context objects, one per type found\n   * in the channel, most recent first.\n   */\n  channelsState: { [key: string]: Context[] };\n  /**\n   * Desktop Agent ImplementationMetadata trying to connect to the bridge.\n   */\n  implementationMetadata: ConnectingAgentImplementationMetadata;\n  /**\n   * The requested Desktop Agent name\n   */\n  requestedName: string;\n}\n\n/**\n * Desktop Agent ImplementationMetadata trying to connect to the bridge.\n *\n * Metadata relating to the FDC3 Desktop Agent implementation and its provider.\n */\nexport interface ConnectingAgentImplementationMetadata {\n  /**\n   * The version number of the FDC3 specification that the implementation provides.\n   * The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  fdc3Version: string;\n  /**\n   * Metadata indicating whether the Desktop Agent implements optional features of\n   * the Desktop Agent API.\n   */\n  optionalFeatures: OptionalFeatures;\n  /**\n   * The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42,\n   * OpenFin etc.).\n   */\n  provider: string;\n  /**\n   * The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\n   */\n  providerVersion?: string;\n}\n\n/**\n * Metadata indicating whether the Desktop Agent implements optional features of\n * the Desktop Agent API.\n */\nexport interface OptionalFeatures {\n  /**\n   * Used to indicate whether the experimental Desktop Agent Bridging\n   * feature is implemented by the Desktop Agent.\n   */\n  DesktopAgentBridging: boolean;\n  /**\n   * Used to indicate whether the exposure of 'originating app metadata' for\n   * context and intent messages is supported by the Desktop Agent.\n   */\n  OriginatingAppMetadata: boolean;\n  /**\n   * Used to indicate whether the optional `fdc3.joinUserChannel`,\n   * `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n   * the Desktop Agent.\n   */\n  UserChannelMembershipAPIs: boolean;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Message sent by Bridge to Desktop Agent if their authentication fails.\n *\n * A message used during the connection flow for a Desktop Agent to the Bridge. Used for\n * messages sent in either direction.\n */\nexport interface ConnectionStep4AuthenticationFailed {\n  meta: ConnectionStep4AuthenticationFailedMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: ConnectionStep4AuthenticationFailedPayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'authenticationFailed';\n}\n\n/**\n * Metadata for this connection step message.\n */\nexport interface ConnectionStep4AuthenticationFailedMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface ConnectionStep4AuthenticationFailedPayload {\n  message?: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * Message sent by Bridge to all Desktop Agent when an agent joins or leaves the bridge,\n * includes the details of all agents, the change made and the expected channel state for\n * all agents.\n *\n * A message used during the connection flow for a Desktop Agent to the Bridge. Used for\n * messages sent in either direction.\n */\nexport interface ConnectionStep6ConnectedAgentsUpdate {\n  meta: ConnectionStep6ConnectedAgentsUpdateMeta;\n  /**\n   * The message payload, containing data pertaining to this connection step.\n   */\n  payload: ConnectionStep6ConnectedAgentsUpdatePayload;\n  /**\n   * Identifies the type of the connection step message.\n   */\n  type: 'connectedAgentsUpdate';\n}\n\n/**\n * Metadata for this connection step message.\n */\nexport interface ConnectionStep6ConnectedAgentsUpdateMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload, containing data pertaining to this connection step.\n */\nexport interface ConnectionStep6ConnectedAgentsUpdatePayload {\n  /**\n   * Should be set when an agent first connects to the bridge and provide its assigned name.\n   */\n  addAgent?: string;\n  /**\n   * Desktop Agent Bridge implementation metadata of all connected agents.\n   */\n  allAgents: DesktopAgentImplementationMetadata[];\n  /**\n   * The updated state of channels that should be adopted by the agents. Should only be set\n   * when an agent is connecting to the bridge.\n   */\n  channelsState?: { [key: string]: Context[] };\n  /**\n   * Should be set when an agent disconnects from the bridge and provide the name that no\n   * longer is assigned.\n   */\n  removeAgent?: string;\n}\n\n/**\n * Includes the name assigned to the Desktop Agent by the Bridge.\n *\n * Metadata relating to the FDC3 Desktop Agent implementation and its provider.\n */\nexport interface DesktopAgentImplementationMetadata {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a particular Desktop\n   * Agent.\n   */\n  desktopAgent: string;\n  /**\n   * The version number of the FDC3 specification that the implementation provides.\n   * The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  fdc3Version: string;\n  /**\n   * Metadata indicating whether the Desktop Agent implements optional features of\n   * the Desktop Agent API.\n   */\n  optionalFeatures: OptionalFeatures;\n  /**\n   * The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42,\n   * OpenFin etc.).\n   */\n  provider: string;\n  /**\n   * The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\n   */\n  providerVersion?: string;\n}\n\n/**\n * Identifies the type of the connection step message.\n */\n\n/**\n * A response to a findInstances request that contains an error.\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface FindInstancesAgentErrorResponse {\n  meta: FindInstancesAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: PayloadClass;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findInstancesResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface FindInstancesAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface PayloadClass {\n  error: FindInstancesErrors;\n}\n\n/**\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n *\n * Should be set if the raiseIntent request returned an error.\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n *\n * Array of error message strings for responses that were not returned to the bridge before\n * the timeout or because an error occurred. Should be the same length as the `errorSources`\n * array and ordered the same. May be omitted if all sources responded without errors.\n *\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n */\nexport type FindInstancesErrors =\n  | 'DesktopAgentNotFound'\n  | 'IntentDeliveryFailed'\n  | 'MalformedContext'\n  | 'NoAppsFound'\n  | 'ResolverTimeout'\n  | 'ResolverUnavailable'\n  | 'TargetAppUnavailable'\n  | 'TargetInstanceUnavailable'\n  | 'UserCancelledResolution'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'IntentListenerConflict'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request for details of instances of a particular app\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface FindInstancesAgentRequest {\n  meta: FindInstancesAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindInstancesAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findInstancesRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface FindInstancesAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceIdentifier;\n  timestamp: Date;\n}\n\n/**\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Optional field that represents the destination that the request should be routed to. Must\n * be set by the Desktop Agent for API calls that include a target app parameter and must\n * include the name of the Desktop Agent hosting the target application.\n *\n * Represents identifiers that MUST include the Desktop Agent name and MAY identify a\n * specific app or instance.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n * be set by the bridge.\n *\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface DestinationObject {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindInstancesAgentRequestPayload {\n  app: AppIdentifier;\n}\n\n/**\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface AppIdentifier {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent?: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to a findInstances request.\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface FindInstancesAgentResponse {\n  meta: AgentResponseMetadata;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindInstancesAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findInstancesResponse';\n}\n\n/**\n * The message payload contains a flag indicating whether the API call was successful, plus\n * any return values for the FDC3 API function called, or indicating that the request\n * resulted in an error and including a standardized error message.\n *\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindInstancesAgentResponsePayload {\n  appIdentifiers: AppMetadata[];\n}\n\n/**\n * Extends an `AppIdentifier`, describing an application or instance of an application, with\n * additional descriptive metadata that is usually provided by an FDC3 App Directory that\n * the Desktop Agent connects to.\n *\n * The additional information from an app directory can aid in rendering UI elements, such\n * as a launcher menu or resolver UI. This includes a title, description, tooltip and icon\n * and screenshot URLs.\n *\n * Note that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the\n * `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\n */\nexport interface AppMetadata {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * A longer, multi-paragraph description for the application that could include markup.\n   */\n  description?: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent?: string;\n  /**\n   * A list of icon URLs for the application that can be used to render UI elements.\n   */\n  icons?: Icon[];\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  /**\n   * An optional set of, implementation specific, metadata fields that can be used to\n   * disambiguate instances, such as a window title or screen position. Must only be set if\n   * `instanceId` is set.\n   */\n  instanceMetadata?: { [key: string]: any };\n  /**\n   * The 'friendly' app name.\n   * This field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now\n   * require an `AppIdentifier` wth `appId` set.\n   * Note that for display purposes the `title` field should be used, if set, in preference to\n   * this field.\n   */\n  name?: string;\n  /**\n   * The type of output returned for any intent specified during resolution. May express a\n   * particular context type (e.g. \"fdc3.instrument\"), channel (e.g. \"channel\") or a channel\n   * that will receive a specified type (e.g. \"channel<fdc3.instrument>\").\n   */\n  resultType?: null | string;\n  /**\n   * Images representing the app in common usage scenarios that can be used to render UI\n   * elements.\n   */\n  screenshots?: Image[];\n  /**\n   * A more user-friendly application title that can be used to render UI elements.\n   */\n  title?: string;\n  /**\n   * A tooltip for the application that can be used to render UI elements.\n   */\n  tooltip?: string;\n  /**\n   * The Version of the application.\n   */\n  version?: string;\n}\n\n/**\n * Describes an Icon image that may be used to represent the application.\n */\nexport interface Icon {\n  /**\n   * The icon dimension, formatted as `<height>x<width>`.\n   */\n  size?: string;\n  /**\n   * The icon url.\n   */\n  src: string;\n  /**\n   * Icon media type. If not present the Desktop Agent may use the src file extension.\n   */\n  type?: string;\n}\n\n/**\n * Describes an image file, typically a screenshot, that often represents the application in\n * a common usage scenario.\n */\nexport interface Image {\n  /**\n   * Caption for the image.\n   */\n  label?: string;\n  /**\n   * The image dimension, formatted as `<height>x<width>`.\n   */\n  size?: string;\n  /**\n   * The image url.\n   */\n  src: string;\n  /**\n   * Image media type. If not present the Desktop Agent may use the src file extension.\n   */\n  type?: string;\n}\n\n/**\n * A response to a findInstances request that contains an error.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface FindInstancesBridgeErrorResponse {\n  meta: FindInstancesBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: MessagePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findInstancesResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface FindInstancesBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface MessagePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * A request for details of instances of a particular app\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface FindInstancesBridgeRequest {\n  meta: FindInstancesBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindInstancesBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findInstancesRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface FindInstancesBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSourceObject;\n  timestamp: Date;\n}\n\n/**\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself.\n *\n * Field that represents the source application that a request or response was received\n * from, or the source Desktop Agent if it issued the request or response itself.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Optional field that represents the destination that the request should be routed to. Must\n * be set by the Desktop Agent for API calls that include a target app parameter and must\n * include the name of the Desktop Agent hosting the target application.\n *\n * Represents identifiers that MUST include the Desktop Agent name and MAY identify a\n * specific app or instance.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n * be set by the bridge.\n *\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n */\nexport interface MetaSourceObject {\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId?: string;\n  /**\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   *\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   */\n  desktopAgent: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindInstancesBridgeRequestPayload {\n  app: AppIdentifier;\n}\n\n/**\n * A response to a findInstances request.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface FindInstancesBridgeResponse {\n  meta: BridgeResponseMessageMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindInstancesBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findInstancesResponse';\n}\n\n/**\n * The message payload contains a flag indicating whether the API call was successful, plus\n * any return values for the FDC3 API function called, or indicating that the request\n * resulted in an error and including a standardized error message.\n *\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindInstancesBridgeResponsePayload {\n  appIdentifiers: AppMetadata[];\n}\n\n/**\n * A response to a findIntent request that contains an error.\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface FindIntentAgentErrorResponse {\n  meta: FindIntentAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: FindIntentAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface FindIntentAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface FindIntentAgentErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request for details of apps available to resolve a particular intent and context pair.\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface FindIntentAgentRequest {\n  meta: FindIntentAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface FindIntentAgentRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceIdentifier;\n  timestamp: Date;\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentAgentRequestPayload {\n  context?: Context;\n  intent: string;\n  resultType?: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to a findIntent request.\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface FindIntentAgentResponse {\n  meta: FindIntentAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindIntentAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface FindIntentAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindIntentAgentResponsePayload {\n  appIntent: AppIntent;\n}\n\n/**\n * An interface that relates an intent to apps.\n */\nexport interface AppIntent {\n  /**\n   * Details of applications that can resolve the intent.\n   */\n  apps: AppMetadata[];\n  /**\n   * Details of the intent whose relationship to resolving applications is being described.\n   */\n  intent: IntentMetadata;\n}\n\n/**\n * Details of the intent whose relationship to resolving applications is being described.\n *\n * Metadata describing an Intent.\n */\nexport interface IntentMetadata {\n  /**\n   * Display name for the intent.\n   */\n  displayName?: string;\n  /**\n   * The unique name of the intent that can be invoked by the raiseIntent call.\n   */\n  name: string;\n}\n\n/**\n * A response to a findIntent request that contains an error.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface FindIntentBridgeErrorResponse {\n  meta: FindIntentBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: FindIntentBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface FindIntentBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface FindIntentBridgeErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * A request for details of apps available to resolve a particular intent and context pair.\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface FindIntentBridgeRequest {\n  meta: FindIntentBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface FindIntentBridgeRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: BridgeParticipantIdentifier;\n  timestamp: Date;\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentBridgeRequestPayload {\n  context?: Context;\n  intent: string;\n  resultType?: string;\n}\n\n/**\n * A response to a findIntent request.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface FindIntentBridgeResponse {\n  meta: FindIntentBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindIntentBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface FindIntentBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindIntentBridgeResponsePayload {\n  appIntent: AppIntent;\n}\n\n/**\n * A response to a findIntentsByContext request that contains an error.\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface FindIntentsByContextAgentErrorResponse {\n  meta: FindIntentsByContextAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: FindIntentsByContextAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentsByContextResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface FindIntentsByContextAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface FindIntentsByContextAgentErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request for details of intents and apps available to resolve them for a particular\n * context.\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface FindIntentsByContextAgentRequest {\n  meta: FindIntentsByContextAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentsByContextAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentsByContextRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface FindIntentsByContextAgentRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentsByContextAgentRequestPayload {\n  context: Context;\n  resultType?: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to a findIntentsByContext request.\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface FindIntentsByContextAgentResponse {\n  meta: FindIntentsByContextAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindIntentsByContextAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentsByContextResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface FindIntentsByContextAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindIntentsByContextAgentResponsePayload {\n  appIntents: AppIntent[];\n}\n\n/**\n * A response to a findIntentsByContext request that contains an error.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface FindIntentsByContextBridgeErrorResponse {\n  meta: FindIntentsByContextBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: FindIntentsByContextBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentsByContextResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface FindIntentsByContextBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface FindIntentsByContextBridgeErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * A request for details of intents and apps available to resolve them for a particular\n * context.\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface FindIntentsByContextBridgeRequest {\n  meta: FindIntentsByContextBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: FindIntentsByContextBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'findIntentsByContextRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface FindIntentsByContextBridgeRequestMeta {\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: BridgeParticipantIdentifier;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface FindIntentsByContextBridgeRequestPayload {\n  context: Context;\n  resultType?: string;\n}\n\n/**\n * A response to a findIntentsByContext request.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface FindIntentsByContextBridgeResponse {\n  meta: FindIntentsByContextBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: FindIntentsByContextBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'findIntentsByContextResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface FindIntentsByContextBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface FindIntentsByContextBridgeResponsePayload {\n  appIntents: AppIntent[];\n}\n\n/**\n * A response to a getAppMetadata request that contains an error.\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface GetAppMetadataAgentErrorResponse {\n  meta: GetAppMetadataAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: GetAppMetadataAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getAppMetadataResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface GetAppMetadataAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface GetAppMetadataAgentErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request for metadata about an app\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface GetAppMetadataAgentRequest {\n  meta: GetAppMetadataAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetAppMetadataAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getAppMetadataRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface GetAppMetadataAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceIdentifier;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetAppMetadataAgentRequestPayload {\n  app: AppObject;\n}\n\n/**\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface AppObject {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to a getAppMetadata request.\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface GetAppMetadataAgentResponse {\n  meta: GetAppMetadataAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: GetAppMetadataAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getAppMetadataResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface GetAppMetadataAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface GetAppMetadataAgentResponsePayload {\n  appMetadata: AppMetadata;\n}\n\n/**\n * A response to a getAppMetadata request that contains an error.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface GetAppMetadataBridgeErrorResponse {\n  meta: GetAppMetadataBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: GetAppMetadataBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getAppMetadataResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface GetAppMetadataBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface GetAppMetadataBridgeErrorResponsePayload {\n  error: FindInstancesErrors;\n}\n\n/**\n * A request for metadata about an app\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface GetAppMetadataBridgeRequest {\n  meta: GetAppMetadataBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: GetAppMetadataBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'getAppMetadataRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface GetAppMetadataBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface GetAppMetadataBridgeRequestPayload {\n  app: AppObject;\n}\n\n/**\n * A response to a getAppMetadata request.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface GetAppMetadataBridgeResponse {\n  meta: GetAppMetadataBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: GetAppMetadataBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'getAppMetadataResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface GetAppMetadataBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface GetAppMetadataBridgeResponsePayload {\n  appMetadata: AppMetadata;\n}\n\n/**\n * A response to an open request that contains an error\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface OpenAgentErrorResponse {\n  meta: OpenAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: OpenAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'openResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface OpenAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface OpenAgentErrorResponsePayload {\n  error: OpenErrorResponsePayload;\n}\n\n/**\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Array of error message strings for responses that were not returned to the bridge before\n * the timeout or because an error occurred. Should be the same length as the `errorSources`\n * array and ordered the same. May be omitted if all sources responded without errors.\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type OpenErrorResponsePayload =\n  | 'AppNotFound'\n  | 'AppTimeout'\n  | 'DesktopAgentNotFound'\n  | 'ErrorOnLaunch'\n  | 'MalformedContext'\n  | 'ResolverUnavailable'\n  | 'ApiTimeout'\n  | 'InvalidArguments'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to open an application\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface OpenAgentRequest {\n  meta: OpenAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: OpenAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'openRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface OpenAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface OpenAgentRequestPayload {\n  /**\n   * The application to open on the specified Desktop Agent\n   */\n  app: AppToOpen;\n  context?: Context;\n}\n\n/**\n * The application to open on the specified Desktop Agent\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface AppToOpen {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to an open request\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface OpenAgentResponse {\n  meta: OpenAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: OpenAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'openResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface OpenAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface OpenAgentResponsePayload {\n  appIdentifier: AppIdentifier;\n}\n\n/**\n * A response to an open request that contains an error\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface OpenBridgeErrorResponse {\n  meta: OpenBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: OpenBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'openResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface OpenBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface OpenBridgeErrorResponsePayload {\n  error: OpenErrorResponsePayload;\n}\n\n/**\n * A request to open an application\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface OpenBridgeRequest {\n  meta: OpenBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: OpenBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'openRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface OpenBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: DestinationObject;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface OpenBridgeRequestPayload {\n  /**\n   * The application to open on the specified Desktop Agent\n   */\n  app: AppToOpen;\n  context?: Context;\n}\n\n/**\n * A response to an open request\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface OpenBridgeResponse {\n  meta: OpenBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: OpenBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'openResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface OpenBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface OpenBridgeResponsePayload {\n  appIdentifier: AppIdentifier;\n}\n\n/**\n * A request to broadcast on a PrivateChannel.\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelBroadcastAgentRequest {\n  meta: PrivateChannelBroadcastAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelBroadcastAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.broadcast';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelBroadcastAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n *\n * Optional field that represents the destination that the request should be routed to. Must\n * be set by the Desktop Agent for API calls that include a target app parameter and must\n * include the name of the Desktop Agent hosting the target application.\n *\n * Represents identifiers that MUST include the Desktop Agent name and MAY identify a\n * specific app or instance.\n *\n * Field that represents the source application that the request was received from, or the\n * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n * be set by the bridge.\n */\nexport interface MetaDestination {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelBroadcastAgentRequestPayload {\n  /**\n   * The Id of the PrivateChannel that the broadcast was sent on\n   */\n  channelId: string;\n  /**\n   * The context object that was the payload of a broadcast message.\n   */\n  context: Context;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to broadcast on a PrivateChannel.\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelBroadcastBridgeRequest {\n  meta: PrivateChannelBroadcastBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelBroadcastBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.broadcast';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface PrivateChannelBroadcastBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelBroadcastBridgeRequestPayload {\n  /**\n   * The Id of the PrivateChannel that the broadcast was sent on\n   */\n  channelId: string;\n  /**\n   * The context object that was the payload of a broadcast message.\n   */\n  context: Context;\n}\n\n/**\n * A request to forward on an EventListenerAdded event, relating to a PrivateChannel\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelEventListenerAddedAgentRequest {\n  meta: PrivateChannelEventListenerAddedAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelEventListenerAddedAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.eventListenerAdded';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelEventListenerAddedAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelEventListenerAddedAgentRequestPayload {\n  /**\n   * The id of the PrivateChannel that the event listener was added to.\n   */\n  channelId: string;\n  listenerType: PrivateChannelEventType;\n}\n\n/**\n * Type defining valid type strings for Private Channel events.\n */\nexport type PrivateChannelEventType = 'addContextListener' | 'unsubscribe' | 'disconnect';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to forward on an EventListenerAdded event, relating to a PrivateChannel\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelEventListenerAddedBridgeRequest {\n  meta: PrivateChannelEventListenerAddedBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelEventListenerAddedBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.eventListenerAdded';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface PrivateChannelEventListenerAddedBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelEventListenerAddedBridgeRequestPayload {\n  /**\n   * The id of the PrivateChannel that the event listener was added to.\n   */\n  channelId: string;\n  listenerType: PrivateChannelEventType;\n}\n\n/**\n * A request to forward on an EventListenerRemoved event, relating to a PrivateChannel\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelEventListenerRemovedAgentRequest {\n  meta: PrivateChannelEventListenerRemovedAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelEventListenerRemovedAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.eventListenerRemoved';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelEventListenerRemovedAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelEventListenerRemovedAgentRequestPayload {\n  /**\n   * The id of the PrivateChannel that the event listener was removed from.\n   */\n  channelId: string;\n  listenerType: PrivateChannelEventType;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to forward on an EventListenerRemoved event, relating to a PrivateChannel\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelEventListenerRemovedBridgeRequest {\n  meta: PrivateChannelEventListenerRemovedBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelEventListenerRemovedBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.eventListenerRemoved';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface PrivateChannelEventListenerRemovedBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelEventListenerRemovedBridgeRequestPayload {\n  /**\n   * The id of the PrivateChannel that the event listener was removed from.\n   */\n  channelId: string;\n  listenerType: PrivateChannelEventType;\n}\n\n/**\n * A request to forward on an AddContextListener event, relating to a PrivateChannel\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelOnAddContextListenerAgentRequest {\n  meta: PrivateChannelOnAddContextListenerAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnAddContextListenerAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onAddContextListener';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelOnAddContextListenerAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnAddContextListenerAgentRequestPayload {\n  /**\n   * The id of the PrivateChannel that the context listener was added to.\n   */\n  channelId: string;\n  /**\n   * The type of the context listener added. Should be null for an untyped listener.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to forward on an AddContextListener event, relating to a PrivateChannel\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelOnAddContextListenerBridgeRequest {\n  meta: PrivateChannelOnAddContextListenerBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnAddContextListenerBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onAddContextListener';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface PrivateChannelOnAddContextListenerBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnAddContextListenerBridgeRequestPayload {\n  /**\n   * The id of the PrivateChannel that the context listener was added to.\n   */\n  channelId: string;\n  /**\n   * The type of the context listener added. Should be null for an untyped listener.\n   */\n  contextType: null | string;\n}\n\n/**\n * A request to forward on a Disconnect event, relating to a PrivateChannel\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelOnDisconnectAgentRequest {\n  meta: PrivateChannelOnDisconnectAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnDisconnectAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onDisconnect';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelOnDisconnectAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnDisconnectAgentRequestPayload {\n  /**\n   * The id of the PrivateChannel that the agent discconnected from.\n   */\n  channelId: string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to forward on a Disconnect event, relating to a PrivateChannel\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelOnDisconnectBridgeRequest {\n  meta: PrivateChannelOnDisconnectBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnDisconnectBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onDisconnect';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface PrivateChannelOnDisconnectBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnDisconnectBridgeRequestPayload {\n  /**\n   * The id of the PrivateChannel that the agent discconnected from.\n   */\n  channelId: string;\n}\n\n/**\n * A request to forward on an Unsubscribe event, relating to a PrivateChannel\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface PrivateChannelOnUnsubscribeAgentRequest {\n  meta: PrivateChannelOnUnsubscribeAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnUnsubscribeAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onUnsubscribe';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface PrivateChannelOnUnsubscribeAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source?: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnUnsubscribeAgentRequestPayload {\n  /**\n   * The id of the PrivateChannel that the context listener was unsubscribed from.\n   */\n  channelId: string;\n  /**\n   * The type of the context listener that was unsubscribed. Should be null for an untyped\n   * listener.\n   */\n  contextType: null | string;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to forward on an Unsubscribe event, relating to a PrivateChannel\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface PrivateChannelOnUnsubscribeBridgeRequest {\n  meta: ERequestMetadata;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: PrivateChannelOnUnsubscribeBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'PrivateChannel.onUnsubscribe';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface ERequestMetadata {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination?: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface PrivateChannelOnUnsubscribeBridgeRequestPayload {\n  /**\n   * The id of the PrivateChannel that the context listener was unsubscribed from.\n   */\n  channelId: string;\n  /**\n   * The type of the context listener that was unsubscribed. Should be null for an untyped\n   * listener.\n   */\n  contextType: null | string;\n}\n\n/**\n * A response to a request to raise an intent that contains an error.\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface RaiseIntentAgentErrorResponse {\n  meta: RaiseIntentAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: RaiseIntentAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface RaiseIntentAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Used if a raiseIntent request resulted in an error.\n *\n * Error message payload containing an standardized error string.\n */\nexport interface RaiseIntentAgentErrorResponsePayload {\n  /**\n   * Should be set if the raiseIntent request returned an error.\n   */\n  error: FindInstancesErrors;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A request to raise an intent.\n *\n * A request message from a Desktop Agent to the Bridge.\n */\nexport interface RaiseIntentAgentRequest {\n  meta: RaiseIntentAgentRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: RaiseIntentAgentRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'raiseIntentRequest';\n}\n\n/**\n * Metadata for a request message sent by Desktop Agents to the Bridge.\n */\nexport interface RaiseIntentAgentRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself.\n   */\n  source: SourceObject;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface RaiseIntentAgentRequestPayload {\n  app: AppDestinationIdentifier;\n  context: Context;\n  intent: string;\n}\n\n/**\n * Field that represents a destination App on a remote Desktop Agent that a request is to be\n * sent to.\n *\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n *\n * Array of DesktopAgentIdentifiers for responses that were not returned to the bridge\n * before the timeout or because an error occurred. May be omitted if all sources responded\n * without errors. MUST include the `desktopAgent` field when returned by the bridge.\n *\n * Array of DesktopAgentIdentifiers for the sources that generated responses to the request.\n * Will contain a single value for individual responses and multiple values for responses\n * that were collated by the bridge. May be omitted if all sources errored. MUST include the\n * `desktopAgent` field when returned by the bridge.\n *\n * Field that represents a destination Desktop Agent that a request is to be sent to.\n *\n * Identifies an application, or instance of an application, and is used to target FDC3 API\n * calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application\n * instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific\n * instance of the application that may be addressed using that Id.\n *\n * Field that represents the source application that a request or response was received\n * from.\n *\n * Identifier for the app instance that was selected (or started) to resolve the intent.\n * `source.instanceId` MUST be set, indicating the specific app instance that\n * received the intent.\n */\nexport interface AppDestinationIdentifier {\n  /**\n   * Used in Desktop Agent Bridging to attribute or target a message to a\n   * particular Desktop Agent.\n   *\n   * The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to\n   * identify the Desktop Agent to target.\n   */\n  desktopAgent: string;\n  /**\n   * The unique application identifier located within a specific application directory\n   * instance. An example of an appId might be 'app@sub.root'.\n   */\n  appId: string;\n  /**\n   * An optional instance identifier, indicating that this object represents a specific\n   * instance of the application described.\n   */\n  instanceId?: string;\n  [property: string]: any;\n}\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Request' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A response to a request to raise an intent.\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface RaiseIntentAgentResponse {\n  meta: RaiseIntentAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: RaiseIntentAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface RaiseIntentAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface RaiseIntentAgentResponsePayload {\n  /**\n   * Used if the raiseIntent request was successfully resolved.\n   */\n  intentResolution: IntentResolution;\n}\n\n/**\n * Used if the raiseIntent request was successfully resolved.\n *\n * IntentResolution provides a standard format for data returned upon resolving an intent.\n *\n * ```javascript\n * //resolve a \"Chain\" type intent\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n *\n * //resolve a \"Client-Service\" type intent with a data response or a Channel\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n * try {\n * const result = await resolution.getResult();\n * if (result && result.broadcast) {\n * console.log(`${resolution.source} returned a channel with id ${result.id}`);\n * } else if (result){\n * console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n * } else {\n * console.error(`${resolution.source} didn't return data`\n * }\n * } catch(error) {\n * console.error(`${resolution.source} returned an error: ${error}`);\n * }\n *\n * // Use metadata about the resolving app instance to target a further intent\n * await agent.raiseIntent(\"intentName\", context, resolution.source);\n * ```\n */\nexport interface IntentResolution {\n  /**\n   * The intent that was raised. May be used to determine which intent the user\n   * chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  intent: string;\n  /**\n   * Identifier for the app instance that was selected (or started) to resolve the intent.\n   * `source.instanceId` MUST be set, indicating the specific app instance that\n   * received the intent.\n   */\n  source: AppIdentifier;\n}\n\n/**\n * A response to a request to raise an intent that contains an error.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface RaiseIntentBridgeErrorResponse {\n  meta: RaiseIntentBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: RaiseIntentBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface RaiseIntentBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Used if a raiseIntent request resulted in an error.\n *\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface RaiseIntentBridgeErrorResponsePayload {\n  /**\n   * Should be set if the raiseIntent request returned an error.\n   */\n  error: FindInstancesErrors;\n}\n\n/**\n * A request to raise an intent.\n *\n * A request message forwarded from the Bridge onto a Desktop Agent connected to it.\n */\nexport interface RaiseIntentBridgeRequest {\n  meta: RaiseIntentBridgeRequestMeta;\n  /**\n   * The message payload typically contains the arguments to FDC3 API functions.\n   */\n  payload: RaiseIntentBridgeRequestPayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Request' appended.\n   */\n  type: 'raiseIntentRequest';\n}\n\n/**\n * Metadata required in a request message forwarded on by the Bridge\n */\nexport interface RaiseIntentBridgeRequestMeta {\n  /**\n   * Optional field that represents the destination that the request should be routed to. Must\n   * be set by the Desktop Agent for API calls that include a target app parameter and must\n   * include the name of the Desktop Agent hosting the target application.\n   */\n  destination: MetaDestination;\n  requestUuid: string;\n  /**\n   * Field that represents the source application that the request was received from, or the\n   * source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST\n   * be set by the bridge.\n   */\n  source: MetaSource;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains the arguments to FDC3 API functions.\n */\nexport interface RaiseIntentBridgeRequestPayload {\n  app: AppDestinationIdentifier;\n  context: Context;\n  intent: string;\n}\n\n/**\n * A response to a request to raise an intent.\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface RaiseIntentBridgeResponse {\n  meta: RaiseIntentBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: RaiseIntentBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface RaiseIntentBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface RaiseIntentBridgeResponsePayload {\n  /**\n   * Used if the raiseIntent request was successfully resolved.\n   */\n  intentResolution: IntentResolution;\n}\n\n/**\n * A secondary response to a request to raise an intent used to deliver the intent result,\n * which contains an error\n *\n * A response message from a Desktop Agent to the Bridge containing an error, to be used in\n * preference to the standard response when an error needs to be returned.\n */\nexport interface RaiseIntentResultAgentErrorResponse {\n  meta: RaiseIntentResultAgentErrorResponseMeta;\n  /**\n   * Error message payload containing an standardized error string.\n   */\n  payload: RaiseIntentResultAgentErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResultResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface RaiseIntentResultAgentErrorResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * Error message payload containing an standardized error string.\n */\nexport interface RaiseIntentResultAgentErrorResponsePayload {\n  error: RaiseIntentResultErrorMessage;\n}\n\n/**\n * Array of error message strings for responses that were not returned to the bridge before\n * the timeout or because an error occurred. Should be the same length as the `errorSources`\n * array and ordered the same. May be omitted if all sources responded without errors.\n *\n * Constants representing the errors that can be encountered when calling the `open` method\n * on the DesktopAgent object (`fdc3`).\n *\n * Constants representing the errors that can be encountered when calling the\n * `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or\n * `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\n */\nexport type RaiseIntentResultErrorMessage =\n  | 'IntentHandlerRejected'\n  | 'NoResultReturned'\n  | 'ApiTimeout'\n  | 'AgentDisconnected'\n  | 'NotConnectedToBridge'\n  | 'ResponseToBridgeTimedOut'\n  | 'MalformedMessage';\n\n/**\n * Identifies the type of the message and it is typically set to the FDC3 function name that\n * the message relates to, e.g. 'findIntent', with 'Response' appended.\n *\n * Unique identifier for a request or event message. Required in all message types.\n *\n * Unique identifier for a response to a specific message and must always be accompanied by\n * a RequestUuid.\n */\n\n/**\n * A secondary response to a request to raise an intent used to deliver the intent result\n *\n * A response message from a Desktop Agent to the Bridge.\n */\nexport interface RaiseIntentResultAgentResponse {\n  meta: RaiseIntentResultAgentResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: RaiseIntentResultAgentResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResultResponse';\n}\n\n/**\n * Metadata for a response messages sent by a Desktop Agent to the Bridge\n */\nexport interface RaiseIntentResultAgentResponseMeta {\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface RaiseIntentResultAgentResponsePayload {\n  intentResult: IntentResult;\n}\n\nexport interface IntentResult {\n  context?: Context;\n  channel?: Channel;\n}\n\n/**\n * Represents a context channel that applications can use to send and receive\n * context data.\n *\n * Please note that There are differences in behavior when you interact with a\n * User channel via the `DesktopAgent` interface and the `Channel` interface.\n * Specifically, when 'joining' a User channel or adding a context listener\n * when already joined to a channel via the `DesktopAgent` interface, existing\n * context (matching the type of the context listener) on the channel is\n * received by the context listener immediately. Whereas, when a context\n * listener is added via the Channel interface, context is not received\n * automatically, but may be retrieved manually via the `getCurrentContext()`\n * function.\n */\nexport interface Channel {\n  /**\n   * Channels may be visualized and selectable by users. DisplayMetadata may be used to\n   * provide hints on how to see them.\n   * For App channels, displayMetadata would typically not be present.\n   */\n  displayMetadata?: DisplayMetadata;\n  /**\n   * Constant that uniquely identifies this channel.\n   */\n  id: string;\n  /**\n   * Uniquely defines each channel type.\n   * Can be \"user\", \"app\" or \"private\".\n   */\n  type: Type;\n}\n\n/**\n * Channels may be visualized and selectable by users. DisplayMetadata may be used to\n * provide hints on how to see them.\n * For App channels, displayMetadata would typically not be present.\n *\n * A system channel will be global enough to have a presence across many apps. This gives us\n * some hints\n * to render them in a standard way. It is assumed it may have other properties too, but if\n * it has these,\n * this is their meaning.\n */\nexport interface DisplayMetadata {\n  /**\n   * The color that should be associated within this channel when displaying this channel in a\n   * UI, e.g: `0xFF0000`.\n   */\n  color?: string;\n  /**\n   * A URL of an image that can be used to display this channel.\n   */\n  glyph?: string;\n  /**\n   * A user-readable name for this channel, e.g: `\"Red\"`.\n   */\n  name?: string;\n}\n\n/**\n * Uniquely defines each channel type.\n * Can be \"user\", \"app\" or \"private\".\n */\nexport type Type = 'app' | 'private' | 'user';\n\n/**\n * A secondary response to a request to raise an intent used to deliver the intent result,\n * which contains an error\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request, used where all connected agents returned errors.\n */\nexport interface RaiseIntentResultBridgeErrorResponse {\n  meta: RaiseIntentResultBridgeErrorResponseMeta;\n  /**\n   * The error message payload contains details of an error return to the app or agent that\n   * raised the original request.\n   */\n  payload: RaiseIntentResultBridgeErrorResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResultResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface RaiseIntentResultBridgeErrorResponseMeta {\n  errorDetails: ResponseErrorDetail[];\n  errorSources: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  timestamp: Date;\n}\n\n/**\n * The error message payload contains details of an error return to the app or agent that\n * raised the original request.\n */\nexport interface RaiseIntentResultBridgeErrorResponsePayload {\n  error: RaiseIntentResultErrorMessage;\n}\n\n/**\n * A secondary response to a request to raise an intent used to deliver the intent result\n *\n * A response message from the Bridge back to the original Desktop Agent that raised the\n * request.\n */\nexport interface RaiseIntentResultBridgeResponse {\n  meta: RaiseIntentResultBridgeResponseMeta;\n  /**\n   * The message payload typically contains return values for FDC3 API functions.\n   */\n  payload: RaiseIntentResultBridgeResponsePayload;\n  /**\n   * Identifies the type of the message and it is typically set to the FDC3 function name that\n   * the message relates to, e.g. 'findIntent', with 'Response' appended.\n   */\n  type: 'raiseIntentResultResponse';\n}\n\n/**\n * Metadata required in a response message collated and/or forwarded on by the Bridge\n */\nexport interface RaiseIntentResultBridgeResponseMeta {\n  errorDetails?: ResponseErrorDetail[];\n  errorSources?: DesktopAgentIdentifier[];\n  requestUuid: string;\n  responseUuid: string;\n  sources?: DesktopAgentIdentifier[];\n  timestamp: Date;\n}\n\n/**\n * The message payload typically contains return values for FDC3 API functions.\n */\nexport interface RaiseIntentResultBridgeResponsePayload {\n  intentResult: IntentResult;\n}\n\n// Converts JSON strings to/from your types\n// and asserts the results of JSON.parse at runtime\nexport class Convert {\n  public static toAgentErrorResponseMessage(json: string): AgentErrorResponseMessage {\n    return cast(JSON.parse(json), r('AgentErrorResponseMessage'));\n  }\n\n  public static agentErrorResponseMessageToJson(value: AgentErrorResponseMessage): string {\n    return JSON.stringify(uncast(value, r('AgentErrorResponseMessage')), null, 2);\n  }\n\n  public static toAgentRequestMessage(json: string): AgentRequestMessage {\n    return cast(JSON.parse(json), r('AgentRequestMessage'));\n  }\n\n  public static agentRequestMessageToJson(value: AgentRequestMessage): string {\n    return JSON.stringify(uncast(value, r('AgentRequestMessage')), null, 2);\n  }\n\n  public static toAgentResponseMessage(json: string): AgentResponseMessage {\n    return cast(JSON.parse(json), r('AgentResponseMessage'));\n  }\n\n  public static agentResponseMessageToJson(value: AgentResponseMessage): string {\n    return JSON.stringify(uncast(value, r('AgentResponseMessage')), null, 2);\n  }\n\n  public static toBridgeErrorResponseMessage(json: string): BridgeErrorResponseMessage {\n    return cast(JSON.parse(json), r('BridgeErrorResponseMessage'));\n  }\n\n  public static bridgeErrorResponseMessageToJson(value: BridgeErrorResponseMessage): string {\n    return JSON.stringify(uncast(value, r('BridgeErrorResponseMessage')), null, 2);\n  }\n\n  public static toBridgeRequestMessage(json: string): BridgeRequestMessage {\n    return cast(JSON.parse(json), r('BridgeRequestMessage'));\n  }\n\n  public static bridgeRequestMessageToJson(value: BridgeRequestMessage): string {\n    return JSON.stringify(uncast(value, r('BridgeRequestMessage')), null, 2);\n  }\n\n  public static toBridgeResponseMessage(json: string): BridgeResponseMessage {\n    return cast(JSON.parse(json), r('BridgeResponseMessage'));\n  }\n\n  public static bridgeResponseMessageToJson(value: BridgeResponseMessage): string {\n    return JSON.stringify(uncast(value, r('BridgeResponseMessage')), null, 2);\n  }\n\n  public static toBroadcastAgentRequest(json: string): BroadcastAgentRequest {\n    return cast(JSON.parse(json), r('BroadcastAgentRequest'));\n  }\n\n  public static broadcastAgentRequestToJson(value: BroadcastAgentRequest): string {\n    return JSON.stringify(uncast(value, r('BroadcastAgentRequest')), null, 2);\n  }\n\n  public static toBroadcastBridgeRequest(json: string): BroadcastBridgeRequest {\n    return cast(JSON.parse(json), r('BroadcastBridgeRequest'));\n  }\n\n  public static broadcastBridgeRequestToJson(value: BroadcastBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('BroadcastBridgeRequest')), null, 2);\n  }\n\n  public static toBridgeCommonDefinitions(json: string): { [key: string]: any } {\n    return cast(JSON.parse(json), m('any'));\n  }\n\n  public static bridgeCommonDefinitionsToJson(value: { [key: string]: any }): string {\n    return JSON.stringify(uncast(value, m('any')), null, 2);\n  }\n\n  public static toConnectionStepMessage(json: string): ConnectionStepMessage {\n    return cast(JSON.parse(json), r('ConnectionStepMessage'));\n  }\n\n  public static connectionStepMessageToJson(value: ConnectionStepMessage): string {\n    return JSON.stringify(uncast(value, r('ConnectionStepMessage')), null, 2);\n  }\n\n  public static toConnectionStep2Hello(json: string): ConnectionStep2Hello {\n    return cast(JSON.parse(json), r('ConnectionStep2Hello'));\n  }\n\n  public static connectionStep2HelloToJson(value: ConnectionStep2Hello): string {\n    return JSON.stringify(uncast(value, r('ConnectionStep2Hello')), null, 2);\n  }\n\n  public static toConnectionStep3Handshake(json: string): ConnectionStep3Handshake {\n    return cast(JSON.parse(json), r('ConnectionStep3Handshake'));\n  }\n\n  public static connectionStep3HandshakeToJson(value: ConnectionStep3Handshake): string {\n    return JSON.stringify(uncast(value, r('ConnectionStep3Handshake')), null, 2);\n  }\n\n  public static toConnectionStep4AuthenticationFailed(json: string): ConnectionStep4AuthenticationFailed {\n    return cast(JSON.parse(json), r('ConnectionStep4AuthenticationFailed'));\n  }\n\n  public static connectionStep4AuthenticationFailedToJson(value: ConnectionStep4AuthenticationFailed): string {\n    return JSON.stringify(uncast(value, r('ConnectionStep4AuthenticationFailed')), null, 2);\n  }\n\n  public static toConnectionStep6ConnectedAgentsUpdate(json: string): ConnectionStep6ConnectedAgentsUpdate {\n    return cast(JSON.parse(json), r('ConnectionStep6ConnectedAgentsUpdate'));\n  }\n\n  public static connectionStep6ConnectedAgentsUpdateToJson(value: ConnectionStep6ConnectedAgentsUpdate): string {\n    return JSON.stringify(uncast(value, r('ConnectionStep6ConnectedAgentsUpdate')), null, 2);\n  }\n\n  public static toFindInstancesAgentErrorResponse(json: string): FindInstancesAgentErrorResponse {\n    return cast(JSON.parse(json), r('FindInstancesAgentErrorResponse'));\n  }\n\n  public static findInstancesAgentErrorResponseToJson(value: FindInstancesAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindInstancesAgentErrorResponse')), null, 2);\n  }\n\n  public static toFindInstancesAgentRequest(json: string): FindInstancesAgentRequest {\n    return cast(JSON.parse(json), r('FindInstancesAgentRequest'));\n  }\n\n  public static findInstancesAgentRequestToJson(value: FindInstancesAgentRequest): string {\n    return JSON.stringify(uncast(value, r('FindInstancesAgentRequest')), null, 2);\n  }\n\n  public static toFindInstancesAgentResponse(json: string): FindInstancesAgentResponse {\n    return cast(JSON.parse(json), r('FindInstancesAgentResponse'));\n  }\n\n  public static findInstancesAgentResponseToJson(value: FindInstancesAgentResponse): string {\n    return JSON.stringify(uncast(value, r('FindInstancesAgentResponse')), null, 2);\n  }\n\n  public static toFindInstancesBridgeErrorResponse(json: string): FindInstancesBridgeErrorResponse {\n    return cast(JSON.parse(json), r('FindInstancesBridgeErrorResponse'));\n  }\n\n  public static findInstancesBridgeErrorResponseToJson(value: FindInstancesBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindInstancesBridgeErrorResponse')), null, 2);\n  }\n\n  public static toFindInstancesBridgeRequest(json: string): FindInstancesBridgeRequest {\n    return cast(JSON.parse(json), r('FindInstancesBridgeRequest'));\n  }\n\n  public static findInstancesBridgeRequestToJson(value: FindInstancesBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('FindInstancesBridgeRequest')), null, 2);\n  }\n\n  public static toFindInstancesBridgeResponse(json: string): FindInstancesBridgeResponse {\n    return cast(JSON.parse(json), r('FindInstancesBridgeResponse'));\n  }\n\n  public static findInstancesBridgeResponseToJson(value: FindInstancesBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('FindInstancesBridgeResponse')), null, 2);\n  }\n\n  public static toFindIntentAgentErrorResponse(json: string): FindIntentAgentErrorResponse {\n    return cast(JSON.parse(json), r('FindIntentAgentErrorResponse'));\n  }\n\n  public static findIntentAgentErrorResponseToJson(value: FindIntentAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentAgentErrorResponse')), null, 2);\n  }\n\n  public static toFindIntentAgentRequest(json: string): FindIntentAgentRequest {\n    return cast(JSON.parse(json), r('FindIntentAgentRequest'));\n  }\n\n  public static findIntentAgentRequestToJson(value: FindIntentAgentRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentAgentRequest')), null, 2);\n  }\n\n  public static toFindIntentAgentResponse(json: string): FindIntentAgentResponse {\n    return cast(JSON.parse(json), r('FindIntentAgentResponse'));\n  }\n\n  public static findIntentAgentResponseToJson(value: FindIntentAgentResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentAgentResponse')), null, 2);\n  }\n\n  public static toFindIntentBridgeErrorResponse(json: string): FindIntentBridgeErrorResponse {\n    return cast(JSON.parse(json), r('FindIntentBridgeErrorResponse'));\n  }\n\n  public static findIntentBridgeErrorResponseToJson(value: FindIntentBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentBridgeErrorResponse')), null, 2);\n  }\n\n  public static toFindIntentBridgeRequest(json: string): FindIntentBridgeRequest {\n    return cast(JSON.parse(json), r('FindIntentBridgeRequest'));\n  }\n\n  public static findIntentBridgeRequestToJson(value: FindIntentBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentBridgeRequest')), null, 2);\n  }\n\n  public static toFindIntentBridgeResponse(json: string): FindIntentBridgeResponse {\n    return cast(JSON.parse(json), r('FindIntentBridgeResponse'));\n  }\n\n  public static findIntentBridgeResponseToJson(value: FindIntentBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentBridgeResponse')), null, 2);\n  }\n\n  public static toFindIntentsByContextAgentErrorResponse(json: string): FindIntentsByContextAgentErrorResponse {\n    return cast(JSON.parse(json), r('FindIntentsByContextAgentErrorResponse'));\n  }\n\n  public static findIntentsByContextAgentErrorResponseToJson(value: FindIntentsByContextAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextAgentErrorResponse')), null, 2);\n  }\n\n  public static toFindIntentsByContextAgentRequest(json: string): FindIntentsByContextAgentRequest {\n    return cast(JSON.parse(json), r('FindIntentsByContextAgentRequest'));\n  }\n\n  public static findIntentsByContextAgentRequestToJson(value: FindIntentsByContextAgentRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextAgentRequest')), null, 2);\n  }\n\n  public static toFindIntentsByContextAgentResponse(json: string): FindIntentsByContextAgentResponse {\n    return cast(JSON.parse(json), r('FindIntentsByContextAgentResponse'));\n  }\n\n  public static findIntentsByContextAgentResponseToJson(value: FindIntentsByContextAgentResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextAgentResponse')), null, 2);\n  }\n\n  public static toFindIntentsByContextBridgeErrorResponse(json: string): FindIntentsByContextBridgeErrorResponse {\n    return cast(JSON.parse(json), r('FindIntentsByContextBridgeErrorResponse'));\n  }\n\n  public static findIntentsByContextBridgeErrorResponseToJson(value: FindIntentsByContextBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextBridgeErrorResponse')), null, 2);\n  }\n\n  public static toFindIntentsByContextBridgeRequest(json: string): FindIntentsByContextBridgeRequest {\n    return cast(JSON.parse(json), r('FindIntentsByContextBridgeRequest'));\n  }\n\n  public static findIntentsByContextBridgeRequestToJson(value: FindIntentsByContextBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextBridgeRequest')), null, 2);\n  }\n\n  public static toFindIntentsByContextBridgeResponse(json: string): FindIntentsByContextBridgeResponse {\n    return cast(JSON.parse(json), r('FindIntentsByContextBridgeResponse'));\n  }\n\n  public static findIntentsByContextBridgeResponseToJson(value: FindIntentsByContextBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('FindIntentsByContextBridgeResponse')), null, 2);\n  }\n\n  public static toGetAppMetadataAgentErrorResponse(json: string): GetAppMetadataAgentErrorResponse {\n    return cast(JSON.parse(json), r('GetAppMetadataAgentErrorResponse'));\n  }\n\n  public static getAppMetadataAgentErrorResponseToJson(value: GetAppMetadataAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataAgentErrorResponse')), null, 2);\n  }\n\n  public static toGetAppMetadataAgentRequest(json: string): GetAppMetadataAgentRequest {\n    return cast(JSON.parse(json), r('GetAppMetadataAgentRequest'));\n  }\n\n  public static getAppMetadataAgentRequestToJson(value: GetAppMetadataAgentRequest): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataAgentRequest')), null, 2);\n  }\n\n  public static toGetAppMetadataAgentResponse(json: string): GetAppMetadataAgentResponse {\n    return cast(JSON.parse(json), r('GetAppMetadataAgentResponse'));\n  }\n\n  public static getAppMetadataAgentResponseToJson(value: GetAppMetadataAgentResponse): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataAgentResponse')), null, 2);\n  }\n\n  public static toGetAppMetadataBridgeErrorResponse(json: string): GetAppMetadataBridgeErrorResponse {\n    return cast(JSON.parse(json), r('GetAppMetadataBridgeErrorResponse'));\n  }\n\n  public static getAppMetadataBridgeErrorResponseToJson(value: GetAppMetadataBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataBridgeErrorResponse')), null, 2);\n  }\n\n  public static toGetAppMetadataBridgeRequest(json: string): GetAppMetadataBridgeRequest {\n    return cast(JSON.parse(json), r('GetAppMetadataBridgeRequest'));\n  }\n\n  public static getAppMetadataBridgeRequestToJson(value: GetAppMetadataBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataBridgeRequest')), null, 2);\n  }\n\n  public static toGetAppMetadataBridgeResponse(json: string): GetAppMetadataBridgeResponse {\n    return cast(JSON.parse(json), r('GetAppMetadataBridgeResponse'));\n  }\n\n  public static getAppMetadataBridgeResponseToJson(value: GetAppMetadataBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('GetAppMetadataBridgeResponse')), null, 2);\n  }\n\n  public static toOpenAgentErrorResponse(json: string): OpenAgentErrorResponse {\n    return cast(JSON.parse(json), r('OpenAgentErrorResponse'));\n  }\n\n  public static openAgentErrorResponseToJson(value: OpenAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('OpenAgentErrorResponse')), null, 2);\n  }\n\n  public static toOpenAgentRequest(json: string): OpenAgentRequest {\n    return cast(JSON.parse(json), r('OpenAgentRequest'));\n  }\n\n  public static openAgentRequestToJson(value: OpenAgentRequest): string {\n    return JSON.stringify(uncast(value, r('OpenAgentRequest')), null, 2);\n  }\n\n  public static toOpenAgentResponse(json: string): OpenAgentResponse {\n    return cast(JSON.parse(json), r('OpenAgentResponse'));\n  }\n\n  public static openAgentResponseToJson(value: OpenAgentResponse): string {\n    return JSON.stringify(uncast(value, r('OpenAgentResponse')), null, 2);\n  }\n\n  public static toOpenBridgeErrorResponse(json: string): OpenBridgeErrorResponse {\n    return cast(JSON.parse(json), r('OpenBridgeErrorResponse'));\n  }\n\n  public static openBridgeErrorResponseToJson(value: OpenBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('OpenBridgeErrorResponse')), null, 2);\n  }\n\n  public static toOpenBridgeRequest(json: string): OpenBridgeRequest {\n    return cast(JSON.parse(json), r('OpenBridgeRequest'));\n  }\n\n  public static openBridgeRequestToJson(value: OpenBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('OpenBridgeRequest')), null, 2);\n  }\n\n  public static toOpenBridgeResponse(json: string): OpenBridgeResponse {\n    return cast(JSON.parse(json), r('OpenBridgeResponse'));\n  }\n\n  public static openBridgeResponseToJson(value: OpenBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('OpenBridgeResponse')), null, 2);\n  }\n\n  public static toPrivateChannelBroadcastAgentRequest(json: string): PrivateChannelBroadcastAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelBroadcastAgentRequest'));\n  }\n\n  public static privateChannelBroadcastAgentRequestToJson(value: PrivateChannelBroadcastAgentRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelBroadcastAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelBroadcastBridgeRequest(json: string): PrivateChannelBroadcastBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelBroadcastBridgeRequest'));\n  }\n\n  public static privateChannelBroadcastBridgeRequestToJson(value: PrivateChannelBroadcastBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelBroadcastBridgeRequest')), null, 2);\n  }\n\n  public static toPrivateChannelEventListenerAddedAgentRequest(\n    json: string\n  ): PrivateChannelEventListenerAddedAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelEventListenerAddedAgentRequest'));\n  }\n\n  public static privateChannelEventListenerAddedAgentRequestToJson(\n    value: PrivateChannelEventListenerAddedAgentRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelEventListenerAddedAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelEventListenerAddedBridgeRequest(\n    json: string\n  ): PrivateChannelEventListenerAddedBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelEventListenerAddedBridgeRequest'));\n  }\n\n  public static privateChannelEventListenerAddedBridgeRequestToJson(\n    value: PrivateChannelEventListenerAddedBridgeRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelEventListenerAddedBridgeRequest')), null, 2);\n  }\n\n  public static toPrivateChannelEventListenerRemovedAgentRequest(\n    json: string\n  ): PrivateChannelEventListenerRemovedAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelEventListenerRemovedAgentRequest'));\n  }\n\n  public static privateChannelEventListenerRemovedAgentRequestToJson(\n    value: PrivateChannelEventListenerRemovedAgentRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelEventListenerRemovedAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelEventListenerRemovedBridgeRequest(\n    json: string\n  ): PrivateChannelEventListenerRemovedBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelEventListenerRemovedBridgeRequest'));\n  }\n\n  public static privateChannelEventListenerRemovedBridgeRequestToJson(\n    value: PrivateChannelEventListenerRemovedBridgeRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelEventListenerRemovedBridgeRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnAddContextListenerAgentRequest(\n    json: string\n  ): PrivateChannelOnAddContextListenerAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnAddContextListenerAgentRequest'));\n  }\n\n  public static privateChannelOnAddContextListenerAgentRequestToJson(\n    value: PrivateChannelOnAddContextListenerAgentRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnAddContextListenerAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnAddContextListenerBridgeRequest(\n    json: string\n  ): PrivateChannelOnAddContextListenerBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnAddContextListenerBridgeRequest'));\n  }\n\n  public static privateChannelOnAddContextListenerBridgeRequestToJson(\n    value: PrivateChannelOnAddContextListenerBridgeRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnAddContextListenerBridgeRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnDisconnectAgentRequest(json: string): PrivateChannelOnDisconnectAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnDisconnectAgentRequest'));\n  }\n\n  public static privateChannelOnDisconnectAgentRequestToJson(value: PrivateChannelOnDisconnectAgentRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnDisconnectAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnDisconnectBridgeRequest(json: string): PrivateChannelOnDisconnectBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnDisconnectBridgeRequest'));\n  }\n\n  public static privateChannelOnDisconnectBridgeRequestToJson(value: PrivateChannelOnDisconnectBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnDisconnectBridgeRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnUnsubscribeAgentRequest(json: string): PrivateChannelOnUnsubscribeAgentRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnUnsubscribeAgentRequest'));\n  }\n\n  public static privateChannelOnUnsubscribeAgentRequestToJson(value: PrivateChannelOnUnsubscribeAgentRequest): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnUnsubscribeAgentRequest')), null, 2);\n  }\n\n  public static toPrivateChannelOnUnsubscribeBridgeRequest(json: string): PrivateChannelOnUnsubscribeBridgeRequest {\n    return cast(JSON.parse(json), r('PrivateChannelOnUnsubscribeBridgeRequest'));\n  }\n\n  public static privateChannelOnUnsubscribeBridgeRequestToJson(\n    value: PrivateChannelOnUnsubscribeBridgeRequest\n  ): string {\n    return JSON.stringify(uncast(value, r('PrivateChannelOnUnsubscribeBridgeRequest')), null, 2);\n  }\n\n  public static toRaiseIntentAgentErrorResponse(json: string): RaiseIntentAgentErrorResponse {\n    return cast(JSON.parse(json), r('RaiseIntentAgentErrorResponse'));\n  }\n\n  public static raiseIntentAgentErrorResponseToJson(value: RaiseIntentAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentAgentErrorResponse')), null, 2);\n  }\n\n  public static toRaiseIntentAgentRequest(json: string): RaiseIntentAgentRequest {\n    return cast(JSON.parse(json), r('RaiseIntentAgentRequest'));\n  }\n\n  public static raiseIntentAgentRequestToJson(value: RaiseIntentAgentRequest): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentAgentRequest')), null, 2);\n  }\n\n  public static toRaiseIntentAgentResponse(json: string): RaiseIntentAgentResponse {\n    return cast(JSON.parse(json), r('RaiseIntentAgentResponse'));\n  }\n\n  public static raiseIntentAgentResponseToJson(value: RaiseIntentAgentResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentAgentResponse')), null, 2);\n  }\n\n  public static toRaiseIntentBridgeErrorResponse(json: string): RaiseIntentBridgeErrorResponse {\n    return cast(JSON.parse(json), r('RaiseIntentBridgeErrorResponse'));\n  }\n\n  public static raiseIntentBridgeErrorResponseToJson(value: RaiseIntentBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentBridgeErrorResponse')), null, 2);\n  }\n\n  public static toRaiseIntentBridgeRequest(json: string): RaiseIntentBridgeRequest {\n    return cast(JSON.parse(json), r('RaiseIntentBridgeRequest'));\n  }\n\n  public static raiseIntentBridgeRequestToJson(value: RaiseIntentBridgeRequest): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentBridgeRequest')), null, 2);\n  }\n\n  public static toRaiseIntentBridgeResponse(json: string): RaiseIntentBridgeResponse {\n    return cast(JSON.parse(json), r('RaiseIntentBridgeResponse'));\n  }\n\n  public static raiseIntentBridgeResponseToJson(value: RaiseIntentBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentBridgeResponse')), null, 2);\n  }\n\n  public static toRaiseIntentResultAgentErrorResponse(json: string): RaiseIntentResultAgentErrorResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResultAgentErrorResponse'));\n  }\n\n  public static raiseIntentResultAgentErrorResponseToJson(value: RaiseIntentResultAgentErrorResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResultAgentErrorResponse')), null, 2);\n  }\n\n  public static toRaiseIntentResultAgentResponse(json: string): RaiseIntentResultAgentResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResultAgentResponse'));\n  }\n\n  public static raiseIntentResultAgentResponseToJson(value: RaiseIntentResultAgentResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResultAgentResponse')), null, 2);\n  }\n\n  public static toRaiseIntentResultBridgeErrorResponse(json: string): RaiseIntentResultBridgeErrorResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResultBridgeErrorResponse'));\n  }\n\n  public static raiseIntentResultBridgeErrorResponseToJson(value: RaiseIntentResultBridgeErrorResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResultBridgeErrorResponse')), null, 2);\n  }\n\n  public static toRaiseIntentResultBridgeResponse(json: string): RaiseIntentResultBridgeResponse {\n    return cast(JSON.parse(json), r('RaiseIntentResultBridgeResponse'));\n  }\n\n  public static raiseIntentResultBridgeResponseToJson(value: RaiseIntentResultBridgeResponse): string {\n    return JSON.stringify(uncast(value, r('RaiseIntentResultBridgeResponse')), null, 2);\n  }\n}\n\nfunction invalidValue(typ: any, val: any, key: any, parent: any = ''): never {\n  const prettyTyp = prettyTypeName(typ);\n  const parentText = parent ? ` on ${parent}` : '';\n  const keyText = key ? ` for key \"${key}\"` : '';\n  throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);\n}\n\nfunction prettyTypeName(typ: any): string {\n  if (Array.isArray(typ)) {\n    if (typ.length === 2 && typ[0] === undefined) {\n      return `an optional ${prettyTypeName(typ[1])}`;\n    } else {\n      return `one of [${typ\n        .map(a => {\n          return prettyTypeName(a);\n        })\n        .join(', ')}]`;\n    }\n  } else if (typeof typ === 'object' && typ.literal !== undefined) {\n    return typ.literal;\n  } else {\n    return typeof typ;\n  }\n}\n\nfunction jsonToJSProps(typ: any): any {\n  if (typ.jsonToJS === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.json] = { key: p.js, typ: p.typ }));\n    typ.jsonToJS = map;\n  }\n  return typ.jsonToJS;\n}\n\nfunction jsToJSONProps(typ: any): any {\n  if (typ.jsToJSON === undefined) {\n    const map: any = {};\n    typ.props.forEach((p: any) => (map[p.js] = { key: p.json, typ: p.typ }));\n    typ.jsToJSON = map;\n  }\n  return typ.jsToJSON;\n}\n\nfunction transform(val: any, typ: any, getProps: any, key: any = '', parent: any = ''): any {\n  function transformPrimitive(typ: string, val: any): any {\n    if (typeof typ === typeof val) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n\n  function transformUnion(typs: any[], val: any): any {\n    // val must validate against one typ in typs\n    const l = typs.length;\n    for (let i = 0; i < l; i++) {\n      const typ = typs[i];\n      try {\n        return transform(val, typ, getProps);\n      } catch (_) {}\n    }\n    return invalidValue(typs, val, key, parent);\n  }\n\n  function transformEnum(cases: string[], val: any): any {\n    if (cases.indexOf(val) !== -1) return val;\n    return invalidValue(\n      cases.map(a => {\n        return l(a);\n      }),\n      val,\n      key,\n      parent\n    );\n  }\n\n  function transformArray(typ: any, val: any): any {\n    // val must be an array with no invalid elements\n    if (!Array.isArray(val)) return invalidValue(l('array'), val, key, parent);\n    return val.map(el => transform(el, typ, getProps));\n  }\n\n  function transformDate(val: any): any {\n    if (val === null) {\n      return null;\n    }\n    const d = new Date(val);\n    if (isNaN(d.valueOf())) {\n      return invalidValue(l('Date'), val, key, parent);\n    }\n    return d;\n  }\n\n  function transformObject(props: { [k: string]: any }, additional: any, val: any): any {\n    if (val === null || typeof val !== 'object' || Array.isArray(val)) {\n      return invalidValue(l(ref || 'object'), val, key, parent);\n    }\n    const result: any = {};\n    Object.getOwnPropertyNames(props).forEach(key => {\n      const prop = props[key];\n      const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;\n      result[prop.key] = transform(v, prop.typ, getProps, key, ref);\n    });\n    Object.getOwnPropertyNames(val).forEach(key => {\n      if (!Object.prototype.hasOwnProperty.call(props, key)) {\n        result[key] = transform(val[key], additional, getProps, key, ref);\n      }\n    });\n    return result;\n  }\n\n  if (typ === 'any') return val;\n  if (typ === null) {\n    if (val === null) return val;\n    return invalidValue(typ, val, key, parent);\n  }\n  if (typ === false) return invalidValue(typ, val, key, parent);\n  let ref: any = undefined;\n  while (typeof typ === 'object' && typ.ref !== undefined) {\n    ref = typ.ref;\n    typ = typeMap[typ.ref];\n  }\n  if (Array.isArray(typ)) return transformEnum(typ, val);\n  if (typeof typ === 'object') {\n    return typ.hasOwnProperty('unionMembers')\n      ? transformUnion(typ.unionMembers, val)\n      : typ.hasOwnProperty('arrayItems')\n        ? transformArray(typ.arrayItems, val)\n        : typ.hasOwnProperty('props')\n          ? transformObject(getProps(typ), typ.additional, val)\n          : invalidValue(typ, val, key, parent);\n  }\n  // Numbers can be parsed by Date but shouldn't be.\n  if (typ === Date && typeof val !== 'number') return transformDate(val);\n  return transformPrimitive(typ, val);\n}\n\nfunction cast<T>(val: any, typ: any): T {\n  return transform(val, typ, jsonToJSProps);\n}\n\nfunction uncast<T>(val: T, typ: any): any {\n  return transform(val, typ, jsToJSONProps);\n}\n\nfunction l(typ: any) {\n  return { literal: typ };\n}\n\nfunction a(typ: any) {\n  return { arrayItems: typ };\n}\n\nfunction u(...typs: any[]) {\n  return { unionMembers: typs };\n}\n\nfunction o(props: any[], additional: any) {\n  return { props, additional };\n}\n\nfunction m(additional: any) {\n  return { props: [], additional };\n}\n\nfunction r(name: string) {\n  return { ref: name };\n}\n\nconst typeMap: any = {\n  AgentErrorResponseMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentResponseMetadata') },\n      { json: 'payload', js: 'payload', typ: r('ErrorResponseMessagePayload') },\n      { json: 'type', js: 'type', typ: r('ResponseMessageType') },\n    ],\n    false\n  ),\n  AgentResponseMetadata: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  ErrorResponseMessagePayload: o([{ json: 'error', js: 'error', typ: r('ResponseErrorDetail') }], 'any'),\n  AgentRequestMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentRequestMetadata') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: r('RequestMessageType') },\n    ],\n    false\n  ),\n  AgentRequestMetadata: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  BridgeParticipantIdentifier: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  SourceIdentifier: o(\n    [\n      { json: 'appId', js: 'appId', typ: u(undefined, '') },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  AgentResponseMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentResponseMetadata') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: r('ResponseMessageType') },\n    ],\n    false\n  ),\n  BridgeErrorResponseMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BridgeErrorResponseMessageMeta') },\n      { json: 'payload', js: 'payload', typ: r('ResponseErrorMessagePayload') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    false\n  ),\n  BridgeErrorResponseMessageMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  DesktopAgentIdentifier: o([{ json: 'desktopAgent', js: 'desktopAgent', typ: '' }], 'any'),\n  ResponseErrorMessagePayload: o([{ json: 'error', js: 'error', typ: u(undefined, r('ResponseErrorDetail')) }], 'any'),\n  BridgeRequestMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BridgeRequestMetadata') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    false\n  ),\n  BridgeRequestMetadata: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('BridgeParticipantIdentifier') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  BridgeResponseMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BridgeResponseMessageMeta') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    false\n  ),\n  BridgeResponseMessageMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  BroadcastAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('BroadcastAgentRequestType') },\n    ],\n    false\n  ),\n  BroadcastAgentRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('SourceObject') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  SourceObject: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  BroadcastAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  Context: o(\n    [\n      { json: 'id', js: 'id', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'type', js: 'type', typ: '' },\n    ],\n    'any'\n  ),\n  BroadcastBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BroadcastBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('BroadcastBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('BroadcastAgentRequestType') },\n    ],\n    false\n  ),\n  BroadcastBridgeRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  MetaSource: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  BroadcastBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  ConnectionStepMessage: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStepMetadata') },\n      { json: 'payload', js: 'payload', typ: m('any') },\n      { json: 'type', js: 'type', typ: r('ConnectionStepMessageType') },\n    ],\n    false\n  ),\n  ConnectionStepMetadata: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: u(undefined, '') },\n      { json: 'responseUuid', js: 'responseUuid', typ: u(undefined, '') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  ConnectionStep2Hello: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStep2HelloMeta') },\n      { json: 'payload', js: 'payload', typ: r('ConnectionStep2HelloPayload') },\n      { json: 'type', js: 'type', typ: r('ConnectionStep2HelloType') },\n    ],\n    false\n  ),\n  ConnectionStep2HelloMeta: o([{ json: 'timestamp', js: 'timestamp', typ: Date }], false),\n  ConnectionStep2HelloPayload: o(\n    [\n      { json: 'authRequired', js: 'authRequired', typ: true },\n      { json: 'authToken', js: 'authToken', typ: u(undefined, '') },\n      { json: 'desktopAgentBridgeVersion', js: 'desktopAgentBridgeVersion', typ: '' },\n      { json: 'supportedFDC3Versions', js: 'supportedFDC3Versions', typ: a('') },\n    ],\n    false\n  ),\n  ConnectionStep3Handshake: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStep3HandshakeMeta') },\n      { json: 'payload', js: 'payload', typ: r('ConnectionStep3HandshakePayload') },\n      { json: 'type', js: 'type', typ: r('ConnectionStep3HandshakeType') },\n    ],\n    false\n  ),\n  ConnectionStep3HandshakeMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  ConnectionStep3HandshakePayload: o(\n    [\n      { json: 'authToken', js: 'authToken', typ: u(undefined, '') },\n      { json: 'channelsState', js: 'channelsState', typ: m(a(r('Context'))) },\n      { json: 'implementationMetadata', js: 'implementationMetadata', typ: r('ConnectingAgentImplementationMetadata') },\n      { json: 'requestedName', js: 'requestedName', typ: '' },\n    ],\n    false\n  ),\n  ConnectingAgentImplementationMetadata: o(\n    [\n      { json: 'fdc3Version', js: 'fdc3Version', typ: '' },\n      { json: 'optionalFeatures', js: 'optionalFeatures', typ: r('OptionalFeatures') },\n      { json: 'provider', js: 'provider', typ: '' },\n      { json: 'providerVersion', js: 'providerVersion', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  OptionalFeatures: o(\n    [\n      { json: 'DesktopAgentBridging', js: 'DesktopAgentBridging', typ: true },\n      { json: 'OriginatingAppMetadata', js: 'OriginatingAppMetadata', typ: true },\n      { json: 'UserChannelMembershipAPIs', js: 'UserChannelMembershipAPIs', typ: true },\n    ],\n    false\n  ),\n  ConnectionStep4AuthenticationFailed: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStep4AuthenticationFailedMeta') },\n      { json: 'payload', js: 'payload', typ: r('ConnectionStep4AuthenticationFailedPayload') },\n      { json: 'type', js: 'type', typ: r('ConnectionStep4AuthenticationFailedType') },\n    ],\n    false\n  ),\n  ConnectionStep4AuthenticationFailedMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  ConnectionStep4AuthenticationFailedPayload: o([{ json: 'message', js: 'message', typ: u(undefined, '') }], false),\n  ConnectionStep6ConnectedAgentsUpdate: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ConnectionStep6ConnectedAgentsUpdateMeta') },\n      { json: 'payload', js: 'payload', typ: r('ConnectionStep6ConnectedAgentsUpdatePayload') },\n      { json: 'type', js: 'type', typ: r('ConnectionStep6ConnectedAgentsUpdateType') },\n    ],\n    false\n  ),\n  ConnectionStep6ConnectedAgentsUpdateMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  ConnectionStep6ConnectedAgentsUpdatePayload: o(\n    [\n      { json: 'addAgent', js: 'addAgent', typ: u(undefined, '') },\n      { json: 'allAgents', js: 'allAgents', typ: a(r('DesktopAgentImplementationMetadata')) },\n      { json: 'channelsState', js: 'channelsState', typ: u(undefined, m(a(r('Context')))) },\n      { json: 'removeAgent', js: 'removeAgent', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  DesktopAgentImplementationMetadata: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'fdc3Version', js: 'fdc3Version', typ: '' },\n      { json: 'optionalFeatures', js: 'optionalFeatures', typ: r('OptionalFeatures') },\n      { json: 'provider', js: 'provider', typ: '' },\n      { json: 'providerVersion', js: 'providerVersion', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindInstancesAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindInstancesAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('PayloadClass') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindInstancesAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PayloadClass: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  FindInstancesAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindInstancesAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentRequestType') },\n    ],\n    false\n  ),\n  FindInstancesAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  DestinationObject: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FindInstancesAgentRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppIdentifier') }], false),\n  AppIdentifier: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FindInstancesAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('AgentResponseMetadata') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindInstancesAgentResponsePayload: o(\n    [{ json: 'appIdentifiers', js: 'appIdentifiers', typ: a(r('AppMetadata')) }],\n    false\n  ),\n  AppMetadata: o(\n    [\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'description', js: 'description', typ: u(undefined, '') },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: u(undefined, '') },\n      { json: 'icons', js: 'icons', typ: u(undefined, a(r('Icon'))) },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n      { json: 'instanceMetadata', js: 'instanceMetadata', typ: u(undefined, m('any')) },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, u(null, '')) },\n      { json: 'screenshots', js: 'screenshots', typ: u(undefined, a(r('Image'))) },\n      { json: 'title', js: 'title', typ: u(undefined, '') },\n      { json: 'tooltip', js: 'tooltip', typ: u(undefined, '') },\n      { json: 'version', js: 'version', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  Icon: o(\n    [\n      { json: 'size', js: 'size', typ: u(undefined, '') },\n      { json: 'src', js: 'src', typ: '' },\n      { json: 'type', js: 'type', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  Image: o(\n    [\n      { json: 'label', js: 'label', typ: u(undefined, '') },\n      { json: 'size', js: 'size', typ: u(undefined, '') },\n      { json: 'src', js: 'src', typ: '' },\n      { json: 'type', js: 'type', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindInstancesBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindInstancesBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('MessagePayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindInstancesBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  MessagePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  FindInstancesBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindInstancesBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentRequestType') },\n    ],\n    false\n  ),\n  FindInstancesBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSourceObject') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  MetaSourceObject: o(\n    [\n      { json: 'appId', js: 'appId', typ: u(undefined, '') },\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  FindInstancesBridgeRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppIdentifier') }], false),\n  FindInstancesBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('BridgeResponseMessageMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindInstancesBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindInstancesAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindInstancesBridgeResponsePayload: o(\n    [{ json: 'appIdentifiers', js: 'appIdentifiers', typ: a(r('AppMetadata')) }],\n    false\n  ),\n  FindIntentAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentAgentErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  FindIntentAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentRequestType') },\n    ],\n    false\n  ),\n  FindIntentAgentRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n    ],\n    false\n  ),\n  FindIntentAgentRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentAgentResponsePayload: o([{ json: 'appIntent', js: 'appIntent', typ: r('AppIntent') }], false),\n  AppIntent: o(\n    [\n      { json: 'apps', js: 'apps', typ: a(r('AppMetadata')) },\n      { json: 'intent', js: 'intent', typ: r('IntentMetadata') },\n    ],\n    false\n  ),\n  IntentMetadata: o(\n    [\n      { json: 'displayName', js: 'displayName', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: '' },\n    ],\n    false\n  ),\n  FindIntentBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentBridgeErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  FindIntentBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentRequestType') },\n    ],\n    false\n  ),\n  FindIntentBridgeRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('BridgeParticipantIdentifier') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n    ],\n    false\n  ),\n  FindIntentBridgeRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentBridgeResponsePayload: o([{ json: 'appIntent', js: 'appIntent', typ: r('AppIntent') }], false),\n  FindIntentsByContextAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentErrorResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }],\n    false\n  ),\n  FindIntentsByContextAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentRequestType') },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentsByContextAgentResponsePayload: o(\n    [{ json: 'appIntents', js: 'appIntents', typ: a(r('AppIntent')) }],\n    false\n  ),\n  FindIntentsByContextBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeErrorResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }],\n    false\n  ),\n  FindIntentsByContextBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentRequestType') },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeRequestMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n      { json: 'destination', js: 'destination', typ: u(undefined, r('BridgeParticipantIdentifier')) },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeRequestPayload: o(\n    [\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'resultType', js: 'resultType', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('FindIntentsByContextBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('FindIntentsByContextBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('FindIntentsByContextAgentErrorResponseType') },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  FindIntentsByContextBridgeResponsePayload: o(\n    [{ json: 'appIntents', js: 'appIntents', typ: a(r('AppIntent')) }],\n    false\n  ),\n  GetAppMetadataAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentErrorResponseType') },\n    ],\n    false\n  ),\n  GetAppMetadataAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataAgentErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  GetAppMetadataAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentRequestType') },\n    ],\n    false\n  ),\n  GetAppMetadataAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceIdentifier')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataAgentRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppObject') }], false),\n  AppObject: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  GetAppMetadataAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentErrorResponseType') },\n    ],\n    false\n  ),\n  GetAppMetadataAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataAgentResponsePayload: o([{ json: 'appMetadata', js: 'appMetadata', typ: r('AppMetadata') }], false),\n  GetAppMetadataBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentErrorResponseType') },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  GetAppMetadataBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentRequestType') },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSourceObject') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeRequestPayload: o([{ json: 'app', js: 'app', typ: r('AppObject') }], false),\n  GetAppMetadataBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('GetAppMetadataBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('GetAppMetadataBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('GetAppMetadataAgentErrorResponseType') },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  GetAppMetadataBridgeResponsePayload: o([{ json: 'appMetadata', js: 'appMetadata', typ: r('AppMetadata') }], false),\n  OpenAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentErrorResponseType') },\n    ],\n    false\n  ),\n  OpenAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenAgentErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('OpenErrorResponsePayload') }], false),\n  OpenAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentRequestType') },\n    ],\n    false\n  ),\n  OpenAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('SourceObject') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenAgentRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: r('AppToOpen') },\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n    ],\n    false\n  ),\n  AppToOpen: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  OpenAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentErrorResponseType') },\n    ],\n    false\n  ),\n  OpenAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenAgentResponsePayload: o([{ json: 'appIdentifier', js: 'appIdentifier', typ: r('AppIdentifier') }], false),\n  OpenBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentErrorResponseType') },\n    ],\n    false\n  ),\n  OpenBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenBridgeErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('OpenErrorResponsePayload') }], false),\n  OpenBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentRequestType') },\n    ],\n    false\n  ),\n  OpenBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('DestinationObject')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenBridgeRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: r('AppToOpen') },\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n    ],\n    false\n  ),\n  OpenBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('OpenBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('OpenBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('OpenAgentErrorResponseType') },\n    ],\n    false\n  ),\n  OpenBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  OpenBridgeResponsePayload: o([{ json: 'appIdentifier', js: 'appIdentifier', typ: r('AppIdentifier') }], false),\n  PrivateChannelBroadcastAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelBroadcastAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelBroadcastAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelBroadcastAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelBroadcastAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  MetaDestination: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  PrivateChannelBroadcastAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  PrivateChannelBroadcastBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelBroadcastBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelBroadcastBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelBroadcastAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelBroadcastBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelBroadcastBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'context', js: 'context', typ: r('Context') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelEventListenerAddedAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelEventListenerAddedAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelEventListenerAddedAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'listenerType', js: 'listenerType', typ: r('PrivateChannelEventType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelEventListenerAddedBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelEventListenerAddedBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelEventListenerAddedAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerAddedBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'listenerType', js: 'listenerType', typ: r('PrivateChannelEventType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelEventListenerRemovedAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelEventListenerRemovedAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelEventListenerRemovedAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'listenerType', js: 'listenerType', typ: r('PrivateChannelEventType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelEventListenerRemovedBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelEventListenerRemovedBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelEventListenerRemovedAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelEventListenerRemovedBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'listenerType', js: 'listenerType', typ: r('PrivateChannelEventType') },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelOnAddContextListenerAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnAddContextListenerAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnAddContextListenerAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelOnAddContextListenerBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnAddContextListenerBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnAddContextListenerAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnAddContextListenerBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelOnDisconnectAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnDisconnectAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnDisconnectAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectAgentRequestPayload: o([{ json: 'channelId', js: 'channelId', typ: '' }], false),\n  PrivateChannelOnDisconnectBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelOnDisconnectBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnDisconnectBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnDisconnectAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnDisconnectBridgeRequestPayload: o([{ json: 'channelId', js: 'channelId', typ: '' }], false),\n  PrivateChannelOnUnsubscribeAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('PrivateChannelOnUnsubscribeAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnUnsubscribeAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnUnsubscribeAgentRequestType') },\n    ],\n    false\n  ),\n  PrivateChannelOnUnsubscribeAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: u(undefined, r('SourceObject')) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnUnsubscribeAgentRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  PrivateChannelOnUnsubscribeBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('ERequestMetadata') },\n      { json: 'payload', js: 'payload', typ: r('PrivateChannelOnUnsubscribeBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('PrivateChannelOnUnsubscribeAgentRequestType') },\n    ],\n    false\n  ),\n  ERequestMetadata: o(\n    [\n      { json: 'destination', js: 'destination', typ: u(undefined, r('MetaDestination')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  PrivateChannelOnUnsubscribeBridgeRequestPayload: o(\n    [\n      { json: 'channelId', js: 'channelId', typ: '' },\n      { json: 'contextType', js: 'contextType', typ: u(null, '') },\n    ],\n    false\n  ),\n  RaiseIntentAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentAgentErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  RaiseIntentAgentRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentAgentRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentAgentRequestPayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentRequestType') },\n    ],\n    false\n  ),\n  RaiseIntentAgentRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: r('MetaDestination') },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('SourceObject') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentAgentRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: r('AppDestinationIdentifier') },\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'intent', js: 'intent', typ: '' },\n    ],\n    false\n  ),\n  AppDestinationIdentifier: o(\n    [\n      { json: 'desktopAgent', js: 'desktopAgent', typ: '' },\n      { json: 'appId', js: 'appId', typ: '' },\n      { json: 'instanceId', js: 'instanceId', typ: u(undefined, '') },\n    ],\n    'any'\n  ),\n  RaiseIntentAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentAgentResponsePayload: o(\n    [{ json: 'intentResolution', js: 'intentResolution', typ: r('IntentResolution') }],\n    false\n  ),\n  IntentResolution: o(\n    [\n      { json: 'intent', js: 'intent', typ: '' },\n      { json: 'source', js: 'source', typ: r('AppIdentifier') },\n    ],\n    false\n  ),\n  RaiseIntentBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentBridgeErrorResponsePayload: o([{ json: 'error', js: 'error', typ: r('FindInstancesErrors') }], false),\n  RaiseIntentBridgeRequest: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentBridgeRequestMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentBridgeRequestPayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentRequestType') },\n    ],\n    false\n  ),\n  RaiseIntentBridgeRequestMeta: o(\n    [\n      { json: 'destination', js: 'destination', typ: r('MetaDestination') },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'source', js: 'source', typ: r('MetaSource') },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentBridgeRequestPayload: o(\n    [\n      { json: 'app', js: 'app', typ: r('AppDestinationIdentifier') },\n      { json: 'context', js: 'context', typ: r('Context') },\n      { json: 'intent', js: 'intent', typ: '' },\n    ],\n    false\n  ),\n  RaiseIntentBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentBridgeResponsePayload: o(\n    [{ json: 'intentResolution', js: 'intentResolution', typ: r('IntentResolution') }],\n    false\n  ),\n  RaiseIntentResultAgentErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentResultAgentErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResultAgentErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResultAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResultAgentErrorResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentResultAgentErrorResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: r('RaiseIntentResultErrorMessage') }],\n    false\n  ),\n  RaiseIntentResultAgentResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentResultAgentResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResultAgentResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResultAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResultAgentResponseMeta: o(\n    [\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentResultAgentResponsePayload: o(\n    [{ json: 'intentResult', js: 'intentResult', typ: r('IntentResult') }],\n    false\n  ),\n  IntentResult: o(\n    [\n      { json: 'context', js: 'context', typ: u(undefined, r('Context')) },\n      { json: 'channel', js: 'channel', typ: u(undefined, r('Channel')) },\n    ],\n    false\n  ),\n  Channel: o(\n    [\n      { json: 'displayMetadata', js: 'displayMetadata', typ: u(undefined, r('DisplayMetadata')) },\n      { json: 'id', js: 'id', typ: '' },\n      { json: 'type', js: 'type', typ: r('Type') },\n    ],\n    false\n  ),\n  DisplayMetadata: o(\n    [\n      { json: 'color', js: 'color', typ: u(undefined, '') },\n      { json: 'glyph', js: 'glyph', typ: u(undefined, '') },\n      { json: 'name', js: 'name', typ: u(undefined, '') },\n    ],\n    false\n  ),\n  RaiseIntentResultBridgeErrorResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentResultBridgeErrorResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResultBridgeErrorResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResultAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResultBridgeErrorResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: a(r('ResponseErrorDetail')) },\n      { json: 'errorSources', js: 'errorSources', typ: a(r('DesktopAgentIdentifier')) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentResultBridgeErrorResponsePayload: o(\n    [{ json: 'error', js: 'error', typ: r('RaiseIntentResultErrorMessage') }],\n    false\n  ),\n  RaiseIntentResultBridgeResponse: o(\n    [\n      { json: 'meta', js: 'meta', typ: r('RaiseIntentResultBridgeResponseMeta') },\n      { json: 'payload', js: 'payload', typ: r('RaiseIntentResultBridgeResponsePayload') },\n      { json: 'type', js: 'type', typ: r('RaiseIntentResultAgentErrorResponseType') },\n    ],\n    false\n  ),\n  RaiseIntentResultBridgeResponseMeta: o(\n    [\n      { json: 'errorDetails', js: 'errorDetails', typ: u(undefined, a(r('ResponseErrorDetail'))) },\n      { json: 'errorSources', js: 'errorSources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'requestUuid', js: 'requestUuid', typ: '' },\n      { json: 'responseUuid', js: 'responseUuid', typ: '' },\n      { json: 'sources', js: 'sources', typ: u(undefined, a(r('DesktopAgentIdentifier'))) },\n      { json: 'timestamp', js: 'timestamp', typ: Date },\n    ],\n    false\n  ),\n  RaiseIntentResultBridgeResponsePayload: o(\n    [{ json: 'intentResult', js: 'intentResult', typ: r('IntentResult') }],\n    false\n  ),\n  ResponseErrorDetail: [\n    'ApiTimeout',\n    'AccessDenied',\n    'AgentDisconnected',\n    'AppNotFound',\n    'AppTimeout',\n    'CreationFailed',\n    'DesktopAgentNotFound',\n    'ErrorOnLaunch',\n    'IntentDeliveryFailed',\n    'IntentHandlerRejected',\n    'IntentListenerConflict',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NoAppsFound',\n    'NoChannelFound',\n    'NoResultReturned',\n    'NotConnectedToBridge',\n    'ResolverTimeout',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n    'TargetAppUnavailable',\n    'TargetInstanceUnavailable',\n    'UserCancelledResolution',\n  ],\n  ResponseMessageType: [\n    'findInstancesResponse',\n    'findIntentResponse',\n    'findIntentsByContextResponse',\n    'getAppMetadataResponse',\n    'openResponse',\n    'raiseIntentResponse',\n    'raiseIntentResultResponse',\n  ],\n  RequestMessageType: [\n    'broadcastRequest',\n    'findInstancesRequest',\n    'findIntentRequest',\n    'findIntentsByContextRequest',\n    'getAppMetadataRequest',\n    'openRequest',\n    'PrivateChannel.broadcast',\n    'PrivateChannel.eventListenerAdded',\n    'PrivateChannel.eventListenerRemoved',\n    'PrivateChannel.onAddContextListener',\n    'PrivateChannel.onDisconnect',\n    'PrivateChannel.onUnsubscribe',\n    'raiseIntentRequest',\n  ],\n  BroadcastAgentRequestType: ['broadcastRequest'],\n  ConnectionStepMessageType: ['authenticationFailed', 'connectedAgentsUpdate', 'handshake', 'hello'],\n  ConnectionStep2HelloType: ['hello'],\n  ConnectionStep3HandshakeType: ['handshake'],\n  ConnectionStep4AuthenticationFailedType: ['authenticationFailed'],\n  ConnectionStep6ConnectedAgentsUpdateType: ['connectedAgentsUpdate'],\n  FindInstancesErrors: [\n    'ApiTimeout',\n    'AgentDisconnected',\n    'DesktopAgentNotFound',\n    'IntentDeliveryFailed',\n    'IntentListenerConflict',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NoAppsFound',\n    'NotConnectedToBridge',\n    'ResolverTimeout',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n    'TargetAppUnavailable',\n    'TargetInstanceUnavailable',\n    'UserCancelledResolution',\n  ],\n  FindInstancesAgentErrorResponseType: ['findInstancesResponse'],\n  FindInstancesAgentRequestType: ['findInstancesRequest'],\n  FindIntentAgentErrorResponseType: ['findIntentResponse'],\n  FindIntentAgentRequestType: ['findIntentRequest'],\n  FindIntentsByContextAgentErrorResponseType: ['findIntentsByContextResponse'],\n  FindIntentsByContextAgentRequestType: ['findIntentsByContextRequest'],\n  GetAppMetadataAgentErrorResponseType: ['getAppMetadataResponse'],\n  GetAppMetadataAgentRequestType: ['getAppMetadataRequest'],\n  OpenErrorResponsePayload: [\n    'ApiTimeout',\n    'AgentDisconnected',\n    'AppNotFound',\n    'AppTimeout',\n    'DesktopAgentNotFound',\n    'ErrorOnLaunch',\n    'InvalidArguments',\n    'MalformedContext',\n    'MalformedMessage',\n    'NotConnectedToBridge',\n    'ResolverUnavailable',\n    'ResponseToBridgeTimedOut',\n  ],\n  OpenAgentErrorResponseType: ['openResponse'],\n  OpenAgentRequestType: ['openRequest'],\n  PrivateChannelBroadcastAgentRequestType: ['PrivateChannel.broadcast'],\n  PrivateChannelEventType: ['addContextListener', 'disconnect', 'unsubscribe'],\n  PrivateChannelEventListenerAddedAgentRequestType: ['PrivateChannel.eventListenerAdded'],\n  PrivateChannelEventListenerRemovedAgentRequestType: ['PrivateChannel.eventListenerRemoved'],\n  PrivateChannelOnAddContextListenerAgentRequestType: ['PrivateChannel.onAddContextListener'],\n  PrivateChannelOnDisconnectAgentRequestType: ['PrivateChannel.onDisconnect'],\n  PrivateChannelOnUnsubscribeAgentRequestType: ['PrivateChannel.onUnsubscribe'],\n  RaiseIntentAgentErrorResponseType: ['raiseIntentResponse'],\n  RaiseIntentAgentRequestType: ['raiseIntentRequest'],\n  RaiseIntentResultErrorMessage: [\n    'ApiTimeout',\n    'AgentDisconnected',\n    'IntentHandlerRejected',\n    'MalformedMessage',\n    'NoResultReturned',\n    'NotConnectedToBridge',\n    'ResponseToBridgeTimedOut',\n  ],\n  RaiseIntentResultAgentErrorResponseType: ['raiseIntentResultResponse'],\n  Type: ['app', 'private', 'user'],\n};\n"
  },
  {
    "path": "packages/fdc3-schema/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-schema\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"clean\": \"npx rimraf dist && npx rimraf generated\",\n    \"mkdirs\": \"npx mkdirp generated/api && npx mkdirp generated/bridging\",\n    \"generate-type-predicates\": \"tsx code-generation/generate-type-predicates.ts\",\n    \"generate\": \"npm run mkdirs && npm run typegen-browser && npm run typegen-bridging && npm run generate-type-predicates && npm run lint\",\n    \"build\": \"npm run generate && tsc\",\n    \"lint\": \"eslint generated/ --fix && npx prettier generated/ --write\",\n    \"test\": \"npm run generate && tsc\",\n    \"typegen-browser\": \"cd schemas && node ../s2tQuicktypeUtil.cjs api/api.schema.json api/common.schema.json ../../fdc3-context/schemas/context/context.schema.json api ../generated/api/BrowserTypes.ts\",\n    \"typegen-bridging\": \"cd schemas && node ../s2tQuicktypeUtil.cjs api/api.schema.json api/common.schema.json api/broadcastRequest.schema.json api/findInstancesRequest.schema.json api/findInstancesResponse.schema.json api/findIntentRequest.schema.json api/findIntentResponse.schema.json api/findIntentsByContextRequest.schema.json api/findIntentsByContextResponse.schema.json api/getAppMetadataRequest.schema.json api/getAppMetadataResponse.schema.json api/openRequest.schema.json api/openResponse.schema.json api/raiseIntentRequest.schema.json api/raiseIntentResponse.schema.json api/raiseIntentResultResponse.schema.json ../../fdc3-context/schemas/context/context.schema.json bridging ../generated/bridging/BridgingTypes.ts\"\n  },\n  \"devDependencies\": {\n    \"message-await\": \"^1.1.0\",\n    \"mkdirp\": \"^3.0.1\",\n    \"quicktype\": \"23.0.78\",\n    \"ts-morph\": \"^24.0.0\",\n    \"tslib\": \"^2.7.0\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/fdc3-schema/s2tQuicktypeUtil.cjs",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/** Utility for preparing arguments to quicktype, which workaround a specific\n * quicktype bug in command line argument handling (where a directory is used\n * as input the source language argument is ignored which causes our schemas\n * to be interpreted as JSON input, rather than JSONSchema).\n *\n * Individual file arguments will be interpreted as 'additional' schema files\n * that will be referenced from the other schemas and may not have top-level output\n * schemas generated, while folders of files w\n *\n *  */\n\nconst path = require('path');\nconst fs = require('fs');\nconst { forEachChild } = require('typescript');\nconst exec = require('child_process').exec;\n\nconst args = process.argv.slice(2);\nconst outputFile = args.pop();\nconst inputs = args;\nconst toProcess = [];\n\nconsole.log('Inputs schema files: ' + inputs.join(' | '));\nconsole.log('Output file argument: ' + outputFile);\n\nlet sources = '';\nlet additionalSchemaFiles = '';\n\n//skip duplicate paths (we might want to specify some files to go first, and might duplicate them)\nconst allPaths = new Set();\n\nconst addAPath = (aPath, paths, sources, type) => {\n  if (!paths.has(aPath)) {\n    paths.add(aPath);\n    return sources + ` ${type} ${aPath}`;\n  } else {\n    console.log(`skipping duplicate path ${aPath}`);\n    return sources;\n  }\n};\n\n//process the content of folders to produce code for top-level types\nlet inputIndex = 0;\nwhile (inputIndex < inputs.length) {\n  if (inputs[inputIndex].endsWith('.schema.json')) {\n    //add individual files with -S as additional schema files used in references (rather than ones that need a top-level output)\n    additionalSchemaFiles = addAPath(path.join(inputs[inputIndex]), allPaths, additionalSchemaFiles, '-S');\n  } else {\n    fs.readdirSync(inputs[inputIndex], { withFileTypes: true }).forEach(file => {\n      if (file.isDirectory()) {\n        inputs.push(path.join(inputs[inputIndex], file.name));\n      } else if (file.name.endsWith('.schema.json')) {\n        sources = addAPath(path.join(inputs[inputIndex], file.name), allPaths, sources, '--src');\n      }\n    });\n  }\n  inputIndex++;\n}\n\n// Normalise path to local quicktype executable.\n//const quicktypeExec = \"node \" + [\"..\",\"quicktype\",\"dist\",\"index.js\"].join(path.sep);\nconst quicktypeExec = ['..', '..', '..', 'node_modules', '.bin', 'quicktype'].join(path.sep);\n\nconst command = `${quicktypeExec} --prefer-const-values --prefer-unions -s schema -o ${outputFile} ${additionalSchemaFiles} ${sources}`;\nconsole.log('command to run: ' + command);\n\nexec(command, function (error, stdout, stderr) {\n  if (stdout) {\n    console.log(stdout);\n  }\n  if (stderr) {\n    console.log(stderr);\n  }\n});\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/README.md",
    "content": "# Intro\n\nThe _schemas/api_ folder contains JSONSchema definitions that are used to implement wire protocols for an app working with a Desktop Agent, and for import into the Bridging wire protocols that shares many of the same structures.\n\nPlease note: Quicktype, the chosen generation tool currently has some limitations that prevent fully automatic schema generation from the existing TS types. For example, it can not handle interfaces that contain methods in their definition (as you can't define methods in JSON). It also fails to generate schemas even if a type contains unused references to other types or interfaces that contain async functions (`Promise` return types). Therefore, in order to generate the `api\\schemas\\api.schema.json` some manual intervention was needed.\n\nOnce these limitations are not an issue the `api\\schemas\\t2sQuicktypeUtil.js` script should be moved to the root level of the project and a new npm script `\"api-schema-gen\": \"node t2sQuicktypeUtil.js src/api schemas/api/api.schema.json\"` should be added. Alternatively, schemas (for API types) may be manually maintained against the matching TypeScript definitions\n\nContents:\n\n- `api\\schemas\\t2sQuicktypeUtil.js` - Script used to run the generation of the schema from the types. Should be moved to the root level of the repo once fully-automated generation can be achieved.\n- `api\\schemas\\api.schema.json` - Partially auto-generated schema from the existing `src\\api` types and metadata objects. Expected to be manually maintained in future.\n- `api\\schemas\\common.schema.json` - Common element definitions referenced in multiple other schemas in both the API and Bridging API protocols.\n- `api\\schemas\\appRequest.schema.json` - The base message definition that requests from an app to the DA are derived from.\n- `api\\schemas\\agentResponse.schema.json` - The base message definition that API call response messages from a DA to an app are derived from.\n- `api\\schemas\\agentEvent.schema.json` - The base message definition that event messages from a DA to an app are derived from.\n- `api\\schemas\\*Request.schema.json` - Schemas defining request messages sent from apps to Desktop Agents.\n- `api\\schemas\\*Response.schema.json` - Schemas defining responses from DAs to apps for request messages (sent from apps to Desktop Agents).\n- `api\\schemas\\*Event.schema.json` - Schemas defining event messages sent from Desktop Agents to Apps.\n\nPlease note that when adding a particular message type, that it needs its own schema file, which will declare the type (string). That type string MUST also be added to an enumeration in the base message schema it was derived from - each base message schema (appRequest, agentResponse, agentEvent) has an enumeration of the valid types and it must appear in that or the message will not validate. Unhelpfully, if you've forgotten to do that Quicktype will only report:\n\n```\nError: Internal error: We got an empty string type.\n```\n\nor another similar error - its not always the same one!\n\nIt can be very hard to figure out in which file the problem occurs. Generally, to figure out where an issue is, you can enable Quicktype's debug output by adding `--debug all` or `--debug print-schema-resolving` to the arguments assembled in s2tQuicktypeUtil.js or by taking the command it constructs (printed to the console) and manually add the option and re-run the command. If you're lucky, the error will be hit during the resolution steps which will point to the file(s) with an issue (often a disagreement between types combined with `allOf`).\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP1Hello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP1Hello.schema.json\",\n  \"title\": \"Web Connection Protocol 1 Hello\",\n  \"description\": \"Hello message sent by an application to a parent window or frame when attempting to establish connectivity to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP1HelloBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP1HelloBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP1Hello Message Type\",\n          \"const\": \"WCP1Hello\"\n        },\n        \"payload\": {\n          \"title\": \"WCP1Hello Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"identityUrl\": {\n              \"title\": \"Identity URL\",\n              \"description\": \"URL to use for the identity of the application. Desktop Agents MUST validate that the origin of the message matches the URL, but MAY implement custom comparison logic.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"actualUrl\": {\n              \"title\": \"Actual URL\",\n              \"description\": \"The current URL of the page attempting to connect. This may differ from the identityUrl, but the origins MUST match.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"description\": \"The version of FDC3 API that the app supports.\",\n              \"type\": \"string\"\n            },\n            \"intentResolver\": {\n              \"title\": \"Intent Resolver Required\",\n              \"description\": \"A flag that may be used to indicate that an intent resolver is or is not required. Set to `false` if no intents, or only targeted intents, are raised.\",\n              \"type\": \"boolean\"\n            },\n            \"channelSelector\": {\n              \"title\": \"Channel Selector Required\",\n              \"description\": \"A flag that may be used to indicate that a channel selector user interface is or is not required. Set to `false` if the app includes its own interface for selecting channels or does not work with user channels.\",\n              \"type\": \"boolean\"\n            }\n          },\n          \"required\": [\"identityUrl\",\"actualUrl\",\"fdc3Version\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [ \"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP2LoadUrl.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP2LoadUrl.schema.json\",\n  \"title\": \"Web Connection Protocol 2 Load Url\",\n  \"description\": \"Response from a Desktop Agent to an application requesting access to it indicating that it should load a specified URL into a hidden iframe in order to establish connectivity to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP2LoadUrlBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP2LoadUrlBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP2LoadUrl Message Type\",\n          \"const\": \"WCP2LoadUrl\"\n        },\n        \"payload\": {\n          \"title\": \"WCP2LoadUrl Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"iframeUrl\": {\n              \"title\": \"iframe URL\",\n              \"type\": \"string\",\n              \"description\": \"A URL which can be used to establish communication with the Desktop Agent, via loading the URL into an iframe and restarting the Web Connection protocol with the iframe as the target.\",\n              \"format\": \"uri\"\n            }\n          },\n          \"required\": [\n            \"iframeUrl\"\n          ],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP3Handshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP3Handshake.schema.json\",\n  \"title\": \"Web Connection Protocol 3 Handshake\",\n  \"description\": \"Handshake message sent by the Desktop Agent to the app (with a MessagePort appended) that should be used for subsequent communication steps.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP3HandshakeBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP3HandshakeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP3Handshake Message Type\",\n          \"const\": \"WCP3Handshake\"\n        },\n        \"payload\": {\n          \"title\": \"WCP3Handshake Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"type\": \"string\",\n              \"description\": \"The version of FDC3 API that the Desktop Agent will provide support for.\"\n            },\n            \"intentResolverUrl\": {\n              \"title\": \"Resolver URL\",\n              \"description\": \"Indicates whether an intent resolver user interface is required and the URL to use to do so. Set to `true` to use the default or `false` to disable the intent resolver (as the Desktop Agent will handle it another way).\",\n              \"oneOf\": [\n                {\n                  \"type\": \"string\",\n                  \"format\": \"uri\"\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"channelSelectorUrl\": {\n              \"title\": \"Channel Selector URL\",\n              \"description\": \"Indicates whether a channel selector user interface is required and the URL to use to do so. Set to `true` to use the default or `false` to disable the channel selector (as the Desktop Agent will handle it another way).\",\n              \"oneOf\": [\n                {\n                  \"type\": \"string\",\n                  \"format\": \"uri\"\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"messageExchangeTimeout\": {\n              \"title\": \"Message Exchange Timeout\",\n              \"description\": \"Indicates a custom timeout (in milliseconds) that should be used for the majority of API message exchanges instead of the default 10,000 millisecond timeout.\",\n              \"type\": \"number\",\n              \"minimum\": 100\n            },\n            \"appLaunchTimeout\": {\n              \"title\": \"App Launch Timeout\",\n              \"description\": \"Indicates a custom timeout (in milliseconds) that should be used for API message exchanges that may involve launching an application, instead of the default 100,000 millisecond timeout.\",\n              \"type\": \"number\",\n              \"minimum\": 15000\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"fdc3Version\",\n            \"intentResolverUrl\",\n            \"channelSelectorUrl\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP4ValidateAppIdentity.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP4ValidateAppIdentity.schema.json\",\n  \"title\": \"Web Connection Protocol 4 Validate App Identity\",\n  \"description\": \"Identity Validation request from an app attempting to connect to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP4ValidateAppIdentityBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP4ValidateAppIdentityBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP4ValidateAppIdentity Message Type\",\n          \"const\": \"WCP4ValidateAppIdentity\"\n        },\n        \"payload\": {\n          \"title\": \"WCP4ValidateAppIdentity Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"identityUrl\": {\n              \"title\": \"Identity URL\",\n              \"description\": \"URL to use for the identity of the application. Desktop Agents MUST validate that the origin of the message matches the URL, but MAY implement custom comparison logic.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"actualUrl\": {\n              \"title\": \"Actual URL\",\n              \"description\": \"The current URL of the page attempting to connect. This may differ from the identityUrl, but the origins MUST match.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"instanceId\": {\n              \"title\": \"instanceId\",\n              \"description\": \"If an application has previously connected to the Desktop Agent, it may specify its prior instance id and associated instance UUID to request the same same instance Id be assigned.\",\n              \"type\": \"string\"\n            },\n            \"instanceUuid\": {\n              \"title\": \"instanceUuid\",\n              \"description\": \"Instance UUID associated with the requested instanceId.\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"identityUrl\", \"actualUrl\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP5ValidateAppIdentityFailedResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP5ValidateAppIdentityFailedResponse.schema.json\",\n  \"title\": \"Web Connection Protocol 5 Validate App Identity Failed Response\",\n  \"description\": \"Message sent by the Desktop Agent to an app if their identity validation fails.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP5ValidateAppIdentityFailedResponseBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP5ValidateAppIdentityFailedResponseBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP5ValidateAppIdentityFailedResponse Message Type\",\n          \"const\": \"WCP5ValidateAppIdentityFailedResponse\"\n        },\n        \"payload\": {\n          \"title\": \"WCP5ValidateAppIdentityFailedResponse Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"message\": {\n              \"title\": \"Identity Validation failed message\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP5ValidateAppIdentityResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json\",\n  \"title\": \"Web Connection Protocol 5 Validate App Identity Success Response\",\n  \"description\": \"Message sent by the Desktop Agent to an app after successful identity validation.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP5ValidateAppIdentityResponseBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP5ValidateAppIdentityResponseBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP5ValidateAppIdentityResponse Message Type\",\n          \"const\": \"WCP5ValidateAppIdentityResponse\"\n        },\n        \"payload\": {\n          \"title\": \"WCP5ValidateAppIdentityResponse Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appId\": {\n              \"title\": \"appId\",\n              \"description\": \"The appId that the app's identity was validated against.\",\n              \"type\": \"string\"\n            },\n            \"instanceId\": {\n              \"title\": \"instanceId\",\n              \"description\": \"The instance Id granted to the application by the Desktop Agent.\",\n              \"type\": \"string\"\n            },\n            \"instanceUuid\": {\n              \"title\": \"instanceUuid\",\n              \"description\": \"Instance UUID associated with the instanceId granted, which may be used to retrieve the same instanceId if the app is reloaded or navigates.\",\n              \"type\": \"string\"\n            },\n            \"implementationMetadata\": {\n              \"title\": \"ImplementationMetadata\",\n              \"description\": \"Implementation metadata for the Desktop Agent, which includes an appMetadata element containing a copy of the app's own metadata.\",\n              \"$ref\": \"api.schema.json#/definitions/ImplementationMetadata\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"appId\",\n            \"instanceId\",\n            \"instanceUuid\",\n            \"implementationMetadata\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCP6Goodbye.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCP6Goodbye.schema.json\",\n  \"title\": \"Web Connection Protocol 6 Goodbye\",\n  \"description\": \"Goodbye message to be sent to the Desktop Agent when disconnecting (e.g. when closing the window or navigating). Desktop Agents should close the MessagePort after receiving this message, but retain instance details in case the application reconnects (e.g. after a navigation event).\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP6GoodbyeBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP6GoodbyeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP6Goodbye Message Type\",\n          \"const\": \"WCP6Goodbye\"\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/DisconnectStepMeta\"\n        }\n      },\n      \"required\": [ \"type\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/WCPConnectionStep.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/WCPConnectionStep.schema.json\",\n  \"title\": \"Web Connection Protocol Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used during the connection flow for an application to a Desktop Agent in a browser window. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Connection Step Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"WCP1Hello\",\n        \"WCP2LoadUrl\",\n        \"WCP3Handshake\",\n        \"WCP4ValidateAppIdentity\",\n        \"WCP5ValidateAppIdentityFailedResponse\",\n        \"WCP5ValidateAppIdentityResponse\",\n        \"WCP6Goodbye\"\n      ],\n      \"description\": \"Identifies the type of the connection step message.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload, containing data pertaining to this connection step.\",\n      \"additionalProperties\": true\n    },\n    \"meta\": {\n      \"title\": \"Connection Step Metadata\",\n      \"description\": \"Metadata for a Web Connection Protocol message.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"#/$defs/DisconnectStepMeta\"\n        },\n        {\n          \"$ref\": \"#/$defs/ConnectionStepMeta\"\n        }\n      ]\n    }\n  },\n  \"required\": [\n    \"type\",\n    \"meta\"\n  ],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"ConnectionStepMeta\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"connectionAttemptUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ConnectionAttemptUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\n        \"timestamp\",\n        \"connectionAttemptUuid\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"DisconnectStepMeta\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\n        \"timestamp\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addContextListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addContextListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddContextListener Request\",\n\t\"description\": \"A request to add a context listener to a specified Channel OR to the current user channel. Where the listener is added to the current user channel (channelId == null), and this app has already been added to a user channel, client code should make a subsequent request to get the current context of that channel for this listener and then call its handler with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddContextListenerRequestType\": {\n\t\t\t\"title\": \"AddContextListener Request Message Type\",\n\t\t\t\"const\": \"addContextListenerRequest\"\n\t\t},\n\t\t\"AddContextListenerRequestPayload\": {\n\t\t\t\"title\": \"AddContextListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to add the listener to or `null` indicating that it should listen to the current user channel (at the time of broadcast).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of context to listen for OR `null` indicating that it should listen to all context types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\", \"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addContextListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addContextListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddContextListener Response\",\n\t\"description\": \"A response to a addContextListener request. Where the listener was added to the current user channel (channelId == null), and this app has already been added to a user channel, client code should make a subsequent request to get the current context of that channel for this listener and then call its handler with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddContextListenerResponseType\": {\n\t\t\t\"title\": \"AddContextListener Response Message Type\",\n\t\t\t\"const\": \"addContextListenerResponse\"\n\t\t},\n\t\t\"AddContextListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddContextListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"AddContextListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddContextListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddEventListener Request\",\n\t\"description\": \"A request to add an event listener for a specified event type to the Desktop Agent.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddEventListenerRequestType\": {\n\t\t\t\"title\": \"AddEventListener Request Message Type\",\n\t\t\t\"const\": \"addEventListenerRequest\"\n\t\t},\n\t\t\"AddEventListenerRequestPayload\": {\n\t\t\t\"title\": \"AddEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"title\": \"Event type\",\n\t\t\t\t\t\"description\": \"The type of the event to be listened to or `null` to listen to all event types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/FDC3EventType\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"type\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddEventListener Response\",\n\t\"description\": \"A response to an addEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddEventListenerResponseType\": {\n\t\t\t\"title\": \"AddEventListener Response Message Type\",\n\t\t\t\"const\": \"addEventListenerResponse\"\n\t\t},\n\t\t\"AddEventListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddEventListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"AddEventListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddEventListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addIntentListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addIntentListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddIntentListener Request\",\n\t\"description\": \"A request to add an Intent listener for a specified intent type.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddIntentListenerRequestType\": {\n\t\t\t\"title\": \"AddIntentListener Request Message Type\",\n\t\t\t\"const\": \"addIntentListenerRequest\"\n\t\t},\n\t\t\"AddIntentListenerRequestPayload\": {\n\t\t\t\"title\": \"AddIntentListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent name\",\n\t\t\t\t\t\"description\": \"The name of the intent to listen for.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/addIntentListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/addIntentListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddIntentListener Response\",\n\t\"description\": \"A response to a addIntentListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddIntentListenerResponseType\": {\n\t\t\t\"title\": \"AddIntentListener Response Message Type\",\n\t\t\t\"const\": \"addIntentListenerResponse\"\n\t\t},\n\t\t\"AddIntentListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddIntentListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t]\n\t\t},\n\t\t\"AddIntentListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddIntentListener Response Error Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/agentEvent.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/agentEvent.schema.json\",\n  \"title\": \"Agent Event Message\",\n  \"type\": \"object\",\n  \"description\": \"A message from a Desktop Agent to an FDC3-enabled app representing an event.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Event Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addEventListenerEvent\",\n        \"broadcastEvent\",\n        \"channelChangedEvent\",\n        \"heartbeatEvent\",\n        \"intentEvent\",\n        \"privateChannelOnAddContextListenerEvent\",\n        \"privateChannelOnDisconnectEvent\",\n        \"privateChannelOnUnsubscribeEvent\",\n        \"contextClearedEvent\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Event Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload contains details of the event that the app is being notified about.\",\n      \"additionalProperties\": true\n    },\n    \"meta\": {\n      \"title\": \"Event Metadata\",\n      \"description\": \"Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"eventUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/EventUuid\"\n        }\n      },\n      \"required\": [\"timestamp\", \"eventUuid\"],\n      \"additionalProperties\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/agentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/agentResponse.schema.json\",\n  \"title\": \"Agent Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the payload contains an `error` property, the request was unsuccessful.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addContextListenerResponse\",\n        \"addEventListenerResponse\",\n        \"addIntentListenerResponse\",\n        \"broadcastResponse\",\n        \"contextListenerUnsubscribeResponse\",\n        \"createPrivateChannelResponse\",\n        \"eventListenerUnsubscribeResponse\",\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"getCurrentChannelResponse\",\n        \"getCurrentContextResponse\",\n        \"getInfoResponse\",\n        \"getOrCreateChannelResponse\",\n        \"getUserChannelsResponse\",\n        \"intentListenerUnsubscribeResponse\",\n        \"intentResultResponse\",\n        \"joinUserChannelResponse\",\n        \"leaveCurrentChannelResponse\",\n        \"openResponse\",\n        \"privateChannelAddEventListenerResponse\",\n        \"privateChannelDisconnectResponse\",\n        \"privateChannelUnsubscribeEventListenerResponse\",\n        \"raiseIntentForContextResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\",\n        \"clearContextResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Payload\",\n      \"type\": \"object\",\n      \"description\": \"A payload for a response to an API call that will contain any return values or an `error` property containing a standardized error message indicating that the request was unsuccessful.\",\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {},\n          \"additionalProperties\": true\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n            }\n          },\n          \"required\": [\n            \"error\"\n          ],\n          \"additionalProperties\": false\n        }\n      ]\n    },\n    \"meta\": {\n      \"title\": \"Agent Response Message Metadata\",\n      \"description\": \"Metadata for messages sent by a Desktop Agent to an app in response to an API call.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"source\": {\n          \"title\": \"Original Source AppIdentifier\",\n          \"description\": \"Field that represents the source application that the request being responded to was received from, for debugging purposes.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\n        \"timestamp\",\n        \"requestUuid\",\n        \"responseUuid\"\n      ],\n      \"additionalProperties\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\n    \"type\",\n    \"payload\",\n    \"meta\"\n  ]\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/api.schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/next/api/api.schema.json\",\n    \"title\": \"FDC3 Desktop Agent API Schemas\",\n    \"definitions\": {\n        \"AppIdentifier\": {\n            \"description\": \"Identifies an application, or instance of an application, and is used to target FDC3 API calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application instances.\\n\\nWill always include at least an `appId` field, which uniquely identifies a specific app.\\n\\nIf the `instanceId` field is set then the `AppMetadata` object represents a specific instance of the application that may be addressed using that Id.\",\n            \"title\": \"AppIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"Icon\": {\n            \"description\": \"Describes an Icon image that may be used to represent the application.\",\n            \"title\": \"Icon\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The icon url.\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The icon dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Icon media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"Image\": {\n            \"description\": \"Describes an image file, typically a screenshot, that often represents the application in a common usage scenario.\",\n            \"title\": \"Image\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The image url.\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The image dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"label\": {\n                    \"description\": \"Caption for the image.\",\n                    \"type\": \"string\",\n                    \"title\": \"label\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"AppMetadata\": {\n            \"description\": \"Extends an `AppIdentifier`, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the Desktop Agent connects to.\\n\\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\\n\\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\",\n            \"title\": \"AppMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The 'friendly' app name. \\nThis field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier` wth `appId` set. \\nNote that for display purposes the `title` field should be used, if set, in preference to this field.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"version\": {\n                    \"description\": \"The Version of the application.\",\n                    \"type\": \"string\",\n                    \"title\": \"version\"\n                },\n                \"instanceMetadata\": {\n                    \"description\": \"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.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true,\n                    \"title\": \"instanceMetadata\"\n                },\n                \"title\": {\n                    \"description\": \"A more user-friendly application title that can be used to render UI elements.\",\n                    \"type\": \"string\",\n                    \"title\": \"title\"\n                },\n                \"tooltip\": {\n                    \"description\": \"A tooltip for the application that can be used to render UI elements.\",\n                    \"type\": \"string\",\n                    \"title\": \"tooltip\"\n                },\n                \"description\": {\n                    \"description\": \"A longer, multi-paragraph description for the application that could include markup.\",\n                    \"type\": \"string\",\n                    \"title\": \"description\"\n                },\n                \"icons\": {\n                    \"description\": \"A list of icon URLs for the application that can be used to render UI elements.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Icon\"\n                    },\n                    \"title\": \"icons\"\n                },\n                \"screenshots\": {\n                    \"description\": \"Images representing the app in common usage scenarios that can be used to render UI elements.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Image\"\n                    },\n                    \"title\": \"screenshots\"\n                },\n                \"resultType\": {\n                    \"description\": \"The type of output 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 (e.g. \\\"channel<fdc3.instrument>\\\").\",\n                    \"type\": [\n                        \"null\",\n                        \"string\"\n                    ],\n                    \"title\": \"resultType\"\n                },\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"IntentMetadata\": {\n            \"description\": \"Metadata describing an Intent.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The unique name of the intent that can be invoked by the raiseIntent call.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"displayName\": {\n                    \"description\": \"Display name for the intent.\",\n                    \"type\": \"string\",\n                    \"title\": \"displayName\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"name\"\n            ]\n        },\n        \"AppIntent\": {\n            \"description\": \"An interface that relates an intent to apps.\",\n            \"title\": \"AppIntent\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"intent\": {\n                    \"$ref\": \"#/definitions/IntentMetadata\",\n                    \"description\": \"Details of the intent whose relationship to resolving applications is being described.\",\n                    \"title\": \"intent\"\n                },\n                \"apps\": {\n                    \"description\": \"Details of applications that can resolve the intent.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/AppMetadata\"\n                    },\n                    \"title\": \"apps\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"apps\",\n                \"intent\"\n            ]\n        },\n        \"DisplayMetadata\": {\n            \"description\": \"A system channel will be global enough to have a presence across many apps. This gives us some hints\\nto render them in a standard way. It is assumed it may have other properties too, but if it has these,\\nthis is their meaning.\",\n            \"title\": \"DisplayMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"A user-readable name for this channel, e.g: `\\\"Red\\\"`.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"color\": {\n                    \"description\": \"The color that should be associated within this channel when displaying this channel in a UI, e.g: `0xFF0000`.\",\n                    \"type\": \"string\",\n                    \"title\": \"color\"\n                },\n                \"glyph\": {\n                    \"description\": \"A URL of an image that can be used to display this channel.\",\n                    \"type\": \"string\",\n                    \"title\": \"glyph\"\n                }\n            },\n            \"additionalProperties\": false\n        },\n        \"Channel\": {\n            \"description\": \"Represents a context channel that applications can use to send and receive\\ncontext data.\\n\\nPlease note that There are differences in behavior when you interact with a\\nUser channel via the `DesktopAgent` interface and the `Channel` interface.\\nSpecifically, when 'joining' a User channel or adding a context listener\\nwhen already joined to a channel via the `DesktopAgent` interface, existing\\ncontext (matching the type of the context listener) on the channel is\\nreceived by the context listener immediately. Whereas, when a context\\nlistener is added via the Channel interface, context is not received\\nautomatically, but may be retrieved manually via the `getCurrentContext()`\\nfunction.\",\n            \"title\": \"Channel\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"id\": {\n                    \"description\": \"Constant that uniquely identifies this channel.\",\n                    \"type\": \"string\",\n                    \"title\": \"id\"\n                },\n                \"type\": {\n                    \"description\": \"Uniquely defines each channel type.\\nCan be \\\"user\\\", \\\"app\\\" or \\\"private\\\".\",\n                    \"enum\": [\n                        \"app\",\n                        \"private\",\n                        \"user\"\n                    ],\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"displayMetadata\": {\n                    \"description\": \"Channels may be visualized and selectable by users. DisplayMetadata may be used to provide hints on how to see them.\\nFor App channels, displayMetadata would typically not be present.\",\n                    \"$ref\": \"#/definitions/DisplayMetadata\",\n                    \"title\": \"displayMetadata\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"id\",\n                \"type\"\n            ]\n        },\n        \"ContextMetadata\": {\n            \"description\": \"Metadata relating to a context or intent and context received through the\\n`addContextListener` and `addIntentListener` functions.\",\n            \"title\": \"ContextMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that sent the context and/or intent.\",\n                    \"title\": \"source\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"source\"\n            ]\n        },\n        \"DesktopAgentIdentifier\": {\n            \"description\": \"Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\\nwhere a request needs to be directed to a Desktop Agent rather than a specific app, or a\\nresponse message is returned by the Desktop Agent (or more specifically its resolver)\\nrather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\\napp details are available or are appropriate.\",\n            \"title\": \"DesktopAgentIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"desktopAgent\": {\n                    \"description\": \"Used in Desktop Agent Bridging to attribute or target a message to a\\nparticular Desktop Agent.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"desktopAgent\"\n            ]\n        },\n        \"OpenError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`).\",\n            \"title\": \"OpenError\",\n            \"enum\": [\n                \"AppNotFound\",\n                \"AppTimeout\",\n                \"DesktopAgentNotFound\",\n                \"ErrorOnLaunch\",\n                \"MalformedContext\",\n                \"ResolverUnavailable\",\n                \"ApiTimeout\",\n                \"InvalidArguments\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResolveError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `addIntentListener`, `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\",\n            \"title\": \"ResolveError\",\n            \"enum\": [\n                \"DesktopAgentNotFound\",\n                \"IntentDeliveryFailed\",\n                \"MalformedContext\",\n                \"NoAppsFound\",\n                \"ResolverTimeout\",\n                \"ResolverUnavailable\",\n                \"TargetAppUnavailable\",\n                \"TargetInstanceUnavailable\",\n                \"UserCancelledResolution\",\n                \"ApiTimeout\",\n                \"InvalidArguments\",\n                \"IntentListenerConflict\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResultError\": {\n            \"title\": \"ResultError\",\n            \"enum\": [\n                \"IntentHandlerRejected\",\n                \"NoResultReturned\",\n                \"ApiTimeout\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ChannelError\": {\n            \"title\": \"ChannelError\",\n            \"enum\": [\n                \"AccessDenied\",\n                \"CreationFailed\",\n                \"MalformedContext\",\n                \"NoChannelFound\",\n                \"ApiTimeout\",\n                \"InvalidArguments\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BridgingError\": {\n            \"title\": \"BridgingError\",\n            \"enum\": [\n                \"AgentDisconnected\",\n                \"NotConnectedToBridge\",\n                \"ResponseToBridgeTimedOut\",\n                \"MalformedMessage\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BaseImplementationMetadata\": {\n            \"description\": \"Metadata relating to the FDC3 Desktop Agent implementation and its provider.\",\n            \"title\": \"BaseImplementationMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"fdc3Version\": {\n                    \"description\": \"The version number of the FDC3 specification that the implementation provides.\\nThe string must be a numeric semver version, e.g. 1.2 or 1.2.1.\",\n                    \"type\": \"string\",\n                    \"title\": \"fdc3Version\"\n                },\n                \"provider\": {\n                    \"description\": \"The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42, OpenFin etc.).\",\n                    \"type\": \"string\",\n                    \"title\": \"provider\"\n                },\n                \"providerVersion\": {\n                    \"description\": \"The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\",\n                    \"type\": \"string\",\n                    \"title\": \"providerVersion\"\n                },\n                \"optionalFeatures\": {\n                    \"description\": \"Metadata indicating whether the Desktop Agent implements optional features of\\nthe Desktop Agent API.\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"OriginatingAppMetadata\": {\n                            \"description\": \"Used to indicate whether the exposure of 'originating app metadata' for\\ncontext and intent messages is supported by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"OriginatingAppMetadata\"\n                        },\n                        \"UserChannelMembershipAPIs\": {\n                            \"description\": \"Used to indicate whether the optional `fdc3.joinUserChannel`,\\n`fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\\nthe Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"UserChannelMembershipAPIs\"\n                        },\n                        \"DesktopAgentBridging\": {\n                            \"description\": \"Used to indicate whether the experimental Desktop Agent Bridging\\nfeature is implemented by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"DesktopAgentBridging\"\n                        }\n                    },\n                    \"additionalProperties\": false,\n                    \"required\": [\n                        \"DesktopAgentBridging\",\n                        \"OriginatingAppMetadata\",\n                        \"UserChannelMembershipAPIs\"\n                    ],\n                    \"title\": \"optionalFeatures\"\n                }\n            },\n            \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\"\n            ]\n        },\n        \"ImplementationMetadata\": {\n            \"description\": \"Includes Metadata for the current application.\",\n            \"title\": \"ImplementationMetadata\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"$ref\": \"#/definitions/BaseImplementationMetadata\"\n                },\n                {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"appMetadata\": {\n                            \"$ref\": \"#/definitions/AppMetadata\",\n                            \"description\": \"The calling application instance's own metadata, according to the Desktop Agent (MUST include at least the `appId` and `instanceId`).\",\n                            \"title\": \"appMetadata\"\n                        }\n                    }\n                }\n            ],\n            \"properties\": {\n                \"fdc3Version\": true,\n                \"provider\": true,\n                \"providerVersion\": true,\n                \"optionalFeatures\": true,\n                \"appMetadata\": true\n            },\n            \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\",\n                \"appMetadata\"\n            ],\n            \"additionalProperties\": false\n        },\n        \"IntentResolution\": {\n            \"description\": \"IntentResolution provides a standard format for data returned upon resolving an intent.\\n\\n```javascript\\n//resolve a \\\"Chain\\\" type intent\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\n\\n//resolve a \\\"Client-Service\\\" type intent with a data response or a Channel\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\ntry {\\n\\t   const result = await resolution.getResult();\\n    if (result && result.broadcast) {\\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\\n    } else if (result){\\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\\n    } else {\\n        console.error(`${resolution.source} didn't return data`\\n    }\\n} catch(error) {\\n    console.error(`${resolution.source} returned an error: ${error}`);\\n}\\n\\n// Use metadata about the resolving app instance to target a further intent\\nawait agent.raiseIntent(\\\"intentName\\\", context, resolution.source);\\n```\",\n            \"title\": \"IntentResolution\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that was selected (or started) to resolve the intent.\\n`source.instanceId` MUST be set, indicating the specific app instance that\\nreceived the intent.\",\n                    \"title\": \"source\"\n                },\n                \"intent\": {\n                    \"description\": \"The intent that was raised. May be used to determine which intent the user\\nchose in response to `fdc3.raiseIntentForContext()`.\",\n                    \"type\": \"string\",\n                    \"title\": \"intent\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"intent\",\n                \"source\"\n            ]\n        },\n        \"IntentResult\": {\n            \"title\": \"IntentResult\",\n            \"anyOf\": [\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Context\",\n                    \"properties\": {\n                        \"context\": {\n                            \"$ref\": \"../context/context.schema.json\"\n                        }\n                    },\n                    \"required\": [\n                        \"context\"\n                    ],\n                    \"additionalProperties\": false\n                },\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Channel\",\n                    \"properties\": {\n                        \"channel\": {\n                            \"$ref\": \"#/definitions/Channel\"\n                        }\n                    },\n                    \"required\": [\n                        \"channel\"\n                    ],\n                    \"additionalProperties\": false\n                },\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Void\",\n                    \"properties\": {},\n                    \"additionalProperties\": false\n                }\n            ]\n        },\n        \"FDC3EventType\": {\n            \"title\": \"FDC3 Event Type\",\n            \"description\": \"The type of a (non-context and non-intent) event that may be received via the FDC3 API's addEventListener function.\",\n            \"type\": \"string\",\n            \"enum\": [\n                \"USER_CHANNEL_CHANGED\"\n            ]\n        },\n        \"FDC3Event\": {\n            \"title\": \"FDC3 Event\",\n            \"description\": \"An event object received via the FDC3 API's addEventListener function. Will always include both type and details, which describe type of the event and any additional details respectively.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"type\": {\n                    \"$ref\": \"#/definitions/FDC3EventType\"\n                },\n                \"details\": {\n                    \"title\": \"Event details\",\n                    \"description\": \"Additional details of the event, such as the `currentChannelId` for a CHANNEL_CHANGED event.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true\n                }\n            },\n            \"required\":[\"type\",\"details\"],\n            \"additionalProperties\": false\n        },\n        \"PrivateChannelEventType\": {\n            \"title\": \"PrivateChannel Event Type\",\n            \"description\": \"Type defining valid type strings for Private Channel events.\",\n            \"type\": \"string\",\n            \"enum\": [\n                \"addContextListener\",\n                \"unsubscribe\",\n                \"disconnect\"\n            ]\n        },\n        \"PrivateChannelEvent\": {\n            \"description\": \"Type defining the format of event objects that may be received via a PrivateChannel's addEventListener function.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"type\": {\n                    \"$ref\": \"#/definitions/PrivateChannelEventType\"\n                },\n                \"details\": {\n                    \"title\": \"Event details\",\n                    \"description\": \"Additional details of the event, such as the `currentChannelId` for a CHANNEL_CHANGED event.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true\n                }\n            },\n            \"required\":[\"type\",\"details\"],\n            \"additionalProperties\": false\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/appRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/appRequest.schema.json\",\n  \"title\": \"App Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message from an FDC3-enabled app to a Desktop Agent.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Request Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addContextListenerRequest\",\n        \"addEventListenerRequest\",\n        \"addIntentListenerRequest\",\n        \"broadcastRequest\",\n        \"contextListenerUnsubscribeRequest\",\n        \"createPrivateChannelRequest\",\n        \"eventListenerUnsubscribeRequest\",\n        \"findInstancesRequest\",\n        \"findIntentRequest\",\n        \"findIntentsByContextRequest\",\n        \"getAppMetadataRequest\",\n        \"getCurrentChannelRequest\",\n        \"getCurrentContextRequest\",\n        \"getInfoRequest\",\n        \"getOrCreateChannelRequest\",\n        \"getUserChannelsRequest\",\n        \"heartbeatAcknowledgementRequest\",\n        \"intentListenerUnsubscribeRequest\",\n        \"intentResultRequest\",\n        \"joinUserChannelRequest\",\n        \"leaveCurrentChannelRequest\",\n        \"openRequest\",\n        \"privateChannelAddEventListenerRequest\",\n        \"privateChannelDisconnectRequest\",\n        \"privateChannelUnsubscribeEventListenerRequest\",\n        \"raiseIntentForContextRequest\",\n        \"raiseIntentRequest\",\n        \"clearContextRequest\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Request payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"title\": \"Request Metadata\",\n      \"description\": \"Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Source AppIdentifier\",\n          \"description\": \"Field that represents the source application that a request or response was received from. Please note that this may be set by an app or Desktop Agent proxy for debugging purposes but a Desktop Agent should make its own determination of the source of a message to avoid spoofing.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/broadcastEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/broadcastEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"broadcast Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that context has been broadcast on a channel it is listening to, or specifically to this app instance if it was launched via `fdc3.open` and context was passed.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastEventType\": {\n\t\t\t\"title\": \"Broadcast Event Message Type\",\n\t\t\t\"const\": \"broadcastEvent\"\n\t\t},\n\t\t\"BroadcastEventPayload\": {\n\t\t\t\"title\": \"broadcast Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the channel that the broadcast was sent on. May be `null` if the context is being broadcast due to a call `fdc3.open` that passed context.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object that was broadcast.\"\n\t\t\t\t},\n\t\t\t\t\"originatingApp\": {\n\t\t\t\t\t\"title\": \"Originating AppIdentifier\",\n\t\t\t\t\t\"description\": \"Details of the application instance that broadcast the context.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\", \"context\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/broadcastRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/broadcastRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Broadcast Request\",\n\t\"description\": \"A request to broadcast context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastRequestType\": {\n\t\t\t\"title\": \"Broadcast Request Message Type\",\n\t\t\t\"const\": \"broadcastRequest\"\n\t\t},\n\t\t\"BroadcastRequestPayload\": {\n\t\t\t\"title\": \"broadcast Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the Channel that the broadcast was sent on.\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object that is to be broadcast.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\",\n\t\t\t\t\"context\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/broadcastResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/broadcastResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Broadcast Response\",\n\t\"description\": \"A response to a request to broadcast context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastResponseType\": {\n\t\t\t\"title\": \"Broadcast Response Message Type\",\n\t\t\t\"const\": \"broadcastResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/channelChangedEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/channelChangedEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"channelChanged Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that its current user channel has changed.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ChannelChangedEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ChannelChangedEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ChannelChangedEventType\": {\n\t\t\t\"title\": \"ChannelChanged Event Message Type\",\n\t\t\t\"const\": \"channelChangedEvent\"\n\t\t},\n\t\t\"ChannelChangedEventPayload\": {\n\t\t\t\"title\": \"channelChanged Event Payload\",\n\t\t\t\"type\": \"object\",\n      \"anyOf\": [\n        {\n          \"deprecated\": true,\n          \"properties\": {\n    \t\t\t\t\"newChannelId\": {\n    \t\t\t\t\t\"title\": \"New Channel Id\",\n    \t\t\t\t\t\"description\": \"Deprecated - allowed for backwards compatibility.  The Id of the channel that the app was added to or `null` if it was removed from a channel.\",\n    \t\t\t\t\t\"oneOf\": [\n    \t\t\t\t\t\t{\n    \t\t\t\t\t\t\t\"type\": \"string\"\n    \t\t\t\t\t\t},\n    \t\t\t\t\t\t{\n    \t\t\t\t\t\t\t\"type\": \"null\"\n    \t\t\t\t\t\t}\n    \t\t\t\t\t]\n    \t\t\t\t}\n    \t\t\t},\n    \t\t\t\"additionalProperties\": false,\n    \t\t\t\"required\": [\n    \t\t\t\t\"newChannelId\"\n    \t\t\t]\n        },{\n          \"properties\": {\n    \t\t\t\t\"currentChannelId\": {\n    \t\t\t\t\t\"title\": \"Current Channel Id\",\n    \t\t\t\t\t\"description\": \"The Id of the channel that the app was added to or `null` if it was removed from a channel.\",\n    \t\t\t\t\t\"oneOf\": [\n    \t\t\t\t\t\t{\n    \t\t\t\t\t\t\t\"type\": \"string\"\n    \t\t\t\t\t\t},\n    \t\t\t\t\t\t{\n    \t\t\t\t\t\t\t\"type\": \"null\"\n    \t\t\t\t\t\t}\n    \t\t\t\t\t]\n    \t\t\t\t}\n    \t\t\t},\n    \t\t\t\"additionalProperties\": false,\n    \t\t\t\"required\": [\n    \t\t\t\t\"currentChannelId\"\n    \t\t\t]\n        }  \n      ]\n\t\t\t\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/clearContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/clearContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Clear Context Request\",\n\t\"description\": \"A request to clear context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ClearContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ClearContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ClearContextRequestType\": {\n\t\t\t\"title\": \"Clear Context Request Message Type\",\n\t\t\t\"const\": \"clearContextRequest\"\n\t\t},\n\t\t\"ClearContextRequestPayload\": {\n\t\t\t\"title\": \"Clear Context Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to clear the context on.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of context to clear for OR `null` indicating that all context types on the channel should be cleared.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"channelId\", \"contextType\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/clearContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/clearContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Clear Context Response\",\n\t\"description\": \"A response to a request to clear context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ClearContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ClearContextResponseType\": {\n\t\t\t\"title\": \"Clear Context Response Message Type\",\n\t\t\t\"const\": \"clearContextResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/common.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/common.schema.json\",\n  \"title\": \"Common definitions\",\n  \"type\": \"object\",\n  \"description\": \"Common definitions that are referenced in the API and Bridging Wire Protocol schemas.\",\n  \"$defs\": {\n    \"ConnectionAttemptUuid\": {\n      \"title\": \"Connection Attempt UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a for an attempt to connect to a Desktop Agent. A Unique UUID should be used in the first (WCP1Hello) message and should be quoted in all subsequent messages to link them to the same connection attempt.\"\n    },\n    \"RequestUuid\": {\n      \"title\": \"Request UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a request or event message. Required in all message types.\"\n    },\n    \"ResponseUuid\": {\n      \"title\": \"Response UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a response to a specific message and must always be accompanied by a RequestUuid.\"\n    },\n    \"EventUuid\": {\n      \"title\": \"Event UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for an event message sent from a Desktop Agent to an app.\"\n    },\n    \"ListenerUuid\": {\n      \"title\": \"Listener UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a `listener` object returned by a Desktop Agent to an app in response to addContextListener, addIntentListener or one of the PrivateChannel event listeners and used to identify it in messages (e.g. when unsubscribing).\"\n    },\n    \"Timestamp\": {\n      \"title\": \"Timestamp\",\n      \"type\": \"string\",\n      \"format\": \"date-time\",\n      \"description\": \"Timestamp at which the message was generated.\"\n    },\n    \"ErrorMessages\": {\n      \"oneOf\": [\n        {\n          \"$ref\": \"api.schema.json#/definitions/ChannelError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/OpenError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/ResolveError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/ResultError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/BridgingError\"\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/contextClearedEvent.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/contextClearedEvent.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"contextCleared Event\",\n  \"description\": \"An event message from the Desktop Agent to an app indicating that context has been cleared on a channel.\",\n  \"allOf\": [\n    {\n      \"$ref\": \"agentEvent.schema.json\"\n    },\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"#/$defs/ContextClearedEventType\"\n        },\n        \"payload\": {\n          \"$ref\": \"#/$defs/ContextClearedEventPayload\"\n        },\n        \"meta\": true\n      },\n      \"additionalProperties\": false\n    }\n  ],\n  \"$defs\": {\n    \"ContextClearedEventType\": {\n      \"title\": \"ContextCleared Event Message Type\",\n      \"const\": \"contextClearedEvent\"\n    },\n    \"ContextClearedEventPayload\": {\n      \"title\": \"contextCleared Event Payload\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"channelId\": {\n          \"title\": \"Channel Id\",\n          \"description\": \"The Id of the channel that was cleared.\",\n          \"type\": [\"string\", \"null\"]\n        },\n        \"contextType\": {\n          \"title\": \"Context Type\",\n          \"description\": \"The type of context that was cleared, or null if all types were cleared.\",\n          \"type\": [\"string\", \"null\"]\n        }\n      },\n      \"required\": [\"channelId\", \"contextType\"],\n      \"additionalProperties\": false\n    }\n}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/contextListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/contextListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"ContextListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ContextListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"contextListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"ContextListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/contextListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/contextListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"ContextListenerUnsubscribe Response\",\n\t\"description\": \"A response to a contextListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ContextListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"contextListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/createPrivateChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/createPrivateChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"CreatePrivateChannel Request\",\n\t\"description\": \"Request to return a Channel with an auto-generated identity that is intended for private communication between applications.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"CreatePrivateChannelRequestType\": {\n\t\t\t\"title\": \"CreatePrivateChannel Request Message Type\",\n\t\t\t\"const\": \"createPrivateChannelRequest\"\n\t\t},\n\t\t\"CreatePrivateChannelRequestPayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/createPrivateChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/createPrivateChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"CreatePrivateChannel Response\",\n\t\"description\": \"A response to a createPrivateChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"CreatePrivateChannelResponseType\": {\n\t\t\t\"title\": \"CreatePrivateChannel Response Message Type\",\n\t\t\t\"const\": \"createPrivateChannelResponse\"\n\t\t},\n\t\t\"CreatePrivateChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannel\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"CreatePrivateChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/eventListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/eventListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"EventListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe an event listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"EventListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"eventListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"EventListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/eventListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/eventListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"EventListenerUnsubscribe Response\",\n\t\"description\": \"A response to an eventListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"EventListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"eventListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceChannelSelected.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceChannelSelected.schema.json\",\n  \"title\": \"Fdc3 UserInterface Channel Selected\",\n  \"description\": \"Message from a channel selector UI to the DA proxy sent when the channel selection changes.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceChannelSelectedBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceChannelSelectedBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface ChannelSelected Message Type\",\n          \"const\": \"Fdc3UserInterfaceChannelSelected\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface ChannelSelected Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"selected\": {\n              \"title\": \"Selected Channel\",\n              \"description\": \"The id of the channel that should be currently selected, or `null` if none should be selected.\",\n              \"oneOf\": [\n                {\"type\": \"string\"}, {\"type\": \"null\"}\n              ]\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"selected\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceChannels.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceChannels.schema.json\",\n  \"title\": \"Fdc3 UserInterface Channels\",\n  \"description\": \"Setup message sent by the DA proxy code in getAgent() to a channel selector UI in an iframe with the channel definitions and current channel selection.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceChannelsBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceChannelsBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Channels Message Type\",\n          \"const\": \"Fdc3UserInterfaceChannels\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Channels Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"userChannels\": {\n              \"title\": \"User Channels\",\n              \"description\": \"User Channel definitions.```````s\",\n              \"type\": \"array\",\n              \"items\": {\n                \"$ref\": \"api.schema.json#/definitions/Channel\"\n              }\n            },\n            \"selected\": {\n              \"title\": \"Selected Channel\",\n              \"description\": \"The id of the channel that should be currently selected, or `null` if none should be selected.\",\n              \"oneOf\": [\n                {\"type\": \"string\"}, {\"type\": \"null\"}\n              ]\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"userChannels\", \"selected\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceDrag.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceDrag.schema.json\",\n  \"title\": \"Fdc3 UserInterface Drag\",\n  \"description\": \"Message from a UI iframe to the DA proxy (setup by `getAgent()`) indicating that the user is dragging the UI to a new location and providing the offset to apply to the location. The DA proxy implementation should limit the location to the current bounds of the window's viewport.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceDragBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceDragBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Drag Message Type\",\n          \"const\": \"Fdc3UserInterfaceDrag\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Drag Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"mouseOffsets\": {\n              \"title\": \"Mouse Offsets\",\n              \"description\": \"The offset to move the frame by.\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"x\": {\n                  \"type\": \"integer\"\n                },\n                \"y\": {\n                  \"type\": \"integer\"\n                }\n              },\n              \"required\": [\"x\", \"y\"],\n              \"additionalProperties\": false\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"mouseOffsets\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceHandshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceHandshake.schema.json\",\n  \"title\": \"Fdc3 UserInterface Handshake\",\n  \"description\": \"Handshake message sent back to a user interface from the DA proxy code (setup by `getAgent()`) over the `MessagePort` provided in the preceding Fdc3UserInterfaceHello message, confirming that it is listening to the `MessagePort` for further communication.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceHandshakeBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceHandshakeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Handshake Message Type\",\n          \"const\": \"Fdc3UserInterfaceHandshake\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Handshake Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"type\": \"string\",\n              \"description\": \"The version of FDC3 API that the Desktop Agent will provide support for.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"fdc3Version\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceHello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceHello.schema.json\",\n  \"title\": \"Fdc3 UserInterface Hello\",\n  \"description\": \"Hello message sent by a UI to the Desktop Agent proxy setup by `getAgent()` to indicate it is ready to communicate, containing initial CSS to set on the iframe, and including an appended `MessagePort` to be used for further communication.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceHelloBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceHelloBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Hello Message Type\",\n          \"const\": \"Fdc3UserInterfaceHello\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Hello Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"implementationDetails\": {\n              \"title\": \"Implementation Details\",\n              \"type\": \"string\",\n              \"description\": \"Details about the UI implementation, such as vendor and version, for logging purposes.\"\n            },\n            \"initialCSS\": {\n              \"title\": \"Initial CSS\",\n              \"type\": \"object\",\n              \"description\": \"A constrained set of styling properties that should be set on the user interface before it is displayed. Note `position` cannot be specified and should always be set to `fixed`.\",\n              \"properties\": {\n                \"height\": {\"type\": \"string\", \"title\": \"height\", \"description\": \"The initial height of the iframe.\"},\n                \"width\": {\"type\": \"string\", \"title\": \"width\", \"description\": \"The initial width of the iframe.\"},\n                \"zIndex\": {\"type\": \"string\", \"title\": \"zIndex\", \"description\": \"The initial zindex to apply to the iframe.\"},\n                \"left\": {\"type\": \"string\", \"title\": \"left\", \"description\": \"The initial left property to apply to the iframe.\"},\n                \"top\": {\"type\": \"string\", \"title\": \"top\", \"description\": \"The initial top property to apply to the iframe.\"},\n                \"bottom\": {\"type\": \"string\", \"title\": \"bottom\", \"description\": \"The initial bottom property to apply to the iframe.\"},\n                \"right\": {\"type\": \"string\", \"title\": \"right\", \"description\": \"The initial right property to apply to the iframe.\"},\n                \"transition\": {\"type\": \"string\", \"title\": \"transition\", \"description\": \"The transition property to apply to the iframe.\"},\n                \"maxHeight\": {\"type\": \"string\", \"title\": \"maxHeight\", \"description\": \"The maximum height to apply to the iframe.\"},\n                \"maxWidth\": {\"type\": \"string\", \"title\": \"maxWidth\", \"description\": \"The maximum with to apply to the iframe.\"}\n              },\n              \"required\": []\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"implementationDetails\",\"initialCSS\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceMessage.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceMessage.schema.json\",\n  \"title\": \"Fdc3 UserInterface Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used to communicate with user interface frames injected by `getAgent()` for displaying UI elements such as the intent resolver or channel selector. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Fdc3 UserInterface Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"Fdc3UserInterfaceHello\",\n        \"Fdc3UserInterfaceHandshake\",\n        \"Fdc3UserInterfaceRestyle\",\n        \"Fdc3UserInterfaceDrag\",\n        \"Fdc3UserInterfaceResolve\",\n        \"Fdc3UserInterfaceResolveAction\",\n        \"Fdc3UserInterfaceChannels\",\n        \"Fdc3UserInterfaceChannelSelected\"\n      ],\n      \"description\": \"Identifies the type of the message to or from the user interface frame.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload.\",\n      \"additionalProperties\": true\n    }\n  },\n  \"required\": [\n    \"type\"\n  ],\n  \"additionalProperties\": false\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceResolve.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceResolve.schema.json\",\n  \"title\": \"Fdc3 UserInterface Resolve\",\n  \"description\": \"Setup message sent by the DA proxy code in getAgent() to an intent resolver UI with the resolver data to setup the UI.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceResolveBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Resolve Message Type\",\n          \"const\": \"Fdc3UserInterfaceResolve\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Resolve Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\"\n            },\n            \"appIntents\": {\n              \"title\": \"Resolution options\",\n              \"type\": \"array\",\n              \"description\": \"An array of AppIntent objects defining the resolution options.\",\n              \"items\": {\n                \"$ref\": \"api.schema.json#/definitions/AppIntent\"\n              },\n              \"additionalProperties\": false\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"context\", \"appIntents\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceResolveAction.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceResolveAction.schema.json\",\n  \"title\": \"Fdc3 UserInterface Resolve Action\",\n  \"description\": \"Message from an intent resolver UI to DA proxy code in getAgent() reporting a user action.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveActionBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceResolveActionBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface ResolveAction Message Type\",\n          \"const\": \"Fdc3UserInterfaceResolveAction\"\n        },\n        \"payload\": {\n          \"oneOf\": [\n            { \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveActionPayload\"},\n            { \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveCancelPayload\"}\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"Fdc3UserInterfaceResolveActionPayload\": {\n      \"title\": \"Fdc3 UserInterface Resolve Action Payload\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"intent\": {\n          \"title\": \"Intent name\",\n          \"type\": \"string\",\n          \"description\": \"The intent resolved.\"\n        },\n        \"appIdentifier\": {\n          \"title\": \"AppIdentifier\",\n          \"description\": \"The App resolution option chosen.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        },\n        \"action\": {\n          \"oneOf\": [\n            {\n              \"type\": \"string\",\n              \"const\": \"hover\"\n            },\n            {\n              \"type\": \"string\",\n              \"const\": \"click\"\n            }\n          ]\n        }\n      },\n      \"required\": [\n        \"intent\",\n        \"appIdentifier\",\n        \"action\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"Fdc3UserInterfaceResolveCancelPayload\": {\n      \"title\": \"Fdc3 UserInterface Resolve Cancel Payload\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"action\": {\n          \"type\": \"string\",\n          \"const\": \"cancel\"\n        }\n      },\n      \"required\": [\n        \"action\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/fdc3UserInterfaceRestyle.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/api/fdc3UserInterfaceRestyle.schema.json\",\n  \"title\": \"Fdc3 UserInterface Restyle\",\n  \"description\": \"Message from a UI frame to the DA proxy code (setup by `getAgent()`) with updated styling information to apply to it. Can be used to implement a pop-open or close interaction or other transition needed by a UI implementation.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceRestyleBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceRestyleBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Restyle Message Type\",\n          \"const\": \"Fdc3UserInterfaceRestyle\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Restyle Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"updatedCSS\": {\n              \"title\": \"Updated CSS\",\n              \"type\": \"object\",\n              \"description\": \"A constrained set of styling properties that should be applied to the frame. Note `position` cannot be set, and should always be `fixed`.\",\n              \"properties\": {\n                \"height\": {\"type\": \"string\", \"title\": \"height\", \"description\": \"The updated height of the iframe.\"},\n                \"width\": {\"type\": \"string\", \"title\": \"width\", \"description\": \"The updated width of the iframe.\"},\n                \"zIndex\": {\"type\": \"string\", \"title\": \"zIndex\", \"description\": \"The updated zIndex to apply to the iframe.\"},\n                \"left\": {\"type\": \"string\", \"title\": \"left\", \"description\": \"The initial left property to apply to the iframe.\"},\n                \"top\": {\"type\": \"string\", \"title\": \"top\", \"description\": \"The initial top property to apply to the iframe.\"},\n                \"bottom\": {\"type\": \"string\", \"title\": \"bottom\", \"description\": \"The initial bottom property to apply to the iframe.\"},\n                \"right\": {\"type\": \"string\", \"title\": \"right\", \"description\": \"The initial right property to apply to the iframe.\"},\n                \"transition\": {\"type\": \"string\", \"title\": \"transition\", \"description\": \"The updated transition property to apply to the iframe.\"},\n                \"maxHeight\": {\"type\": \"string\", \"title\": \"maxHeight\", \"description\": \"The updated maximum height to apply to the iframe.\"},\n                \"maxWidth\": {\"type\": \"string\", \"title\": \"maxWidth\", \"description\": \"The updated maximum with to apply to the iframe.\"}\n              },\n              \"required\": []\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"updatedCSS\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findInstancesRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findInstancesRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindInstances Request\",\n\t\"description\": \"A request for details of instances of a particular app.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindInstancesRequestType\": {\n\t\t\t\"title\": \"FindInstances Request Message Type\",\n\t\t\t\"const\": \"findInstancesRequest\"\n\t\t},\n\t\t\"FindInstancesRequestPayload\": {\n\t\t\t\"type\": \"object\",\n\t\t\t\"title\": \"FindInstances Request Payload\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"app\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findInstancesResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findInstancesResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindInstances Response\",\n\t\"description\": \"A response to a findInstances request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindInstancesResponseType\": {\n\t\t\t\"title\": \"FindInstances Response Message Type\",\n\t\t\t\"const\": \"findInstancesResponse\"\n\t\t},\n\t\t\"FindInstancesSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindInstances Response Message Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"description\": \"The message payload contains a flag indicating whether the API call was successful, plus any return values for the FDC3 API function called, or indicating that the request resulted in an error and including a standardized error message.\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIdentifiers\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppMetadata\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIdentifiers\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindInstancesErrorResponsePayload\": {\n\t\t\t\"title\": \"FindInstances Error Response Message Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"findInstances Errors\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findIntentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findIntentRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntent Request\",\n\t\"description\": \"A request for details of apps available to resolve a particular intent and context pair.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentRequestType\": {\n\t\t\t\"title\": \"FindIntent Request Message Type\",\n\t\t\t\"const\": \"findIntentRequest\"\n\t\t},\n\t\t\"FindIntentRequestPayload\": {\n\t\t\t\"title\": \"FindIntent Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent name\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"title\": \"Context argument\",\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"resultType\": {\n\t\t\t\t\t\"title\": \"Result type argument\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findIntentResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findIntentResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntent Response\",\n\t\"description\": \"A response to a findIntent request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentResponseType\": {\n\t\t\t\"title\": \"FindIntent Response Message Type\",\n\t\t\t\"const\": \"findIntentResponse\"\n\t\t},\n\t\t\"FindIntentSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindIntent Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntent\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntent\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindIntentErrorResponsePayload\": {\n\t\t\t\"title\": \"FindIntent Response Error Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"findIntent Errors\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findIntentsByContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findIntentsByContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntentsByContext Request\",\n\t\"description\": \"A request for details of intents and apps available to resolve them for a particular context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentsByContextRequestType\": {\n\t\t\t\"title\": \"FindIntentsByContext Request Message Type\",\n\t\t\t\"const\": \"findIntentsByContextRequest\"\n\t\t},\n\t\t\"FindIntentsByContextRequestPayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"resultType\": {\n\t\t\t\t  \"title\": \"Result type argument\",\n\t\t\t\t  \"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/findIntentsByContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/findIntentsByContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntentsByContext Response\",\n\t\"description\": \"A response to a findIntentsByContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentsByContextResponseType\": {\n\t\t\t\"title\": \"FindIntentsByContext Response Message Type\",\n\t\t\t\"const\": \"findIntentsByContextResponse\"\n\t\t},\n\t\t\"FindIntentsByContextSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntents\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntents\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindIntentsByContextErrorResponsePayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"FindIntentsByContext Error Message\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getAppMetadataRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getAppMetadataRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetAppMetadata Request\",\n\t\"description\": \"A request for metadata about an app.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetAppMetadataRequestType\": {\n\t\t\t\"title\": \"GetAppMetadata Request Message Type\",\n\t\t\t\"const\": \"getAppMetadataRequest\"\n\t\t},\n\t\t\"GetAppMetadataRequestPayload\": {\n\t\t\t\"title\": \"GetAppMetadata Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"app\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getAppMetadataResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getAppMetadataResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetAppMetadata Response\",\n\t\"description\": \"A response to a getAppMetadata request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetAppMetadataResponseType\": {\n\t\t\t\"title\": \"GetAppMetadata Response Message Type\",\n\t\t\t\"const\": \"getAppMetadataResponse\"\n\t\t},\n\t\t\"GetAppMetadataSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetAppMetadata Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appMetadata\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppMetadata\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appMetadata\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetAppMetadataErrorResponsePayload\": {\n\t\t\t\"title\": \"GetAppMetadata Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"GetAppMetadata Error Message\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getCurrentChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getCurrentChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentChannel Request\",\n\t\"description\": \"A request to return the Channel object for the current User channel membership. Returns `null` if the app is not joined to a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentChannelRequestType\": {\n\t\t\t\"title\": \"GetCurrentChannel Request Message Type\",\n\t\t\t\"const\": \"getCurrentChannelRequest\"\n\t\t},\n\t\t\"GetCurrentChannelRequestPayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getCurrentChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getCurrentChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentChannel Response\",\n\t\"description\": \"A response to a getCurrentChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentChannelResponseType\": {\n\t\t\t\"title\": \"GetCurrentChannel Response Message Type\",\n\t\t\t\"const\": \"getCurrentChannelResponse\"\n\t\t},\n\t\t\"GetCurrentChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channel\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{ \"$ref\": \"api.schema.json#/definitions/Channel\" },\n\t\t\t\t\t\t{ \"type\": \"null\" }\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"channel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetCurrentChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getCurrentContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getCurrentContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentContext Request\",\n\t\"description\": \"A request to return the current context (either of a specified type or most recent broadcast) of a specified Channel. Returns `null` if no context (of the requested type if one was specified) is available in the channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentContextRequestType\": {\n\t\t\t\"title\": \"GetCurrentContext Request Message Type\",\n\t\t\t\"const\": \"getCurrentContextRequest\"\n\t\t},\n\t\t\"GetCurrentContextRequestPayload\": {\n\t\t\t\"title\": \"GetCurrentContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to return the current context of.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of context to return for OR `null` indicating that the most recently broadcast context on the channel should be returned.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"channelId\", \"contextType\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getCurrentContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getCurrentContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentContext Response\",\n\t\"description\": \"A response to a getCurrentContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentContextResponseType\": {\n\t\t\t\"title\": \"GetCurrentContext Response Message Type\",\n\t\t\t\"const\": \"getCurrentContextResponse\"\n\t\t},\n\t\t\"GetCurrentContextSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentContext Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"title\": \"Current Context\",\n\t\t\t\t\t\"description\": \"The most recently broadcast context object (of the specified type, if one was specified), or `null` if none was available in the channel.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{ \"$ref\": \"../context/context.schema.json\" },\n\t\t\t\t\t\t{ \"type\": \"null\" }\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetCurrentContextErrorResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentContext Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getInfoRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getInfoRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetInfo Request\",\n\t\"description\": \"Request to retrieve information about the FDC3 Desktop Agent implementation and the metadata of the calling application according to the Desktop Agent.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetInfoRequestType\": {\n\t\t\t\"title\": \"GetInfo Request Message Type\",\n\t\t\t\"const\": \"getInfoRequest\"\n\t\t},\n\t\t\"GetInfoRequestPayload\": {\n\t\t\t\"title\": \"GetInfo Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getInfoResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getInfoResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetInfo Response\",\n\t\"description\": \"A response to a getInfo request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetInfoResponseType\": {\n\t\t\t\"title\": \"GetInfo Response Message Type\",\n\t\t\t\"const\": \"getInfoResponse\"\n\t\t},\n\t\t\"GetInfoSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetInfo Success Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"implementationMetadata\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ImplementationMetadata\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"implementationMetadata\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetInfoErrorResponsePayload\": {\n\t\t\t\"title\": \"GetInfo Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getOrCreateChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getOrCreateChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetOrCreateChannel Request\",\n\t\"description\": \"Request to return a Channel with an auto-generated identity that is intended for private communication between applications.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetOrCreateChannelRequestType\": {\n\t\t\t\"title\": \"GetOrCreateChannel Request Message Type\",\n\t\t\t\"const\": \"getOrCreateChannelRequest\"\n\t\t},\n\t\t\"GetOrCreateChannelRequestPayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to return\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\"channelId\"]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getOrCreateChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getOrCreateChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetOrCreateChannel Response\",\n\t\"description\": \"A response to a getOrCreateChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetOrCreateChannelResponseType\": {\n\t\t\t\"title\": \"GetOrCreateChannel Response Message Type\",\n\t\t\t\"const\": \"getOrCreateChannelResponse\"\n\t\t},\n\t\t\"GetOrCreateChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channel\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"channel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetOrCreateChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getUserChannelsRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getUserChannelsRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetUserChannels Request\",\n\t\"description\": \"Request to retrieve a list of the User Channels available for the app to join.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetUserChannelsRequestType\": {\n\t\t\t\"title\": \"GetUserChannels Request Message Type\",\n\t\t\t\"const\": \"getUserChannelsRequest\"\n\t\t},\n\t\t\"GetUserChannelsRequestPayload\": {\n\t\t\t\"title\": \"GetUserChannels Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/getUserChannelsResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/getUserChannelsResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetUserChannels Response\",\n\t\"description\": \"A response to a getUserChannels request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetUserChannelsResponseType\": {\n\t\t\t\"title\": \"GetUserChannels Response Message Type\",\n\t\t\t\"const\": \"getUserChannelsResponse\"\n\t\t},\n\t\t\"GetUserChannelsSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetUserChannels Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"userChannels\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"userChannels\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetUserChannelsErrorResponsePayload\": {\n\t\t\t\"title\": \"GetUserChannels Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/heartbeatAcknowledgmentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/heartbeatAcknowledgementRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"HeartbeatAcknowledgement Request\",\n\t\"description\": \"A request that serves as an acknowledgement of a heartbeat event from the Desktop Agent and indicates that an application window or frame is still alive.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatAcknowledgementRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatAcknowledgementRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"HeartbeatAcknowledgementRequestType\": {\n\t\t\t\"title\": \"HeartbeatAcknowledgement Request Message Type\",\n\t\t\t\"const\": \"heartbeatAcknowledgementRequest\"\n\t\t},\n\t\t\"HeartbeatAcknowledgementRequestPayload\": {\n\t\t\t\"title\": \"heartbeatAcknowledgement Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"heartbeatEventUuid\": {\n\t\t\t\t\t\"title\": \"Heartbeat Event Uuid\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The eventUuid value of the HeartbeatEvent that the acknowledgement being sent relates to.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"heartbeatEventUuid\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/heartbeatEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/heartbeatEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Heartbeat Event\",\n\t\"description\": \"A heartbeat message from the Desktop Agent to an app indicating that the Desktop Agent is alive and that the application should send a heartbeatResponseRequest to the agent in response.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"HeartbeatEventType\": {\n\t\t\t\"title\": \"Heartbeat Event Message Type\",\n\t\t\t\"const\": \"heartbeatEvent\"\n\t\t},\n\t\t\"HeartbeatEventPayload\": {\n\t\t\t\"title\": \"heartbeat Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": []\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/intentEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/intentEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"intent Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that it has been selected to resolve a raised intent and context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentEventType\": {\n\t\t\t\"title\": \"Intent Event Message Type\",\n\t\t\t\"const\": \"intentEvent\"\n\t\t},\n\t\t\"IntentEventPayload\": {\n\t\t\t\"title\": \"Intent Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent\",\n\t\t\t\t\t\"description\": \"The intent that was raised.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object passed with the raised intent.\"\n\t\t\t\t},\n\t\t\t\t\"originatingApp\": {\n\t\t\t\t\t\"title\": \"Originating AppIdentifier\",\n\t\t\t\t\t\"description\": \"Details of the application instance that raised the intent.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t},\n\t\t\t\t\"raiseIntentRequestUuid\": {\n\t\t\t\t\t\"title\": \"raiseIntentRequest UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The requestUuid value of the raiseIntentRequest that the intentEvent being sent relates to.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\", \"context\", \"raiseIntentRequestUuid\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/intentListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/intentListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"intentListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"IntentListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/intentListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/intentListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentListenerUnsubscribe Response\",\n\t\"description\": \"A response to a intentListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"intentListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/intentResultRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/intentResultRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentResult Request\",\n\t\"description\": \"A request to deliver a result for an intent (which may include a `void` result that just indicates that the handler has run, returning no result). The result is tied to the intentEvent it relates to by quoting the `eventUuid` of the intentEvent in its payload.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentResultRequestType\": {\n\t\t\t\"title\": \"IntentResult Request Message Type\",\n\t\t\t\"const\": \"intentResultRequest\"\n\t\t},\n\t\t\"IntentResultRequestPayload\": {\n\t\t\t\"title\": \"IntentResult Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentEventUuid\": {\n\t\t\t\t\t\"title\": \"IntentEvent UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The eventUuid value of the intentEvent that the result being sent relates to.\"\n\t\t\t\t},\n\t\t\t\t\"raiseIntentRequestUuid\": {\n\t\t\t\t\t\"title\": \"raiseIntentRequest UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The requestUuid value of the raiseIntentRequest that the result being sent relates to.\"\n\t\t\t\t},\n\t\t\t\t\"intentResult\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResult\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentEventUuid\", \"raiseIntentRequestUuid\", \"intentResult\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/intentResultResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/intentResultResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentResult Response\",\n\t\"description\": \"A response to a request to deliver an intent result.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentResultResponseType\": {\n\t\t\t\"title\": \"IntentResult Response Message Type\",\n\t\t\t\"const\": \"intentResultResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/joinUserChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/joinUserChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"JoinUserChannel Request\",\n\t\"description\": \"Request to join the app to the specified User channel. On successfully joining a channel, client code should make subsequent requests to get the current context of that channel for all registered context listeners and then call their handlers with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"JoinUserChannelRequestType\": {\n\t\t\t\"title\": \"JoinUserChannel Request Message Type\",\n\t\t\t\"const\": \"joinUserChannelRequest\"\n\t\t},\n\t\t\"JoinUserChannelRequestPayload\": {\n\t\t\t\"title\": \"JoinUserChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to join.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\"channelId\"]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/joinUserChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/joinUserChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"JoinUserChannel Response\",\n\t\"description\": \"A response to a joinUserChannel request. On receipt of this response, client code should make subsequent requests to get the current context of that channel for all registered context listeners and then call their handlers with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"JoinUserChannelResponseType\": {\n\t\t\t\"title\": \"JoinUserChannel Response Message Type\",\n\t\t\t\"const\": \"joinUserChannelResponse\"\n\t\t},\n\t\t\"JoinUserChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"JoinUserChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"JoinUserChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"JoinUserChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/leaveCurrentChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/leaveCurrentChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"LeaveCurrentChannel Request\",\n\t\"description\": \"Request to remove the app from any User channel membership.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"LeaveCurrentChannelRequestType\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Request Message Type\",\n\t\t\t\"const\": \"leaveCurrentChannelRequest\"\n\t\t},\n\t\t\"LeaveCurrentChannelRequestPayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/leaveCurrentChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/leaveCurrentChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"LeaveCurrentChannel Response\",\n\t\"description\": \"A response to a leaveCurrentChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"LeaveCurrentChannelResponseType\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Response Message Type\",\n\t\t\t\"const\": \"leaveCurrentChannelResponse\"\n\t\t},\n\t\t\"LeaveCurrentChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"LeaveCurrentChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/openRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/openRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Open Request\",\n\t\"description\": \"A request to open an application.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"OpenRequestType\": {\n\t\t\t\"title\": \"Open Request Message Type\",\n\t\t\t\"const\": \"openRequest\"\n\t\t},\n\t\t\"OpenRequestPayload\": {\n\t\t\t\"title\": \"Open Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"If a Context object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"app\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/openResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/openResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Open Response\",\n\t\"description\": \"A response to a open request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/OpenSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/OpenErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"OpenResponseType\": {\n\t\t\t\"title\": \"Open Response Message Type\",\n\t\t\t\"const\": \"openResponse\"\n\t\t},\n\t\t\"OpenSuccessResponsePayload\": {\n\t\t\t\"title\": \"Open Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIdentifier\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIdentifier\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"OpenErrorResponsePayload\": {\n\t\t\t\"title\": \"Open Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"Open Error Response Payload\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/OpenError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelAddEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelAddEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelAddEventListener Request\",\n\t\"description\": \"A request to add an event listener to a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelAddEventListenerRequestType\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Request Message Type\",\n\t\t\t\"const\": \"privateChannelAddEventListenerRequest\"\n\t\t},\n\t\t\"PrivateChannelAddEventListenerRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener should be added to.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"listenerType\": {\n\t\t\t\t\t\"title\": \"Event listener type\",\n\t\t\t\t\t\"description\": \"The type of PrivateChannel event that the listener should be applied to, or null for all event types.\",\n\t\t\t\t\t\"oneOf\" : [\n\t\t\t\t\t\t{ \"$ref\": \"api.schema.json#/definitions/PrivateChannelEventType\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"listenerType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelAddEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelAddEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelAddEventListener Response\",\n\t\"description\": \"A response to a privateChannelAddEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelAddEventListenerResponseType\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Response Message Type\",\n\t\t\t\"const\": \"privateChannelAddEventListenerResponse\"\n\t\t},\n\t\t\"PrivateChannelAddEventListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"PrivateChannelAddEventListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelDisconnectRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelDisconnectRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelDisconnect Request\",\n\t\"description\": \"Request that indicates that a participant will no longer interact with a specified `PrivateChannel`.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelDisconnectRequestType\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Request Message Type\",\n\t\t\t\"const\": \"privateChannelDisconnectRequest\"\n\t\t},\n\t\t\"PrivateChannelDisconnectRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the Channel that should be disconnected from\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"channelId\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelDisconnectResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelDisconnectResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelDisconnect Response\",\n\t\"description\": \"A response to a privateChannelDisconnect request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelDisconnectResponseType\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Response Message Type\",\n\t\t\t\"const\": \"privateChannelDisconnectResponse\"\n\t\t},\n\t\t\"PrivateChannelDisconnectSuccessResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"PrivateChannelDisconnectErrorResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelOnAddContextListenerEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelOnAddContextListenerEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"privateChannelOnAddContextListener Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has added a context listener to a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnAddContextListenerEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnAddContextListener Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnAddContextListenerEvent\"\n\t\t},\n\t\t\"PrivateChannelOnAddContextListenerEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnAddContextListener Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener was added to.\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of the context listener added to the channel by another app, or null if it will listen to all types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelOnDisconnectEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelOnDisconnectEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"privateChannelOnDisconnect Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has disconnected from a specific PrivateChannel and will no longer interact with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnDisconnectEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnDisconnectEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnDisconnectEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnDisconnect Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnDisconnectEvent\"\n\t\t},\n\t\t\"PrivateChannelOnDisconnectEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnDisconnect Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the app has disconnected from.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelOnUnsubscribeEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelOnUnsubscribeEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelOnUnsubscribe Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has unsubscribed a context listener from a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnUnsubscribeEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnUnsubscribe Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnUnsubscribeEvent\"\n\t\t},\n\t\t\"PrivateChannelOnUnsubscribeEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnUnsubscribe Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener was unsubscribed from.\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of the context listener unsubscribed from the channel by another app, or null if it was listening to all types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelUnsubscribeEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelUnsubscribeEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelUnsubscribeEventListener Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelUnsubscribeEventListenerRequestType\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Request Message Type\",\n\t\t\t\"const\": \"privateChannelUnsubscribeEventListenerRequest\"\n\t\t},\n\t\t\"PrivateChannelUnsubscribeEventListenerRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/privateChannelUnsubscribeEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/privateChannelUnsubscribeEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelUnsubscribeEventListener Response\",\n\t\"description\": \"A response to a privateChannelUnsubscribeEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelUnsubscribeEventListenerResponseType\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Response Message Type\",\n\t\t\t\"const\": \"privateChannelUnsubscribeEventListenerResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/raiseIntentForContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/raiseIntentForContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentForContext Request\",\n\t\"description\": \"A request to raise an unspecified intent for a specified context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentForContextRequestType\": {\n\t\t\t\"title\": \"RaiseIntentForContext Request Message Type\",\n\t\t\t\"const\": \"raiseIntentForContextRequest\"\n\t\t},\n\t\t\"RaiseIntentForContextRequestPayload\": {\n\t\t\t\"title\": \"RaiseIntentForContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/raiseIntentForContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/raiseIntentForContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentForContext Response\",\n\t\"description\": \"A response to a raiseIntentForContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"title\": \"RaiseIntentForContext Response Payload\",\n\t\t\t\t\t\"description\": \"There are 3 possible responses to a raiseIntentForContext request, each of which sets a single property in the payload: Success (`intentResolution`), Needs further resolution (`appIntents`) or Error (`error`).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"raiseIntentResponse.schema.json#/$defs/RaiseIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextNeedsResolutionResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"raiseIntentResponse.schema.json#/$defs/RaiseIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentForContextResponseType\": {\n\t\t\t\"title\": \"RaiseIntentForContext Response Message Type\",\n\t\t\t\"const\": \"raiseIntentForContextResponse\"\n\t\t},\n\t\t\"RaiseIntentForContextNeedsResolutionResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntentForContext NeedsResolution Response Payload\",\n\t\t\t\"description\": \"Response to a raiseIntentForContext request that needs additional resolution (i.e. show an intent resolver UI).\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntents\": {\n\t\t\t\t\t\"title\": \"AppIntents\",\n\t\t\t\t\t\"description\": \"Used if a raiseIntentForContext request requires additional resolution (e.g. by showing an intent resolver) before it can be handled.\",\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntents\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/raiseIntentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/raiseIntentRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntent Request\",\n\t\"description\": \"A request to raise an intent for a context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentRequestType\": {\n\t\t\t\"title\": \"RaiseIntent Request Message Type\",\n\t\t\t\"const\": \"raiseIntentRequest\"\n\t\t},\n\t\t\"RaiseIntentRequestPayload\": {\n\t\t\t\"title\": \"RaiseIntent Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intent\", \"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/raiseIntentResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/raiseIntentResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntent Response\",\n\t\"description\": \"A response to a raiseIntent request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"title\": \"RaiseIntent Response Payload\",\n\t\t\t\t\t\"description\": \"There are 3 possible responses to a raiseIntent request, each of which sets a single property in the payload: Success (`intentResolution`), Needs further resolution (`appIntent`) or Error (`error`).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentNeedsResolutionResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentResponseType\": {\n\t\t\t\"title\": \"RaiseIntent Response Message Type\",\n\t\t\t\"const\": \"raiseIntentResponse\"\n\t\t},\n\t\t\"RaiseIntentSuccessResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Success Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentResolution\": {\n\t\t\t\t\t\"title\": \"Intent Resolution\",\n\t\t\t\t\t\"description\": \"Used if the raiseIntent request was successfully resolved.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResolution\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentResolution\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentNeedsResolutionResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent NeedsResolution Response Payload\",\n\t\t\t\"description\": \"Response to a raiseIntent request that needs additional resolution (i.e. show an intent resolver UI).\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntent\": {\n\t\t\t\t\t\"title\": \"AppIntent\",\n\t\t\t\t\t\"description\": \"Used if a raiseIntent request requires additional resolution (e.g. by showing an intent resolver) before it can be handled.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntent\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentErrorResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Error Response Payload\",\n\t\t\t\"description\": \"Used if a raiseIntent request resulted in an error.\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"RaiseIntent Error\",\n\t\t\t\t\t\"description\": \"Should be set if the raiseIntent request returned an error.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/raiseIntentResultResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/next/api/raiseIntentResultResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentResult Response\",\n\t\"description\": \"A secondary response to a request to raise an intent used to deliver the intent result. This message should quote the original requestUuid of the raiseIntentRequest message in its `meta.requestUuid` field.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentResultResponseType\": {\n\t\t\t\"title\": \"RaiseIntentResult Response Message Type\",\n\t\t\t\"const\": \"raiseIntentResultResponse\"\n\t\t},\n\t\t\"RaiseIntentResultSuccessResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Result Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentResult\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResult\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentResult\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentResultErrorResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntentResult Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/api/t2sQuicktypeUtil.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/** Utility for preparing arguments to quicktype, which workaround a specific\n * quicktype bug in command line argument handling (where a directory is used\n * as input the source language argument is ignored which causes our schemas\n * to be interpreted as JSON input, rather than JSONSchema).\n * Bug issue:\n *  */\n\nconst path = require('path');\nconst fs = require('fs');\nconst exec = require('child_process').exec;\n\nconst args = process.argv.slice(2);\nconst outputPath = args.pop();\nconst inputs = args;\n\nconsole.log('Inputs: ' + inputs.join(' | '));\nconsole.log('Output path argument: ' + outputPath);\n\nlet source = '';\n\nlet dirIndex = 0;\n\nconst excludedTypes = [\n  'DesktopAgent.ts',\n  'Listener.ts',\n  'Methods.ts',\n  'PrivateChannel.ts',\n  'Types.ts',\n  'RecommendedChannels.ts',\n];\n\nlet sources = '';\n\nwhile (dirIndex < inputs.length) {\n  if (inputs[dirIndex].endsWith('.ts')) {\n    sources += `--src ${path.join(inputs[dirIndex])} `;\n  } else {\n    fs.readdirSync(inputs[dirIndex], { withFileTypes: true }).forEach(file => {\n      if (file.isDirectory()) {\n        inputs.push(path.join(inputs[dirIndex], file.name));\n      } else {\n        if (!excludedTypes.includes(file.name)) {\n          sources += `--src ${path.join(inputs[dirIndex], file.name)} `;\n        }\n      }\n    });\n  }\n  dirIndex++;\n}\n\n// Normalise path to local quicktype executable.\nconst quicktypeExec = ['.', 'node_modules', '.bin', 'quicktype'].join(path.sep);\n\nconst command = `${quicktypeExec} -l schema -o ${outputPath} ${sources}`;\nconsole.log('command to run: ' + command);\n\nexec(command, function (error, stdout, stderr) {\n  if (stdout) {\n    console.log(stdout);\n  }\n  if (stderr) {\n    console.log(stderr);\n  }\n});\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/agentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/agentErrorResponse.schema.json\",\n  \"title\": \"Agent Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge containing an error, to be used in preference to the standard response when an error needs to be returned.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Error Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"Error message payload containing an standardized error string.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n        }\n      },\n      \"unevaluatedProperties\": false,\n      \"required\": [\"error\"]\n    },\n    \"meta\": {\n      \"$ref\": \"agentResponse.schema.json#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/agentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/agentRequest.schema.json\",\n  \"title\": \"Agent Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Request Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"broadcastRequest\",\n        \"findInstancesRequest\",\n        \"findIntentRequest\",\n        \"findIntentsByContextRequest\",\n        \"getAppMetadataRequest\",\n        \"openRequest\",\n        \"PrivateChannel.broadcast\",\n        \"PrivateChannel.eventListenerAdded\",\n        \"PrivateChannel.eventListenerRemoved\",\n        \"PrivateChannel.onAddContextListener\",\n        \"PrivateChannel.onDisconnect\",\n        \"PrivateChannel.onUnsubscribe\",\n        \"raiseIntentRequest\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"AgentRequestMeta\": {\n      \"title\": \"Agent Request Metadata\",\n      \"description\": \"Metadata for a request message sent by Desktop Agents to the Bridge.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself.\",\n          \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/agentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/agentResponse.schema.json\",\n  \"title\": \"Agent Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"$defs\": {\n    \"AgentResponseMeta\": {\n      \"title\": \"Agent Response Metadata\",\n      \"description\": \"Metadata for a response messages sent by a Desktop Agent to the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/bridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/bridgeErrorResponse.schema.json\",\n  \"title\": \"Bridge Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request, used where all connected agents returned errors.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Error Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The error message payload contains details of an error return to the app or agent that raised the original request.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n        }\n      }\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeErrorResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeErrorResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\", \"errorSources\", \"errorDetails\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/bridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/bridgeRequest.schema.json\",\n  \"title\": \"Bridge Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message forwarded from the Bridge onto a Desktop Agent connected to it.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Message type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeRequestMeta\": {\n      \"title\": \"Bridge Request Metadata\",\n      \"description\": \"Metadata required in a request message forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Bridge Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST be set by the bridge.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\", \"source\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/bridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/bridgeResponse.schema.json\",\n  \"title\": \"Bridge Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"sources\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseSources\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/broadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/broadcastAgentRequest.schema.json\",\n  \"title\": \"Broadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"BroadcastRequestBase\": {\n      \"title\": \"Broadcast Request\",\n      \"type\":\"object\",\n      \"description\": \"A request to broadcast context on a channel.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/broadcastRequest.schema.json#/$defs/BroadcastRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/broadcastRequest.schema.json#/$defs/BroadcastRequestPayload\"\n        },\n        \"meta\": {\n          \"type\": \"object\",\n          \"title\": \"broadcast request metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/broadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/broadcastBridgeRequest.schema.json\",\n  \"title\": \"Broadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"broadcastAgentRequest.schema.json#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/common.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/common.schema.json\",\n  \"title\": \"Bridge Common definitions\",\n  \"type\": \"object\",\n  \"description\": \"Common definitions that are referenced only in the Bridging wire protocol schemas\",\n  \"$defs\": {\n    \"RequestSource\": {\n      \"title\": \"Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from, or the source Desktop Agent if it issued the request or response itself.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ]\n    },\n    \"AppRequestSource\": {\n      \"title\": \"App Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n    },\n    \"AgentDestination\": {\n      \"title\": \"Agent Destination identifier\",\n      \"description\": \"Field that represents a destination Desktop Agent that a request is to be sent to.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n    },\n    \"AppDestination\": {\n      \"title\": \"App Destination identifier\",\n      \"description\": \"Field that represents a destination App on a remote Desktop Agent that a request is to be sent to.\",\n      \"allOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        }\n      ]\n    },\n    \"BridgeParticipantIdentifier\": {\n      \"title\": \"Bridge Participant Identifier\",\n      \"description\": \"Represents identifiers that MUST include the Desktop Agent name and MAY identify a specific app or instance.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"allOf\": [\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n            },\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n            }\n          ]\n        }\n      ]\n    },\n    \"BridgeResponseSources\": {\n      \"title\": \"Desktop Agents that responded\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for the sources that generated responses to the request. Will contain a single value for individual responses and multiple values for responses that were collated by the bridge. May be omitted if all sources errored. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"BridgeResponseErrorSources\": {\n      \"title\": \"Desktop Agents that errored\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for responses that were not returned to the bridge before the timeout or because an error occurred. May be omitted if all sources responded without errors. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"BridgeResponseErrorDetails\": {\n      \"title\": \"Response Error Details\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n      },\n      \"description\": \"Array of error message strings for responses that were not returned to the bridge before the timeout or because an error occurred. Should be the same length as the `errorSources` array and ordered the same. May be omitted if all sources responded without errors.\"\n    },\n    \"DesktopAgentImplementationMetadata\": {\n      \"description\": \"Includes the name assigned to the Desktop Agent by the Bridge.\",\n      \"title\": \"DesktopAgentImplementationMetadata\",\n      \"type\": \"object\",\n      \"allOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/BaseImplementationMetadata\"\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"desktopAgent\": {\n              \"description\": \"Used in Desktop Agent Bridging to attribute or target a message to a particular Desktop Agent.\",\n              \"type\": \"string\",\n              \"title\": \"desktopAgent\"\n            }\n          }\n        }\n      ],\n      \"properties\": {\n        \"fdc3Version\": true,\n        \"provider\": true,\n        \"providerVersion\": true,\n        \"optionalFeatures\": true,\n        \"desktopAgent\": true\n      },\n      \"required\": [\n        \"fdc3Version\",\n        \"optionalFeatures\",\n        \"provider\",\n        \"desktopAgent\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/connectionStep.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/connectionStep.schema.json\",\n  \"title\": \"Connection Step Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used during the connection flow for a Desktop Agent to the Bridge. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Connection Step Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"hello\",\n        \"handshake\",\n        \"authenticationFailed\",\n        \"connectedAgentsUpdate\"\n      ],\n      \"description\": \"Identifies the type of the connection step message.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload, containing data pertaining to this connection step.\",\n      \"unevaluatedProperties\": false\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/ConnectionStepMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"ConnectionStepMeta\": {\n      \"title\": \"Connection Step Metadata\",\n      \"description\": \"Metadata for this connection step message.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        }\n      },\n      \"required\": [\"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/connectionStep2Hello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/connectionStep2Hello.schema.json\",\n  \"title\": \"ConnectionStep2Hello\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep2HelloBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep2HelloBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep2Hello\",\n      \"description\": \"Hello message sent by the Bridge to anyone connecting to the Bridge (enables identification as a bridge and confirmation of whether authentication is required)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 2 Message Type\",\n          \"const\": \"hello\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 2 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"desktopAgentBridgeVersion\": {\n              \"title\": \"Desktop Agent Bridge Version Number\",\n              \"description\": \"The version of the Bridge\",\n              \"type\": \"string\"\n            },\n            \"supportedFDC3Versions\": {\n              \"title\": \"Supported FDC3 Versions\",\n              \"type\": \"array\",\n              \"description\": \"The FDC3 versions supported by the Bridge\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"authRequired\": {\n              \"title\": \"Authentication Required\",\n              \"type\": \"boolean\",\n              \"description\": \"A flag indicating whether the Desktop Agent Bridge requires authentication or not.\"\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\",\n              \"description\": \"An optional Desktop Agent Bridge JWT authentication token if the Desktop Agent want to authenticate a bridge.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"desktopAgentBridgeVersion\", \"supportedFDC3Versions\", \"authRequired\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 2 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/connectionStep3Handshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/connectionStep3Handshake.schema.json\",\n  \"title\": \"ConnectionStep3Handshake\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep3HandshakeBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep3HandshakeBase\": {\n      \"type\": \"object\",\n      \"title\": \"ConnectionStep3Handshake\",\n      \"description\": \"Handshake message sent by the Desktop Agent to the Bridge (including requested name, channel state and authentication data)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 3 Message Type\",\n          \"const\": \"handshake\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 3 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"implementationMetadata\": {\n              \"title\": \"Connecting Agent ImplementationMetadata\",\n              \"description\": \"Desktop Agent ImplementationMetadata trying to connect to the bridge.\",\n              \"type\": \"object\",\n              \"allOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/BaseImplementationMetadata\"\n                }\n              ],\n              \"properties\": {\n                \"fdc3Version\": true,\n                \"provider\": true,\n                \"providerVersion\": true,\n                \"optionalFeatures\": true\n              },\n              \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\"\n              ],\n              \"additionalProperties\": false\n            },\n            \"requestedName\": {\n              \"title\": \"Requested name\",\n              \"description\": \"The requested Desktop Agent name\",\n              \"type\": \"string\"\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The current state of the Desktop Agent's App and User channels (exclude any Private channels), as a mapping of channel id to an array of Context objects, one per type found in the channel, most recent first.\",\n              \"additionalProperties\": {\n                \"title\": \"Channel \",\n                \"type\": \"array\",\n                \"items\": {\n                  \"$ref\": \"../context/context.schema.json\"\n                }\n              }\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"implementationMetadata\",\n            \"requestedName\",\n            \"channelsState\"\n          ]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 3 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"requestUuid\",\n            \"timestamp\"\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/connectionStep4AuthenticationFailed.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/connectionStep4AuthenticationFailed.schema.json\",\n  \"title\": \"ConnectionStep4AuthenticationFailed\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep4AuthenticationFailedBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep4AuthenticationFailedBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep4AuthenticationFailed\",\n      \"description\": \"Message sent by Bridge to Desktop Agent if their authentication fails.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 4 Message Type\",\n          \"const\": \"authenticationFailed\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 4 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"message\": {\n              \"title\": \"Authentication failed message\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 4 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/connectionStep6ConnectedAgentsUpdate.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/connectionStep6ConnectedAgentsUpdate.schema.json\",\n  \"title\": \"ConnectionStep6ConnectedAgentsUpdate\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep6ConnectedAgentsUpdateBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep6ConnectedAgentsUpdateBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep6ConnectedAgentsUpdateBase\",\n      \"description\": \"Message sent by Bridge to all Desktop Agent when an agent joins or leaves the bridge, includes the details of all agents, the change made and the expected channel state for all agents.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 6 Message Type\",\n          \"const\": \"connectedAgentsUpdate\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 6 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"addAgent\": {\n              \"title\": \"Agents To Add\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent first connects to the bridge and provide its assigned name.\"\n            },\n            \"removeAgent\": {\n              \"title\": \"Agents To Remove\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent disconnects from the bridge and provide the name that no longer is assigned.\"\n            },\n            \"allAgents\": {\n              \"title\": \"All Connected Agents\",\n              \"type\": \"array\",\n              \"description\": \"Desktop Agent Bridge implementation metadata of all connected agents.\",\n              \"items\": {\n                \"$ref\": \"common.schema.json#/$defs/DesktopAgentImplementationMetadata\"\n              }\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The updated state of channels that should be adopted by the agents. Should only be set when an agent is connecting to the bridge.\",\n              \"additionalProperties\": {\n                \"type\": \"array\",\n                  \"items\": {\n                    \"$ref\": \"../context/context.schema.json\"\n                  }\n              }\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"allAgents\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 6 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentErrorResponse.schema.json\",\n  \"title\": \"FindInstances Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesErrorResponseBase\": {\n      \"title\": \"FindInstances Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindInstances Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentRequest.schema.json\",\n  \"title\": \"FindInstances Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesRequestBase\": {\n      \"title\": \"FindInstances Request\",\n      \"type\": \"object\",\n      \"description\": \"A request for details of instances of a particular app\",\n      \"properties\":{\n        \"type\": {\n          \"$ref\": \"../api/findInstancesRequest.schema.json#/$defs/FindInstancesRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesRequest.schema.json#/$defs/FindInstancesRequestPayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindInstances request metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"oneOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentResponse.schema.json\",\n  \"title\": \"FindInstances Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesResponseBase\": {\n      \"title\": \"FindInstances Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesSuccessResponsePayload\"\n        },\n        \"meta\": true\n      },\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeErrorResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentErrorResponse.schema.json#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeRequest.schema.json\",\n  \"title\": \"FindInstances Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentRequest.schema.json#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findInstancesBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentResponse.schema.json#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentErrorResponseBase\": {\n      \"title\": \"FindIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentAgentRequest.schema.json\",\n  \"title\": \"FindIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentRequestBase\": {\n      \"title\": \"FindIntent Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of apps available to resolve a particular intent and context pair.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentRequest.schema.json#/$defs/FindIntentRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentRequest.schema.json#/$defs/FindIntentRequestPayload\"\n        },\n        \"meta\": {\n          \"title\" : \"FindIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": true\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentAgentResponse.schema.json\",\n  \"title\": \"FindIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentResponseBase\": {\n      \"title\": \"FindIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentErrorResponse.schema.json#/$defs/FindIntentErrorResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeRequest.schema.json\",\n  \"title\": \"FindIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentRequest.schema.json#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentResponse.schema.json#/$defs/FindIntentResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextErrorResponseBase\": {\n      \"title\": \"FindIntentsByContext Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextRequestBase\": {\n      \"title\": \"FindIntentsByContext Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of intents and apps available to resolve them for a particular context.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextRequest.schema.json#/$defs/FindIntentsByContextRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextRequest.schema.json#/$defs/FindIntentsByContextRequestPayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextResponseBase\": {\n      \"title\": \"FindIntentsByContext Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentErrorResponse.schema.json#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentRequest.schema.json#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/findIntentsByContextBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentResponse.schema.json#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataErrorResponseBase\": {\n      \"title\": \"GetAppMetadata Error Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentRequest.schema.json\",\n  \"title\": \"GetAppMetadata Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataRequestBase\": {\n      \"title\": \"GetAppMetadata Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for metadata about an app\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataRequest.schema.json#/$defs/GetAppMetadataRequestType\"\n        },\n        \"payload\": {\n          \"type\": \"object\",\n          \"allOf\": [{\n            \"properties\": {\n              \"app\": {\n                \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n              }\n            },\n            \"required\": [\n              \"app\"\n            ]\n          },{\n            \"$ref\": \"../api/getAppMetadataRequest.schema.json#/$defs/GetAppMetadataRequestPayload\"\n          }]\n        },\n        \"meta\": {\n          \"title\" : \"GetAppMetadata Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataResponseBase\": {\n      \"title\": \"GetAppMetadata Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentErrorResponse.schema.json#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeRequest.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentRequest.schema.json#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/getAppMetadataBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentResponse.schema.json#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openAgentErrorResponse.schema.json\",\n  \"title\": \"Open Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenErrorResponseBase\": {\n      \"title\": \"Open Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request that contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openAgentRequest.schema.json\",\n  \"title\": \"Open Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenRequestBase\": {\n      \"title\": \"Open Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to open an application\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openRequest.schema.json#/$defs/OpenRequestType\"\n        },\n        \"payload\": {\n          \"title\": \"Open Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"app\": {\n              \"type\": \"object\",\n              \"title\": \"App to open\",\n              \"description\": \"The application to open on the specified Desktop Agent\",\n              \"allOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            }\n          },\n          \"required\": [\"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\":  {\n          \"title\": \"Open Request Metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openAgentResponse.schema.json\",\n  \"title\": \"Open Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenResponseBase\": {\n      \"title\": \"Open Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openBridgeErrorResponse.schema.json\",\n  \"title\": \"Open Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentErrorResponse.schema.json#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openBridgeRequest.schema.json\",\n  \"title\": \"Open Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentRequest.schema.json#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/openBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/openBridgeResponse.schema.json\",\n  \"title\": \"Open Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentResponse.schema.json#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelBroadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelBroadcastAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelBroadcastRequestBase\": {\n      \"title\": \"PrivateChannelBroadcast Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to broadcast on a PrivateChannel.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel Broadcast Message type\",\n          \"const\": \"PrivateChannel.broadcast\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelBroadcast Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The Id of the PrivateChannel that the broadcast was sent on\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\",\n              \"description\": \"The context object that was the payload of a broadcast message.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"context\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelBroadcast Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelBroadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelBroadcastBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelBroadcastAgentRequest.schema.json#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelEventListenerAddedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerAddedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerAddedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerAdded Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerAdded event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerAdded Message type\",\n          \"const\": \"PrivateChannel.eventListenerAdded\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the event listener was added to.\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/PrivateChannelEventType\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerAddedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerRemovedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerRemoved Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerRemoved event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerRemoved Message type\",\n          \"const\": \"PrivateChannel.eventListenerRemoved\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the event listener was removed from.\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/PrivateChannelEventType\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerRemovedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnAddContextListenerRequestBase\": {\n      \"title\": \"PrivateChannelOnAddContextListener Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an AddContextListener event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnAddContextListener Message type\",\n          \"const\": \"PrivateChannel.onAddContextListener\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the context listener was added to.\"\n            },\n            \"contextType\": {\n              \"oneOf\": [\n                { \"type\": \"string\" },\n                { \"type\": \"null\" }\n              ],\n              \"title\": \"Context Type\",\n              \"description\": \"The type of the context listener added. Should be null for an untyped listener.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnAddContextListenerAgentRequest.schema.json#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnDisconnectAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnDisconnectAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnDisconnectRequestBase\": {\n      \"title\": \"PrivateChannelOnDisconnect Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on a Disconnect event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnDisconnect Message type\",\n          \"const\": \"PrivateChannel.onDisconnect\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the agent discconnected from.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnDisconnectBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnDisconnectBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnDisconnectAgentRequest.schema.json#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnUnsubscribeRequestBase\": {\n      \"title\": \"PrivateChannelOnUnsubscribe Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an Unsubscribe event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnUnsubscribe Message type\",\n          \"const\": \"PrivateChannel.onUnsubscribe\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the context listener was unsubscribed from.\"\n            },\n            \"contextType\": {\n              \"oneOf\": [\n                { \"type\": \"string\" },\n                { \"type\": \"null\" }\n              ],\n              \"title\": \"Context Type\",\n              \"description\": \"The type of the context listener that was unsubscribed. Should be null for an untyped listener.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnUnsubscribeAgentRequest.schema.json#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentErrorResponseBase\": {\n      \"title\": \"RaiseIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentRequest.schema.json\",\n  \"title\": \"RaiseIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentRequestBase\": {\n      \"title\": \"RaiseIntent Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentRequest.schema.json#/$defs/RaiseIntentRequestType\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intent\": {\n              \"type\": \"string\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            },\n            \"app\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"required\": [\"intent\", \"context\", \"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false,\n          \"required\": [\"requestUuid\",\"timestamp\",\"destination\",\"source\"] \n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResponseBase\": {\n      \"title\": \"RaiseIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentErrorResponse.schema.json#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeRequest.schema.json\",\n  \"title\": \"RaiseIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentRequest.schema.json#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentResponse.schema.json#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentResultAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultErrorResponseBase\": {\n      \"title\": \"RaiseIntent Result Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result, which contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Result Response Message type\",\n          \"const\": \"raiseIntentResultResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Result Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"RaiseIntent Result Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResultError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentResultAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultResponseBase\": {\n      \"title\": \"RaiseIntent Result Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResultResponse.schema.json#/$defs/RaiseIntentResultResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResultResponse.schema.json#/$defs/RaiseIntentResultSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentResultBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentErrorResponse.schema.json#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridging/raiseIntentResultBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentResponse.schema.json#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridgingAsyncAPI/README.md",
    "content": "# Agent Bridging AsyncAPI schema\n\nThis folder contains an AsyncAPI schema that may be used to generate clients and server stubs for Desktop Agent Bridging. It is based on references to the JSON schema files that define the various messages in the adjacent schemas/bridging folder.\n\nExample commands to generate code from the AsyncAPI schema:\n(run from the root of your FDC3 checkout)\n\nFirst run:\n\n```ps\nnpm install -g @asyncapi/generator\n```\n\nThen:\n\n- .NET\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/dotnet-nats-template -o ../some/path/outside/FDC3/folder\n    ```\n\n- Node.js\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/nodejs-ws-template -o ../some/path/outside/FDC3/folder -p server=local\n     ```\n\n- Markdown\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/markdown-template -o ../some/path/outside/FDC3/folder \n     ```\n\n- HTML\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/html-template -o ../some/path/outside/FDC3/folder \n    ```\n"
  },
  {
    "path": "packages/fdc3-schema/schemas/bridgingAsyncAPI/bridgingAsyncAPI.json",
    "content": "{\n    \"asyncapi\": \"2.6.0\",\n    \"info\": {\n        \"title\": \"Desktop Agent Bridge\",\n        \"version\": \"1.0.0\",\n        \"description\": \"API for an FDC3 Desktop Agent to communicate with an FDC3 Desktop Agent Bridge and through it, other Desktop Agents.\",\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"https://www.apache.org/licenses/LICENSE-2.0\"\n        }\n    },\n    \"servers\": {\n        \"local\": {\n            \"url\": \"ws://localhost:4475\",\n            \"description\": \"Desktop agent bridge server exposing websocket connection\",\n            \"protocol\": \"ws\"\n        }\n    },\n    \"defaultContentType\": \"application/json\",\n    \"channels\": {\n        \"/\": {\n            \"publish\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/handshake\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/broadcastRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelBroadcast-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerAdded-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerRemoved-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnAddContextListener-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnUnsubscribe-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Agent\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by A Desktop Agent to a Bridge\",\n                \"operationId\": \"Send\"\n            },\n            \"subscribe\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/hello\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/authenticationFailed\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/connectedAgentsUpdate\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Bridge\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by a Bridge to a Desktop Agent\",\n                \"operationId\": \"Receive\"\n            }\n        }\n    },\n    \"components\": {\n        \"messages\": {\n            \"broadcastRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/broadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"hello\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep2Hello.schema.json#\"\n                }\n            },\n            \"handshake\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep3Handshake.schema.json#\"\n                }\n            },\n            \"authenticationFailed\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep4AuthenticationFailed.schema.json#\"\n                }\n            },\n            \"connectedAgentsUpdate\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep6ConnectedAgentsUpdate.schema.json#\"\n                }\n            },\n            \"findInstancesRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentRequest.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentRequest.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"openRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentRequest.schema.json#\"\n                }\n            },\n            \"openResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"openResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"privateChannelBroadcast-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelBroadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerAdded-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerAddedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerRemoved-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerRemovedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnAddContextListener-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnAddContextListenerAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnDisconnect-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnDisconnectAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnUnsubscribe-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnUnsubscribeAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeErrorResponse.schema.json#\"\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "packages/fdc3-schema/src/index.ts",
    "content": "import * as BrowserTypes from '../generated/api/BrowserTypes.js';\nimport * as BridgingTypes from '../generated/bridging/BridgingTypes.js';\n\nexport { BrowserTypes, BridgingTypes };\n"
  },
  {
    "path": "packages/fdc3-schema/tsconfig.json",
    "content": "{\n    \"extends\": \"../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"rootDirs\": [\n            \"src\",\n            \"generated\"\n        ],\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src/**/*.ts\",\n        \"generated/**/*.ts\",\n        \"schemas/**/*.json\"\n    ],\n    \"exclude\": [\n        \"dist/**\"\n    ],\n    \"references\": []\n}"
  },
  {
    "path": "packages/fdc3-standard/.eslintrc.json",
    "content": "{\n    \"root\": true,\n    \"parser\": \"@typescript-eslint/parser\",\n    \"parserOptions\": {\n        \"project\": [\n            \"./tsconfig.json\"\n        ]\n    },\n    \"plugins\": [\n        \"@typescript-eslint\",\n        \"jsx-a11y\"\n    ],\n    \"env\": {\n        \"browser\": true,\n        \"jest\": true\n    },\n    \"extends\": [\n        \"plugin:@typescript-eslint/eslint-recommended\",\n        \"plugin:@typescript-eslint/recommended\",\n        \"prettier\"\n    ],\n    \"rules\": {\n        \"@typescript-eslint/adjacent-overload-signatures\": \"warn\",\n        \"@typescript-eslint/no-empty-interface\": \"warn\",\n        \"@typescript-eslint/no-empty-function\": \"warn\",\n        \"@typescript-eslint/no-explicit-any\": \"off\",\n        \"@typescript-eslint/no-unused-vars\": [\n            \"error\",\n            {\n                \"argsIgnorePattern\": \"^_\"\n            }\n        ]\n    }\n}"
  },
  {
    "path": "packages/fdc3-standard/README.md",
    "content": "# FDC3 Standard Module\n\nInterface definitions for the FDC3 standard in TypeScript (e.g. the `DesktopAgent` interface) and the app directory schema.  \n\nFurther details:\n - https://github.com/finos/FDC3\n - [FDC3 Specification](https://fdc3.finos.org/)\n - Main FDC3 module: https://www.npmjs.com/package/@finos/fdc3"
  },
  {
    "path": "packages/fdc3-standard/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n  {\n    rules: {\n      '@typescript-eslint/adjacent-overload-signatures': 'warn',\n      '@typescript-eslint/no-empty-function': 'warn',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          argsIgnorePattern: '^_',\n        },\n      ],\n    },\n  },\n];\n"
  },
  {
    "path": "packages/fdc3-standard/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-standard\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"clean\": \"rimraf dist coverage\",\n    \"build\": \"tsc\",\n    \"test\": \"tsc && vitest run\",\n    \"test:watch\": \"vitest\",\n    \"lint\": \"eslint src/ --fix\"\n  },\n  \"prettier\": {\n    \"semi\": true,\n    \"singleQuote\": true,\n    \"arrowParens\": \"avoid\",\n    \"trailingComma\": \"es5\",\n    \"endOfLine\": \"auto\",\n    \"printWidth\": 120\n  },\n  \"dependencies\": {\n    \"@finos/fdc3-context\": \"2.2.2\",\n    \"@finos/fdc3-schema\": \"2.2.2\"\n  },\n  \"devDependencies\": {\n    \"@apidevtools/swagger-parser\": \"^10.1.1\",\n    \"jsdom\": \"^28.1.0\",\n    \"jsonschema\": \"^1.4.0\",\n    \"quicktype\": \"23.0.78\",\n    \"tslib\": \"^2.7.0\",\n    \"vitest-mock-extended\": \"^3.0.0\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/AppIdentifier.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * Identifies an application, or instance of an application, and is used to target FDC3 API calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application instances.\n *\n * Will always include at least an `appId` field, which uniquely identifies a specific app.\n *\n * If the `instanceId` field is set then the `AppMetadata` object represents a specific instance of the application that may be addressed using that Id.\n */\nexport interface AppIdentifier {\n  /** The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root' */\n  readonly appId: string;\n\n  /** An optional instance identifier, indicating that this object represents a specific instance of the application described.*/\n  readonly instanceId?: string;\n\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\n   *  @experimental Introduced in FDC3 2.1 and may be refined by further changes outside the normal FDC3 versioning policy.\n   **/\n  readonly desktopAgent?: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/AppIntent.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { AppMetadata } from './AppMetadata.js';\nimport { IntentMetadata } from './IntentMetadata.js';\n\n/**\n * An interface that relates an intent to apps\n */\nexport interface AppIntent {\n  /** Details of the intent whose relationship to resolving applications is being described. */\n  readonly intent: IntentMetadata;\n  /** Details of applications that can resolve the intent. */\n  readonly apps: Array<AppMetadata>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/AppMetadata.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { AppIdentifier } from './AppIdentifier.js';\nimport { Icon } from './Icon.js';\nimport { Image } from './Image.js';\n\n/**\n * Extends an `AppIdentifier`, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\n *\n * The additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\n *\n * Note that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\n */\nexport interface AppMetadata extends AppIdentifier {\n  /** \n      The 'friendly' app name. \n      This field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier` wth `appId` set. \n      Note that for display purposes the `title` field should be used, if set, in preference to this field.\n   */\n  readonly name?: string;\n\n  /** The Version of the application. */\n  readonly version?: string;\n\n  /** 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. */\n  readonly instanceMetadata?: { [key: string]: any };\n\n  /** A more user-friendly application title that can be used to render UI elements  */\n  readonly title?: string;\n\n  /**  A tooltip for the application that can be used to render UI elements */\n  readonly tooltip?: string;\n\n  /** A longer, multi-paragraph description for the application that could include markup */\n  readonly description?: string;\n\n  /** A list of icon URLs for the application that can be used to render UI elements */\n  readonly icons?: Array<Icon>;\n\n  /** Images representing the app in common usage scenarios that can be used to render UI elements  */\n  readonly screenshots?: Array<Image>;\n\n  /** The type of output 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 (e.g. \"channel<fdc3.instrument>\"). */\n  readonly resultType?: string | null;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Channel.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { Context } from '@finos/fdc3-context';\nimport { ContextHandler } from './Types.js';\nimport { DisplayMetadata } from './DisplayMetadata.js';\nimport { Listener } from './Listener.js';\nimport { EventHandler } from './Events.js';\n\n/**\n * Represents a context channel that applications can use to send and receive\n * context data.\n *\n * Please note that There are differences in behavior when you interact with a\n * User channel via the `DesktopAgent` interface and the `Channel` interface.\n * Specifically, when 'joining' a User channel or adding a context listener\n * when already joined to a channel via the `DesktopAgent` interface, existing\n * context (matching the type of the context listener) on the channel is\n * received by the context listener immediately. Whereas, when a context\n * listener is added via the Channel interface, context is not received\n * automatically, but may be retrieved manually via the `getCurrentContext()`\n * function.\n */\nexport interface Channel {\n  /**\n   * Constant that uniquely identifies this channel.\n   */\n  readonly id: string;\n\n  /**\n   * Uniquely defines each channel type.\n   * Can be \"user\", \"app\" or \"private\".\n   */\n  readonly type: 'user' | 'app' | 'private';\n\n  /**\n   * Channels may be visualized and selectable by users. DisplayMetadata may be used to provide hints on how to see them.\n   * For App channels, displayMetadata would typically not be present.\n   */\n  readonly displayMetadata?: DisplayMetadata;\n\n  /**\n   * Broadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of.\n   *\n   * If the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the `ChannelError` enumeration.\n   *\n   * Channel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n   *\n   * If you are working with complex context types composed of other simpler types (as recommended by the FDC3 Context Data specification) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n   *\n   * If an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the `ChannelError.MalformedContext` error.\n   */\n  broadcast(context: Context): Promise<void>;\n\n  /**\n   * When a `contextType`_` is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n   *\n   * If no `contextType` is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n   *\n   * It is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n   *\n   * If getting the current context fails, the promise will be rejected with an `Error` with a `message` string from the `ChannelError` enumeration.\n   */\n  getCurrentContext(contextType?: string): Promise<Context | null>;\n\n  /**\n   * Adds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n   *\n   * If, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the `getCurrentContext(contextType)` function.\n   *\n   * Optional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n   *\n   * Adding multiple context listeners on the same or overlapping types (i.e. named type and null type) MUST be allowed, and MUST trigger all context handlers when a relevant context type is broadcast on the current channel.\n   *\n   */\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n\n  /**\n   * Clears context from the channel, and triggers the event listener on the `contextCleared` event to notify existing listeners that the context was cleared. Listeners added to the channel and calls to [`getCurrentContext`](#getcurrentcontext) will not receive any existing context until new context is broadcast to the channel.\n   *\n   * If a `contextType` is provided, only contexts of that type will be cleared.\n   *\n   * If no `contextType` is provided, all contexts will be cleared.\n   */\n  clearContext(contextType?: string): Promise<void>;\n\n  /**\n   * Register a handler for events from the Channel. Whenever the handler function\n   * is called it will be passed an event object with details related to the event.\n   *\n   * ```js\n   * // any event type\n   * const listener = await myChannel.addEventListener(null, event => {\n   *   console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n   * });\n   *\n   * // listener for a specific event type\n   * const contextClearedListener = await myChannel.addEventListener(\n   *    \"contextCleared\",\n   *    event => { ... }\n   * );\n   * ```\n   *\n   * @param {string | null} type If non-null, only events of the specified type will be received by the handler.\n   * @param {EventHandler} handler A function that events received will be passed to.\n   *\n   */\n  addEventListener(type: string | null, handler: EventHandler): Promise<Listener>;\n\n  /**\n   * @deprecated use `addContextListener(null, handler)` instead of `addContextListener(handler)`.\n   */\n  // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/ContextMetadata.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { AppIdentifier } from './AppIdentifier.js';\n\n/**\n * Metadata relating to a context or intent and context received through the\n * `addContextListener` and `addIntentListener` functions.\n *\n * @experimental Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy.\n */\nexport interface ContextMetadata {\n  /** Identifier for the app instance that sent the context and/or intent.\n   *\n   *  @experimental\n   */\n  readonly source: AppIdentifier;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/DesktopAgent.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { AppIntent } from './AppIntent.js';\nimport { Channel } from './Channel.js';\nimport { ContextHandler, IntentHandler } from './Types.js';\nimport { IntentResolution } from './IntentResolution.js';\nimport { Listener } from './Listener.js';\nimport { Context } from '@finos/fdc3-context';\nimport { ImplementationMetadata } from './ImplementationMetadata.js';\nimport { PrivateChannel } from './PrivateChannel.js';\nimport { AppIdentifier } from './AppIdentifier.js';\nimport { AppMetadata } from './AppMetadata.js';\nimport { Intent } from '../intents/Intents.js';\nimport { ContextType } from '../context/ContextType.js';\nimport { EventHandler, FDC3EventTypes } from './Events.js';\n\n/**\n * A Desktop Agent is a desktop component (or aggregate of components) that serves as a\n * launcher and message router (broker) for applications in its domain.\n *\n * A Desktop Agent can be connected to one or more App Directories and will use directories for application\n * identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of\n * a given platform, handling functionality like explicit application interop workflows where\n * security, consistency, and implementation requirements are proprietary.\n */\n\nexport interface DesktopAgent {\n  /**\n   * Launches an app, specified via an `AppIdentifier` object.\n   *\n   * The `open` method differs in use from `raiseIntent`.  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying the App Directory, `open` would be used to open an app returned in the search results.\n   *\n   * **Note**, if the intent, context and target app name are all known, it is recommended to instead use `raiseIntent` with the `target` argument.\n   *\n   * If a Context object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n   *\n   * Returns an `AppIdentifier` object with the `instanceId` field set identifying the instance of the application opened by this call.\n   *\n   * If an error occurs while opening the app, the promise MUST be rejected with an `Error` Object with a `message` chosen from the `OpenError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration.\n   *\n   * ```javascript\n   * //Open an app without context, using an AppIdentifier object to specify the target by `appId`.\n   * let appIdentifier = {appId: 'myApp-v1.0.1'};\n   * let instanceIdentifier = await fdc3.open(appIdentifier);\n   *\n   * //Open an app with context\n   * let instanceIdentifier = await fdc3.open(appIdentifier, context);\n   * ```\n   */\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n\n  /**\n   * Find out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type.\n   *\n   * `findIntent` is effectively granting programmatic access to the Desktop Agent's resolver.\n   * It returns a promise resolving to the intent, its metadata and metadata about the apps and app instances that registered that intent.\n   * This can be used to raise the intent against a specific app or app instance.\n   *\n   * If the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the `ResolveError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration. This includes the case where no apps are found that resolve the intent, when the `ResolveError.NoAppsFound` message should be used, and when an invalid context object is passed as an argument, when the `ResolveError.MalformedContext` message should be used.\n   *\n   * Result types may be a type name, the string \"channel\" (which indicates that the app\n   * will return a channel) or a string indicating a channel that returns a specific type,\n   * e.g. \"channel<fdc3.instrument>\".\n   *\n   * If intent resolution to an app returning a channel is requested, the desktop agent\n   * MUST include both apps that are registered as returning a channel and those registered\n   * as returning a channel with a specific type in the response.\n   *\n   * ```javascript\n   * // I know 'StartChat' exists as a concept, and want to know which apps can resolve it ...\n   * const appIntent = await fdc3.findIntent(\"StartChat\");\n   *\n   * // returns a single AppIntent:\n   * // {\n   * //     intent: { name: \"StartChat\" },\n   * //   apps: [\n   * //    { appId: \"Skype\" },\n   * //    { appId: \"Symphony\" },\n   * //    { appId: \"Slack\" }\n   * //   ]\n   * // }\n   *\n   * // raise the intent against a particular app\n   * await fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0]);\n   *\n   * //later, we want to raise 'StartChat' intent again\n   * const appIntent = await fdc3.findIntent(\"StartChat\");\n   * // returns an AppIntent, but with multiple options for resolution,\n   * // which includes an existing instance of an application:\n   * // {\n   * //   intent: { name: \"StartChat\" },\n   * //   apps: [\n   * //    { appId: \"Skype\" },\n   * //    { appId: \"Symphony\" },\n   * //    { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n   * //    { appId: \"Slack\" }\n   * //   ]\n   * ```\n   *\n   * An optional input context object and result type may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types.\n   *\n   * ```javascript\n   * const appIntent = await fdc3.findIntent(\"StartChat\", contact);\n   *\n   * // returns only apps that support the type of the specified input context:\n   * // {\n   * //     intent: { name: \"StartChat\" },\n   * //     apps: [{ appId: \"Symphony\" }]\n   * // }\n   *\n   * const appIntent = await fdc3.findIntent(\"ViewContact\", contact, \"fdc3.ContactList\");\n   *\n   * // returns only apps that return the specified result Context type:\n   * // {\n   * //     intent: { name: \"ViewContact\" },\n   * //     apps: { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n   * // }\n   *\n   * const appIntent = await fdc3.findIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n   *\n   * // returns only apps that return a channel which will receive the specified input and result types:\n   * // {\n   * //     intent: { name: \"QuoteStream\" },\n   * //     apps: [{ appId: \"MyOMS\", resultType: \"channel<fdc3.Quote>\"}]\n   * // }\n   * ```\n   */\n  findIntent(intent: Intent, context?: Context, resultType?: string): Promise<AppIntent>;\n\n  /**\n   * Find all the available intents for a particular context, and optionally a desired result context type.\n   *\n   * `findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.\n   * It returns a promise resolving to an `AppIntent` which provides details of the intent, its metadata and metadata about the apps and app instances that are registered to handle it. This can be used to raise the intent against a specific app or app instance.\n   *\n   * If the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the `ResolveError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration. This includes the case where no intents with associated apps are found, when the `ResolveError.NoAppsFound` message should be used, and when an invalid context object is passed as an argument, when the `ResolveError.MalformedContext` message should be used.\n   *\n   * The optional `resultType` argument may be a type name, the string \"channel\" (which indicates that the app\n   * should return a channel) or a string indicating a channel that returns a specific type,\n   * e.g. \"channel<fdc3.instrument>\". If intent resolution to an app returning a channel is requested without\n   * a specified context type, the desktop agent MUST also include apps that are registered as returning a\n   * channel with a specific type in the response.\n   *\n   * ```javascript\n   * // 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...\n   * const appIntents = await fdc3.findIntentsByContext(context);\n   *\n   * // returns for example:\n   * // [\n   * //   {\n   * //     intent: { name: \"StartCall\" },\n   * //     apps: [{ name: \"Skype\" }]\n   * //   },\n   * //   {\n   * //     intent: { name: \"StartChat\" },\n   * //     apps: [\n   * //       { appId: \"Skype\" },\n   * //       { appId: \"Symphony\" },\n   * //       { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n   * //       { appId: \"Slack\" }\n   * //     ]\n   * //   }\n   * // ];\n   *\n   * // or I look for only intents that are resolved by apps returning a particular result type\n   * const appIntentsForType = await fdc3.findIntentsByContext(context, \"fdc3.ContactList\");\n   * // returns for example:\n   * // [{\n   * //     intent: { name: \"ViewContact\" },\n   * //     apps: [{ appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n   * // }];\n   *\n   * // select a particular intent to raise\n   * const resolvedIntent = appIntents[1];\n   *\n   * // target a particular app or instance\n   * const selectedApp = resolvedIntent.apps[2];\n   *\n   * // raise the intent, passing the given context, targeting the app or app instance\n   * await fdc3.raiseIntent(startChat.intent.name, context, selectedApp);\n   * ```\n   */\n  findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n\n  /**\n   * Find all the available instances for a particular application.\n   *\n   * If there are no instances of the specified application the returned promise should resolve to an empty array.\n   *\n   * If the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the `ResolveError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration.\n   *\n   * ```javascript\n   * // Retrieve a list of instances of an application\n   * let instances = await fdc3.findInstances({appId: \"MyAppId\"});\n   *\n   * // Target a raised intent at a specific instance\n   * let resolution = fdc3.raiseIntent(\"ViewInstrument\", context, instances[0]);\n   * ```\n   * @param app\n   */\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n\n  /**\n   * Publishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User Channel_ the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n   *\n   * DesktopAgent implementations should ensure that context messages broadcast to a channel by an application joined to it should not be delivered back to that same application.\n   *\n   * If you are working with complex context types composed of other simpler types then you should broadcast\n   * each individual type (starting with the simpler types, followed by the complex type) that you want other\n   * apps to be able to respond to. Doing so allows applications to filter the context types they receive by\n   * adding listeners for specific context types.\n   *\n   * If an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the `ChannelError.MalformedContext` error.\n   *\n   * ```javascript\n   * const instrument = {\n   *   type: 'fdc3.instrument',\n   *   id: {\n   *     ticker: 'AAPL'\n   *   }\n   * };\n   * fdc3.broadcast(context);\n   * ```\n   */\n  broadcast(context: Context): Promise<void>;\n\n  /**\n   * Raises a specific intent for resolution against apps registered with the Desktop Agent.\n   *\n   * 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, the user MAY be presented with a Resolver UI allowing them to pick one, or another method of Resolution applied to select an app.\n   * 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`.\n   *\n   * 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, the promise MUST be rejected with an `Error` object with a `message` chosen from the `ResolveError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the `ResolveError.MalformedContext` string as its `message`.\n   *\n   * 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.\n   *\n   * Returns an `IntentResolution` object with details of the app instance that was selected (or started) to respond to the intent.\n   *\n   * 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, Channel object or void 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` enumeration, if: (1) the intent handling function's returned promise rejects, (2) the intent handling function doesn't return a valid response (a promise or void), or (3) the returned promise resolves to an invalid type.\n   *\n   * ```javascript\n   * // raise an intent for resolution by the desktop agent\n   * // a resolver UI may be displayed if more than one application can resolve the intent\n   * await fdc3.raiseIntent(\"StartChat\", context);\n   *\n   * // or find apps to resolve an intent to start a chat with a given contact\n   * const appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n   * // use the metadata of an app or app instance to describe the target app for the intent\n   * await fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n   *\n   * //Raise an intent without a context by using the null context type\n   * await fdc3.raiseIntent(\"StartChat\", {type: \"fdc3.nothing\"});\n   *\n   * //Raise an intent and retrieve a result from the IntentResolution\n   * let resolution = await agent.raiseIntent(\"intentName\", context);\n   * try {\n   * \t   const result = await resolution.getResult();\n   *     if (result && result.broadcast) { //detect whether the result is Context or a Channel\n   *         console.log(`${resolution.source} returned a channel with id ${result.id}`);\n   *     } else if (result){\n   *         console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n   *     } else {\n   *         console.error(`${resolution.source} didn't return anything`\n   *     }\n   * } catch(error) {\n   *     console.error(`${resolution.source} returned an error: ${error}`);\n   * }\n   * ```\n   */\n  raiseIntent(intent: Intent, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n\n  /**\n   * Finds and raises an intent against apps registered with the desktop agent based on the type of the specified context data example.\n   *\n   * The desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context.\n   * Alternatively, the specific app or app instance to target can also be provided, in which case the resolver SHOULD only offer intents supported by the specified application.\n   *\n   * Using `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app.\n   *\n   * Returns an `IntentResolution` object, see `raiseIntent()` for details.\n   *\n   * If a target intent and app cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, the promise MUST be rejected with an `Error` object with a `message` chosen from the `ResolveError` enumeration, or (if connected to a Desktop Agent Bridge) the `BridgingError` enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`.  If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the `ResolveError.MalformedContext` string as its `message`.\n   *\n   * ```javascript\n   * // Resolve against all intents registered for the type of the specified context\n   * await fdc3.raiseIntentForContext(context);\n   *\n   * // Resolve against all intents registered by a specific target app for the specified context\n   * await fdc3.raiseIntentForContext(context, targetAppIdentifier);\n   * ```\n   */\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n\n  /**\n   * Adds a listener for incoming intents raised by other applications, via calls to `fdc3.raiseIntent` or `fdc3.raiseIntentForContext.  If the application is intended to be launched to resolve raised intents, it SHOULD add its intent listeners as quickly as possible after launch or an error MAY be returned to the caller and the intent and context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n   *\n   * The handler function may return void or a promise that should resolve to an `IntentResult`, which is either a `Context` object, representing any data that should be returned to the app that raised the intent, a `Channel` Object, a `PrivateChannel` over which data responses will be sent, or `void`. The `IntentResult` will be returned to app that raised the intent via the `IntentResolution` and retrieved from it using the `getResult()` function.\n   *\n   * The Desktop Agent MUST reject the promise returned by the `getResult()` function of `IntentResolution` 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.\n   *\n   * The `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n   *\n   * Optional metadata about the raised intent, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n   *\n   * Adding multiple intent listeners on the same type MUST be rejected with the `ResolveError.IntentListenerConflict`, unless the previous listener was removed first though `listener.unsubscribe()`\n   *\n   * ```javascript\n   * //Handle a raised intent\n   * const listener = fdc3.addIntentListener('StartChat', context => {\n   *     // start chat has been requested by another application\n   *     return;\n   * });\n   *\n   * //Handle a raised intent and log the originating app metadata\n   * const listener = fdc3.addIntentListener('StartChat', (contact, metadata) => {\n   *   console.log(`Received intent StartChat\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n   *   return;\n   * });\n   *\n   * //Handle a raised intent and return Context data via a promise\n   * fdc3.addIntentListener(\"CreateOrder\", (context) => {\n   *     return new Promise<Context>((resolve) => {\n   *         // go create the order\n   *         resolve({type: \"fdc3.order\", id: { \"orderId\": 1234}});\n   *\t   });\n   * });\n   *\n   * //Handle a raised intent and return a Private Channel over which response will be sent\n   * fdc3.addIntentListener(\"QuoteStream\", async (context) => {\n   *   const channel: PrivateChannel = await fdc3.createPrivateChannel();\n   *   const symbol = context.id.symbol;\n   *\n   *   // Called when the remote side adds a context listener\n   *   const addContextListener = channel.onAddContextListener((contextType) => {\n   *     // broadcast price quotes as they come in from our quote feed\n   *     feed.onQuote(symbol, (price) => {\n   *       channel.broadcast({ type: \"price\", price});\n   *     });\n   *   });\n   *\n   *   // Stop the feed if the remote side closes\n   *   const disconnectListener = channel.onDisconnect(() => {\n   *     feed.stop(symbol);\n   *   });\n   *\n   *   return channel;\n   * });\n   * ```\n   */\n  addIntentListener(intent: Intent, handler: IntentHandler): Promise<Listener>;\n\n  /**\n   * Adds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or `fdc3.open`API call. If the consumer is only interested in a context of a particular type, they can they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.\n   *\n   * Context broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from channels. If this function is called after the app has already joined a channel and the channel already contains context that would be passed to the context listener, then it will be called immediately with that context.\n   *\n   * Context may also be received via this listener if the application was launched via a call to  `fdc3.open`, where context was passed as an argument. In order to receive this, applications SHOULD add their context listener as quickly as possible after launch, or an error MAY be returned to the caller and the context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n   *\n   * Optional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n   *\n   * Adding multiple context listeners on the same or overlapping types (i.e. named type and null type) MUST be allowed, and MUST trigger all contextHandlers when a relevant context type is broadcast on the current user channel. Please note, that this behavior differs from `fdc3.addIntentListener` API call; refer to the relevant documentation for more detials.\n   *\n   * ```javascript\n   * // any context\n   * const listener = await fdc3.addContextListener(null, context => { ... });\n   *\n   * // listener for a specific type\n   * const contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });\n   *\n   * // listener that logs metadata for the message a specific type\n   * const contactListener = await fdc3.addContextListener('fdc3.contact', (contact, metadata) => {\n   *   console.log(`Received context message\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n   *   //do something else with the context\n   * });\n   * ```\n   */\n  addContextListener(contextType: ContextType | null, handler: ContextHandler): Promise<Listener>;\n\n  /**\n   * Register a handler for events from the Desktop Agent. Whenever the handler function\n   * is called it will be passed an event object with details related to the event.\n   *\n   * ```js\n   * // any event type\n   * const listener = await fdc3.addEventListener(null, event => { ... });\n   *\n   * // listener for a specific event type that logs its details\n   * const userChannelChangedListener = await fdc3.addEventListener(\"userChannelChanged\", event => {\n   * console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n   * //do something else with the event\n   * });\n   * ```\n   *\n   * @param {FDC3EventType|null} type If non-null, only events of the specified type will be received by the handler.\n   * @param {EventHandler} handler A function that events received will be passed to.\n   *\n   */\n  addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise<Listener>;\n\n  /**\n   * Retrieves a list of the User channels available for the app to join.\n   */\n  getUserChannels(): Promise<Array<Channel>>;\n\n  /**\n   * Optional function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.\n   *\n   * If an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.\n   *\n   * If the channel already contains context that would be passed to context listeners added via `fdc3.addContextListener` then those listeners will be called immediately with that context.\n   *\n   * An app can only be joined to one channel at a time.\n   *\n   * If an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n   *\n   * ```javascript\n   *   // get all system channels\n   *   const channels = await fdc3.getUserChannels();\n   *   // create UI to pick from the User channels\n   *   // join the channel on selection\n   *   fdc3.joinUserChannel(selectedChannel.id);\n   *  ```\n   */\n  joinUserChannel(channelId: string): Promise<void>;\n\n  /**\n   * Returns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist.\n   *\n   * If the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n   *\n   * ```javascript\n   * try {\n   *   const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n   *   const myChannel.addContextListener(null, context => {});\n   * }\n   * catch (err){\n   *   //app could not register the channel\n   * }\n   * ```\n   */\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n\n  /**\n   * Returns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create Channels that will be returned to other applications via an `IntentResolution` for a raised intent.\n   *\n   * If the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the `ChannelError` enumeration.\n   *\n   * The `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n   *\n   *  * It is intended that Desktop Agent implementations:\n   * - SHOULD restrict external apps from listening or publishing on this channel.\n   * - MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n   * - MUST provide the `id` value for the channel as required by the `Channel` interface.\n   *\n   * ```javascript\n   * fdc3.addIntentListener(\"QuoteStream\", async (context) => {\n   * \tconst channel: PrivateChannel = await fdc3.createPrivateChannel();\n   * \tconst symbol = context.id.ticker;\n   *\n   * \t// This gets called when the remote side adds a context listener\n   * \tconst addContextListener = channel.onAddContextListener((contextType) => {\n   * \t\t// broadcast price quotes as they come in from our quote feed\n   * \t\tfeed.onQuote(symbol, (price) => {\n   * \t\t\tchannel.broadcast({ type: \"price\", price});\n   * \t\t});\n   * \t});\n   *\n   * \t// This gets called when the remote side calls Listener.unsubscribe()\n   * \tconst unsubscriberListener = channel.onUnsubscribe((contextType) => {\n   * \t\tfeed.stop(symbol);\n   * \t});\n   *\n   * \t// This gets called if the remote side closes\n   * \tconst disconnectListener = channel.onDisconnect(() => {\n   * \t\tfeed.stop(symbol);\n   * \t})\n   *\n   * \treturn channel;\n   * });\n   * ```\n   */\n  createPrivateChannel(): Promise<PrivateChannel>;\n\n  /**\n   * Optional function that returns the `Channel` object for the current User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n   *\n   * Returns `null` if the app is not joined to a channel.\n   */\n  getCurrentChannel(): Promise<Channel | null>;\n\n  /**\n   * Optional function that removes the app from any User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n   *\n   * Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not on a channel.\n   *\n   * ```javascript\n   * //desktop-agent scope context listener\n   * const fdc3Listener = fdc3.addContextListener(null, context => {});\n   * await fdc3.leaveCurrentChannel();\n   * //the fdc3Listener will now cease receiving context\n   * //listening on a specific channel, retrieved via fdc3.getOrCreateChannel(), will continue to work:\n   * redChannel.addContextListener(null, channelListener);\n   * ```\n   */\n  leaveCurrentChannel(): Promise<void>;\n\n  /**\n   * Retrieves information about the FDC3 Desktop Agent implementation, including the supported version\n   * of the FDC3 specification, the name of the provider of the implementation, its own version number\n   * and the metadata of the calling application according to the desktop agent.\n   *\n   * Returns an `ImplementationMetadata` object.  This metadata object can be used to vary the behavior\n   * of an application based on the version supported by the Desktop Agent and for logging purposes.\n   *\n   * ```js\n   * import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n   *\n   * if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n   *   await fdc3.raiseIntentForContext(context);\n   * } else {\n   *   await fdc3.raiseIntent(\"ViewChart\", context);\n   * }\n   * ```\n   *\n   * The `ImplementationMetadata` object returned also includes the metadata for the calling application,\n   * according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId`\n   * and other details, e.g.:\n   *\n   * ```js\n   * let implementationMetadata = await fdc3.getInfo();\n   * let {appId, instanceId} = implementationMetadata.appMetadata;\n   * ```\n   */\n  getInfo(): Promise<ImplementationMetadata>;\n\n  /**\n   * Retrieves the `AppMetadata` for an `AppIdentifier`, which provides additional metadata (such as icons,\n   * a title and description) from the App Directory record for the application, that may be used for display\n   * purposes.\n   *\n   * If the app is not found, the promise MUST be rejected with an `Error` Object with the `message` given by `ResolveError.TargetAppUnavailable`, or (if connected to a Desktop Agent Bridge) an error from the `BridgingError` enumeration.\n   *\n   * ```js\n   * let appIdentifier = { appId: \"MyAppId@my.appd.com\" }\n   * let appMetadata = await fdc3.getAppMetadata(appIdentifier);\n   * ```\n   */\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n\n  //---------------------------------------------------------------------------------------------\n  // Deprecated function signatures\n  //---------------------------------------------------------------------------------------------\n\n  /**\n   * Adds a listener for incoming context broadcasts from the Desktop Agent.\n   * @deprecated use `addContextListener(null, handler)` instead of `addContextListener(handler)`. Provided for backwards compatibility with versions FDC3 standard <2.0.\n   */\n  // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n\n  /**\n   * @deprecated Alias to the `getUserChannels` function provided for backwards compatibility with versions FDC3 standard <2.0.\n   */\n  getSystemChannels(): Promise<Array<Channel>>;\n\n  /**\n   * @deprecated Alias to the `joinUserChannel` function Provided for backwards compatibility with versions FDC3 standard <2.0.\n   */\n  joinChannel(channelId: string): Promise<void>;\n\n  /**\n   * @deprecated version of `open` that launches an app by by name rather than `AppIdentifier`. Provided for backwards compatibility with versions FDC3 standard <2.0.\n   *\n   * ```javascript\n   * //Open an app without context, using the app name\n   * let instanceMetadata = await fdc3.open('myApp');\n   * ```\n   */\n  // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures\n  open(name: string, context?: Context): Promise<AppIdentifier>;\n\n  /**\n   * @deprecated version of `raiseIntent` that targets an app by by name rather than `AppIdentifier`. Provided for backwards compatibility with versions FDC3 standard <2.0.\n   *\n   * ```javascript\n   * // use the `name` metadata of an app to describe the target app for the intent\n   * await fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0].name);\n   * ```\n   */\n  // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures\n  raiseIntent(intent: Intent, context: Context, name: string): Promise<IntentResolution>;\n\n  /**\n   * @deprecated version of `raiseIntentForContext` that targets an app by by name rather than `AppIdentifier`. Provided for backwards compatibility with versions FDC3 standard <2.0.\n   *\n   * ```javascript\n   * // Resolve against all intents registered by a specific target app name for the specified context\n   * await fdc3.raiseIntentForContext(context, targetAppName);\n   * ```\n   */\n  // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures\n  raiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/DesktopAgentIdentifier.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\n * where a request needs to be directed to a Desktop Agent rather than a specific app, or a\n * response message is returned by the Desktop Agent (or more specifically its resolver)\n * rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\n * app details are available or are appropriate.\n * @experimental Introduced in FDC3 2.1 and may be refined by further changes outside the normal FDC3 versioning policy.\n */\nexport interface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a\n   *  particular Desktop Agent. */\n  readonly desktopAgent: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/DisplayMetadata.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * A system channel will be global enough to have a presence across many apps. This gives us some hints\n * to render them in a standard way. It is assumed it may have other properties too, but if it has these,\n * this is their meaning.\n */\nexport interface DisplayMetadata {\n  /**\n   * A user-readable name for this channel, e.g: `\"Red\"`\n   */\n  readonly name?: string;\n\n  /**\n   * The color that should be associated within this channel when displaying this channel in a UI, e.g: `0xFF0000`.\n   */\n  readonly color?: string;\n\n  /**\n   * A URL of an image that can be used to display this channel\n   */\n  readonly glyph?: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Errors.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * Contains constants representing the errors that can be encountered when trying to connect to a web-based Desktop Agent with the getAgent function.\n */\nexport enum AgentError {\n  /** Returned if no Desktop Agent was found by any means available or\n   * if the Agent previously connected to is not contactable on a\n   * subsequent connection attempt.*/\n  AgentNotFound = 'AgentNotFound',\n\n  /** Returned if validation of the app identity by the Desktop Agent\n   * Failed or the app is not being allowed to connect to the Desktop Agent\n   * for another reason. */\n  AccessDenied = 'AccessDenied',\n\n  /** Returned if an error or exception occurs while trying to set\n   * up communication with a Desktop Agent. */\n  ErrorOnConnect = 'ErrorOnConnect',\n\n  /** Returned if the failover function is not a function, or it did not\n   * resolve to one of the allowed types. */\n  InvalidFailover = 'InvalidFailover',\n\n  /** Returned if an API call rejects after a timeout. Used where an API call\n   * is not aligned to another error enumeration.\n   */\n  ApiTimeout = 'ApiTimeout',\n}\n\n/** Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`). */\nexport enum OpenError {\n  /** Returned if the specified application is not found.*/\n  AppNotFound = 'AppNotFound',\n\n  /** Returned if the specified application fails to launch correctly.*/\n  ErrorOnLaunch = 'ErrorOnLaunch',\n\n  /** Returned if the specified application launches but fails to add a context listener in order to receive the context passed to the `fdc3.open` call.*/\n  AppTimeout = 'AppTimeout',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/\n  ResolverUnavailable = 'ResolverUnavailable',\n\n  /** Returned if a call to the `open` function is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/\n  MalformedContext = 'MalformedContext',\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n\n  /** Returned if a timeout occurs before a call to open is resolved for any reason other than the not adding its context listener in time.*/\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned when incorrect arguments are passed to API calls.*/\n  InvalidArguments = 'InvalidArguments',\n}\n\n/** Constants representing the errors that can be encountered when calling the `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`). */\nexport enum ResolveError {\n  /** SHOULD be returned if no apps are available that can resolve the intent and context combination.*/\n  NoAppsFound = 'NoAppsFound',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/\n  ResolverUnavailable = 'ResolverUnavailable',\n\n  /** Returned if the user cancelled the resolution request, for example by closing or cancelling a resolver UI.*/\n  UserCancelled = 'UserCancelledResolution',\n\n  /** SHOULD be returned if a timeout cancels an intent resolution that required user interaction. Please use `ResolverUnavailable` instead for situations where a resolver UI or similar fails.*/\n  ResolverTimeout = 'ResolverTimeout',\n\n  /** Returned if a specified target application is not available or a new instance of it cannot be opened. */\n  TargetAppUnavailable = 'TargetAppUnavailable',\n\n  /** Returned if a specified target application instance is not available, for example because it has been closed. */\n  TargetInstanceUnavailable = 'TargetInstanceUnavailable',\n\n  /** Returned if the intent and context could not be delivered to the selected application or instance, for example because it has not added an intent handler within a timeout.*/\n  IntentDeliveryFailed = 'IntentDeliveryFailed',\n\n  /** Returned if a call to one of the `raiseIntent` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/\n  MalformedContext = 'MalformedContext',\n\n  /** Returned if `fdc3.addIntentListener` is called for a specified intent that the application has already added a listener for and has not subsequently removed it. */\n  IntentListenerConflict = 'IntentListenerConflict',\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n\n  /** Returned if a timeout occurs before the API call is resolved for any reason other than the resolver timing out (use ResolverTimeout) or an app launched by a raiseIntent function doesn't add its intent listener in time (use IntentDeliveryFailed).*/\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned when incorrect arguments are passed to API calls.*/\n  InvalidArguments = 'InvalidArguments',\n}\n\nexport enum ResultError {\n  /** Returned if the intent handler exited without returning a valid result (a promise resolving to a Context, Channel object or void). */\n  NoResultReturned = 'NoResultReturned',\n\n  /** Returned if the Intent handler function processing the raised intent throws an error or rejects the Promise it returned. */\n  IntentHandlerRejected = 'IntentHandlerRejected',\n\n  /** Returned if a timeout occurs before the getResult() API call is resolved.*/\n  ApiTimeout = 'ApiTimeout',\n}\n\nexport enum ChannelError {\n  /** Returned if the specified channel is not found when attempting to join a channel via the `joinUserChannel` function  of the DesktopAgent (`fdc3`).*/\n  NoChannelFound = 'NoChannelFound',\n\n  /** SHOULD be returned when a request to join a user channel or to a retrieve a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods of the DesktopAgent (`fdc3`) object is denied. */\n  AccessDenied = 'AccessDenied',\n\n  /** SHOULD be returned when a channel cannot be created or retrieved via the `getOrCreateChannel` method of the DesktopAgent (`fdc3`).*/\n  CreationFailed = 'CreationFailed',\n\n  /** Returned if a call to the `broadcast` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/\n  MalformedContext = 'MalformedContext',\n\n  /** Returned if a timeout occurs before any Channel related API call is resolved.*/\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned when incorrect arguments are passed to API calls.*/\n  InvalidArguments = 'InvalidArguments',\n}\n\nexport enum BridgingError {\n  /** @experimental Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging, within the alloted timeout. */\n  ResponseTimedOut = 'ResponseToBridgeTimedOut',\n\n  /** @experimental Returned if a Desktop Agent that has been targeted by a particular request has been disconnected from the Bridge before a response has been received from it. */\n  AgentDisconnected = 'AgentDisconnected',\n\n  /** @experimental Returned for FDC3 API calls that are specified with arguments indicating that a remote Desktop agent should be targeted (e.g. raiseIntent with an app on a remote DesktopAgent targeted), when the local Desktop Agent is not connected to a bridge. */\n  NotConnectedToBridge = 'NotConnectedToBridge',\n\n  /** @experimental Returned if a message to a Bridge deviates from the schema for that message sufficiently that it could not be processed. */\n  MalformedMessage = 'MalformedMessage',\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Events.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * Type defining a basic event object that may be emitted by an FDC3 API interface\n * such as DesktopAgent or PrivateChannel. There are more specific event types\n * defined for each interface.\n */\nexport interface ApiEvent {\n  readonly type: string;\n  readonly details: any;\n}\n\n/** Type representing a handler function for events from the Desktop Agent\n * or a PrivateChannel.\n * @param event The handler function will be passed an `ApiEvent` (or more specifically\n *  an `FDC3Event` or `PrivateChannelEvent`) Object providing details of the event (such\n * as a change of channel membership for the app, or type of context listener added)\n * as the only parameter.\n */\nexport type EventHandler = (event: ApiEvent) => void;\n\n/**\n * Type defining valid type strings for DesktopAgent interface events.\n */\nexport type FDC3EventTypes = 'userChannelChanged' | 'contextCleared';\n\n/**\n * Type defining the format of event objects that may be received\n * via the FDC3 API's `addEventListener` function.\n */\nexport interface FDC3Event extends ApiEvent {\n  readonly details: any;\n  readonly type: FDC3EventTypes;\n}\n\n/**\n * Type defining the format of event `userChannelChanged` objects\n */\nexport interface FDC3ChannelChangedEvent extends FDC3Event {\n  readonly type: 'userChannelChanged';\n  readonly details: {\n    currentChannelId: string | null;\n  };\n}\n\n/**\n * Type defining the format of event `contextCleared` objects\n */\nexport interface FDC3ContextClearedEvent extends FDC3Event {\n  readonly type: 'contextCleared';\n  readonly details: {\n    contextType: string | null;\n  };\n}\n\n/**\n * Type defining valid type strings for Private Channel events.\n */\nexport type PrivateChannelEventTypes = 'addContextListener' | 'unsubscribe' | 'disconnect';\n\n/**\n * Type defining the format of event objects that may be received\n * via a PrivateChannel's `addEventListener` function.\n */\nexport interface PrivateChannelEvent extends ApiEvent {\n  readonly type: PrivateChannelEventTypes;\n  readonly details: any;\n}\n\n/**\n * Type defining the format of events representing a context listener being\n * added to the channel (`addContextListener`). Desktop Agents MUST fire this\n * event for each invocation of `addContextListener` on the channel, including\n * those that occurred before this handler was registered (to prevent race\n * conditions).\n * The context type of the listener added is provided as `details.contextType`,\n * which will be `null` if all event types are being listened to.\n */\nexport interface PrivateChannelAddContextListenerEvent extends PrivateChannelEvent {\n  readonly type: 'addContextListener';\n  readonly details: {\n    contextType: string | null;\n  };\n}\n\n/**\n * Type defining the format of events representing a context listener\n * removed from the channel (`Listener.unsubscribe()`). Desktop Agents MUST call\n * this when `disconnect()` is called by the other party, for each listener that\n * they had added.\n * The context type of the  listener removed is provided as `details.contextType`,\n * which will be `null` if all event types were being listened to.\n */\nexport interface PrivateChannelUnsubscribeEvent extends PrivateChannelEvent {\n  readonly type: 'unsubscribe';\n  readonly details: {\n    contextType: string | null;\n  };\n}\n\n/**\n * Type defining the format of events representing a remote app being terminated\n * or otherwise disconnecting from the PrivateChannel. This event is in addition to\n * unsubscribe events that will also be fired for any context listeners they had added.\n * No details are provided.\n */\nexport interface PrivateChannelDisconnectEvent extends PrivateChannelEvent {\n  readonly type: 'disconnect';\n  readonly details: null | undefined;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/GetAgent.ts",
    "content": "/**\n * Typescript related to the getAgent() function. Note that GetAgent.md is a copy of this file which has been modified\n * for display in markdown format.\n */\nimport { DesktopAgent } from './DesktopAgent.js';\n\n/**\n * Function used to retrieve an FDC3 Desktop Agent API instance, which\n * supports the discovery of a Desktop Agent Preload (a container-injected\n * API implementation) or a Desktop Agent Proxy (a Browser-based Desktop Agent\n * running in another window or frame). Finally, if no Desktop Agent is found,\n * a failover function may be supplied by an app allowing it to start or otherwise\n * connect to a Desktop Agent (e.g. by loading a proprietary adaptor that\n * returns a `DesktopAgent` implementation or by creating a window or iframe of\n * its own that will provide a Desktop Agent Proxy.\n *\n * @param {GetAgentParams} params Optional parameters object, which\n * may include a URL to use for the app's identity, other settings\n * that affect the behavior of the getAgent() function and a `failover`\n * function that should be run if a Desktop Agent is not detected.\n *\n * @returns A promise that resolves to a DesktopAgent implementation or\n * rejects with an error message from the `AgentError` enumeration if unable to\n * return a Desktop Agent implementation.\n *\n * @example\n * const fdc3 = await getAgent();\n *\n * // OR\n *\n * getAgent({\n *     identityUrl: \"https://example.com/path?param=appName#example\",\n *     channelSelector: false,\n *     intentResolver: false\n * }).then((fdc3) => {\n *     //do FDC3 stuff here\n * };\n */\nexport type GetAgentType = (params?: GetAgentParams) => Promise<DesktopAgent>;\n\n/**\n * @typedef {Object} GetAgentParams Type representing parameters passed to the\n * getAgent function.\n *\n * @property {number} timeoutMs Number of milliseconds to allow for an FDC3\n * implementation to be found before calling the failover function or\n * rejecting (default 1000). Note that the timeout is cancelled as soon as a\n * Desktop Agent is detected. There may be additional set-up steps to perform\n * which will happen outside the timeout.\n *\n * @property {string} identityUrl The app's current URL is normally sent to\n * a web-based desktop agent to help establish its identity. This property\n * may be used to override the URL sent (to handle situations where an app's\n * URL is not sufficiently stable to use for identity purposes,  e.g. due to\n * client-side route changes when navigating within the app). The URL set MUST\n * match the origin of the application (scheme, hostname, and port) or it will\n * be ignored. If not specified, the app's current URL will be used.\n *\n * @property {boolean} channelSelector Flag indicating that the application\n * needs access to a channel selector UI (i.e. because it supports User Channels\n * and does not implement its own UI for selecting channels). Defaults to\n * `true`. MAY be ignored by Desktop Agent Preload (container) implementations.\n *\n * @property {boolean} intentResolver Flag indicating that the application\n * needs access to an intent resolver UI (i.e. because it supports raising one\n * or more intents and and does not implement its own UI for selecting target\n * apps). Defaults to `true`. MAY be ignored by Desktop Agent Preload (container)\n * implementations.\n *\n * @property {boolean} dontSetWindowFdc3 For backwards compatibility, `getAgent`\n * will set a reference to the Desktop Agent implementation at `window.fdc3`\n * if one does not already exist, and will fire the fdc3Ready event. Defaults to\n * `false`. Setting this flag to `true` will inhibit that behavior, leaving\n * `window.fdc3` unset.\n *\n * @property {function} failover An optional function that provides a\n * means of connecting to or starting a Desktop Agent, which will be called\n * if no Desktop Agent is detected. Must return either a Desktop Agent\n * implementation directly (e.g. by using a proprietary adaptor) or a\n * WindowProxy (e.g a reference to another window returned by `window.open`\n * or an iframe's `contentWindow`) for a window or frame in which it has loaded\n * a Desktop Agent or suitable proxy to one that works with FDC3 Web Connection\n * and Desktop Agent Communication Protocols.\n *\n * @property {GetAgentLogLevels} logLevels Settings that determine what should\n * will logged by the getAgent() implementation and DesktopAgentProxy to the\n * JavaScript console.\n */\nexport type GetAgentParams = {\n  timeoutMs?: number;\n  identityUrl?: string;\n  channelSelector?: boolean;\n  intentResolver?: boolean;\n  dontSetWindowFdc3?: boolean;\n  failover?: (args: GetAgentParams) => Promise<WindowProxy | DesktopAgent>;\n  logLevels?: GetAgentLogLevels;\n};\n\n/**\n * @typedef {Object} GetAgentLogLevels Type representing log-level parameters \\\n * passed to the getAgent function that control what is logged to the JavaScript\n * console by the getAgent() implementation and any DesktopAgentProxy it creates.\n *\n * @property {boolean} connection Log-level for messages relating to establishing\n * a connection to the Desktop Agent (default INFO).\n *\n * @property {boolean} proxy Log-level for messages from a DesktopAgentProxy\n * created by getAgent. These include log of messages sent or received from the\n * DesktopAgent at the INFO level and heartbeat messages at the DEBUG level\n * (default WARN).\n *\n */\nexport type GetAgentLogLevels = {\n  connection: LogLevel;\n  proxy: LogLevel;\n};\n\n/**\n * Type representing the different log-levels that can be set.\n */\nexport enum LogLevel {\n  NONE = 0,\n  ERROR = 1,\n  WARN = 2,\n  INFO = 3,\n  DEBUG = 4,\n}\n\n/** Type representing the format of data stored by `getAgent`\n *  in Session Storage. The `identityUrl` of each app is used\n *  as the key. */\nexport type SessionStorageFormat = {\n  /** */\n  [key: string]: DesktopAgentDetails;\n};\n\n/** Type representing data on the Desktop Agent that an app\n *  connected to that is persisted by the getAgent function\n *  to be used when re-connecting (after a navigation or\n *  refresh event) and to ensure a consistent instanceId.\n */\nexport type DesktopAgentDetails = {\n  /** The type of Desktop Agent connected to. Used to\n   *  prevent an inadvertent switch to a different agent.*/\n  agentType: WebDesktopAgentType;\n\n  /** The URL that was previously sent to the Desktop Agent\n   * to establish the app's identity.*/\n  identityUrl: string;\n\n  /** The current URL at the time of the last connection to\n   * a Desktop Agent.*/\n  actualUrl: string;\n\n  /** Optional URL field that should be used to store any\n   *  URL that was used to connect to a Desktop Agent. URLs\n   *  may have been provided by a parent window that has since\n   *  gone away and persisting may allow re-connection in such\n   *  cases. */\n  agentUrl?: string;\n\n  /** The appId that was identified for the application by the\n   * Desktop Agent.*/\n  appId: string;\n\n  /** The instanceId that was issued to the app by the Desktop\n   * Agent. */\n  instanceId: string;\n\n  /** The instanceUuid that was issued to the app. This should be\n   *  passed when connecting to the Desktop Agent to help\n   *  identify that this app has connected before and which\n   *  instance it is, enabling the Desktop Agent to reissue\n   *  the same instanceId. The instanceUuid should never be shared\n   *  with other applications and is not available through the\n   *  FDC3 API, allowing it to be used as a shared secret with\n   *  the Desktop Agent that issued the associated instanceId.*/\n  instanceUuid: string;\n};\n\n/** Enumeration of values used to describe types of web-based\n *  Desktop Agent. Each 'type' refers to the means by which\n *  a connection to the agent is made and/or an interface to it\n *  received. */\nexport enum WebDesktopAgentType {\n  /** Denotes Desktop Agents that inject the FDC3 interface\n   *  at `window.fdc3`. */\n  Preload = 'PRELOAD',\n\n  /** Denotes Desktop Agents that run (or provide an interface)\n   *  within a parent window or frame, a reference to which\n   *  will be found at `window.opener`, `window.parent`,\n   *  `window.parent.opener` etc. */\n  ProxyParent = 'PROXY_PARENT',\n\n  /** Denotes Desktop Agents that are connected to by loading a URL\n   *  into a hidden iframe whose URL was returned by a parent window\n   *  or frame. */\n  ProxyUrl = 'PROXY_URL',\n\n  /** Denotes a Desktop Agent that was returned by a failover\n   *  function that was passed by the application. */\n  Failover = 'FAILOVER',\n}\n\nexport const DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX = 'fdc3-desktop-agent-details';\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Icon.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nexport interface Icon {\n  /** The icon url */\n  readonly src: string;\n\n  /** The icon dimension, formatted as `<height>x<width>`. */\n  readonly size?: string;\n\n  /** Icon media type. If not present the Desktop Agent may use the src file extension. */\n  readonly type?: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Image.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nexport interface Image {\n  /** The image url. */\n  readonly src: string;\n\n  /** The image dimension, formatted as `<height>x<width>`. */\n  readonly size?: string;\n\n  /** Image media type. If not present the Desktop Agent may use the src file extension. */\n  readonly type?: string;\n\n  /** Caption for the image. */\n  readonly label?: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/ImplementationMetadata.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { AppMetadata } from './AppMetadata.js';\n\n/**\n * Metadata relating to the FDC3 Desktop Agent implementation and its provider.\n */\nexport interface ImplementationMetadata {\n  /** The version number of the FDC3 specification that the implementation provides.\n   *  The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  readonly fdc3Version: string;\n\n  /** The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42, OpenFin etc.). */\n  readonly provider: string;\n\n  /** The version of the provider of the Desktop Agent implementation (e.g. 5.3.0). */\n  readonly providerVersion?: string;\n\n  /** Metadata indicating whether the Desktop Agent implements optional features of\n   *  the Desktop Agent API.\n   */\n  readonly optionalFeatures: {\n    /** Used to indicate whether the exposure of 'originating app metadata' for\n     *  context and intent messages is supported by the Desktop Agent.*/\n    readonly OriginatingAppMetadata: boolean;\n    /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n     *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n     *  the Desktop Agent.*/\n    readonly UserChannelMembershipAPIs: boolean;\n    /** Used to indicate whether the experimental Desktop Agent Bridging\n     *  feature is implemented by the Desktop Agent.*/\n    readonly DesktopAgentBridging: boolean;\n  };\n\n  /** The calling application instance's own metadata, according to the Desktop Agent (MUST include at least the `appId` and `instanceId`). */\n  readonly appMetadata: AppMetadata;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/IntentMetadata.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { Intent } from '../intents/Intents.js';\n\n/**\n * Intent descriptor\n */\nexport interface IntentMetadata {\n  /** The unique name of the intent that can be invoked by the raiseIntent call */\n  readonly name: Intent;\n\n  /** Display name for the intent.\n   * @deprecated Use the intent name for display as display name may vary for\n   * each application as it is defined in the app's AppD record.\n   */\n  readonly displayName?: string;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/IntentResolution.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { IntentResult } from './Types.js';\nimport { AppIdentifier } from './AppIdentifier.js';\nimport { Intent } from '../intents/Intents.js';\n\n/**\n * IntentResolution provides a standard format for data returned upon resolving an intent.\n *\n * ```javascript\n * //resolve a \"Chain\" type intent\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n *\n * //resolve a \"Client-Service\" type intent with a data response or a Channel\n * let resolution = await agent.raiseIntent(\"intentName\", context);\n * try {\n * \t   const result = await resolution.getResult();\n *     if (result && result.broadcast) {\n *         console.log(`${resolution.source} returned a channel with id ${result.id}`);\n *     } else if (result){\n *         console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n *     } else {\n *         console.error(`${resolution.source} didn't return data`\n *     }\n * } catch(error) {\n *     console.error(`${resolution.source} returned an error: ${error}`);\n * }\n *\n * // Use metadata about the resolving app instance to target a further intent\n * await agent.raiseIntent(\"intentName\", context, resolution.source);\n * ```\n */\nexport interface IntentResolution {\n  /**\n   * Identifier for the app instance that was selected (or started) to resolve the intent.\n   * `source.instanceId` MUST be set, indicating the specific app instance that\n   * received the intent.\n   */\n  readonly source: AppIdentifier;\n  /**\n   * The intent that was raised. May be used to determine which intent the user\n   * chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  readonly intent: Intent;\n  /**\n   * Retrieves a promise that will resolve to `Context` data returned\n   * by the application that resolves the raised intent, a `Channel`\n   * established and returned by the app resolving the intent or void.\n   *\n   * A `Channel` returned MAY be of the `PrivateChannel` type. The\n   * client can then `addContextListener()` on that channel to, for example,\n   * receive a stream of data.\n   *\n   * If an error occurs (i.e. an error is thrown by the handler function,\n   * the promise it returns is rejected, or the promise resolved to an invalid\n   * type) then the Desktop Agent MUST reject the promise returned by the\n   * `getResult()` function of the `IntentResolution` with a string from\n   * the `ResultError` enumeration, or (if connected to a Desktop Agent\n   * Bridge) the `BridgingError` enumeration.\n   */\n  getResult(): Promise<IntentResult>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Listener.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nexport interface Listener {\n  /**\n   * Unsubscribe the listener object.\n   */\n  unsubscribe(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Methods.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport {\n  AppIdentifier,\n  AppIntent,\n  Channel,\n  ContextHandler,\n  IntentHandler,\n  IntentResolution,\n  Listener,\n  ImplementationMetadata,\n  AppMetadata,\n  PrivateChannel,\n  Intent,\n  StandardContextType,\n  StandardIntent,\n  ContextType,\n  FDC3EventTypes,\n  EventHandler,\n  DesktopAgent,\n} from '../index.js';\nimport { StandardContextsSet } from '../internal/contextConfiguration.js';\nimport { StandardIntentsSet } from '../internal/intentConfiguration.js';\nimport { Context } from '@finos/fdc3-context';\n\nconst UnavailableError = new Error('FDC3 DesktopAgent not available at `window.fdc3`.');\n\n/**\n * @deprecated This function depends on window.fdc3 (which may not be set for web-based Desktop Agents)\n * and does not wait on the fdc3Ready event, so it may return errors on container-based Desktop Agents.\n * Use `const fdc3 = getAgent()` to retrieve (and wait for) a reference to the FDC3 API instead.\n */\nfunction rejectIfNoGlobal(f: (fdc3: DesktopAgent) => Promise<any>) {\n  return window.fdc3 ? f(window.fdc3) : Promise.reject(UnavailableError);\n}\n\nfunction isString(app: AppIdentifier | string | undefined): app is string {\n  return !!app && typeof app === 'string';\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function open(app: AppIdentifier | string, context?: Context): Promise<AppIdentifier> {\n  if (isString(app)) {\n    return window.fdc3 ? window.fdc3.open(app, context) : Promise.reject(UnavailableError);\n  } else {\n    return window.fdc3 ? window.fdc3.open(app, context) : Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function findIntent(intent: Intent, context?: Context, resultType?: string): Promise<AppIntent> {\n  return window.fdc3 ? window.fdc3.findIntent(intent, context, resultType) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function findIntentsByContext(context: Context, resultType?: string): Promise<AppIntent[]> {\n  return window.fdc3 ? window.fdc3.findIntentsByContext(context, resultType) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function broadcast(context: Context): Promise<void> {\n  return window.fdc3 ? window.fdc3.broadcast(context) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function raiseIntent(intent: Intent, context: Context, app?: AppIdentifier | string): Promise<IntentResolution> {\n  if (isString(app)) {\n    return window.fdc3 ? window.fdc3.raiseIntent(intent, context, app) : Promise.reject(UnavailableError);\n  } else {\n    return window.fdc3 ? window.fdc3.raiseIntent(intent, context, app) : Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function raiseIntentForContext(context: Context, app?: AppIdentifier | string): Promise<IntentResolution> {\n  if (isString(app)) {\n    return window.fdc3 ? window.fdc3.raiseIntentForContext(context, app) : Promise.reject(UnavailableError);\n  } else {\n    return window.fdc3 ? window.fdc3.raiseIntentForContext(context, app) : Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function addIntentListener(intent: Intent, handler: IntentHandler): Promise<Listener> {\n  return window.fdc3 ? window.fdc3.addIntentListener(intent, handler) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function addContextListener(\n  contextTypeOrHandler: ContextType | null | ContextHandler,\n  handler?: ContextHandler\n): Promise<Listener> {\n  //Handle (deprecated) function signature that allowed contextType argument to be omitted\n  if (typeof contextTypeOrHandler !== 'function') {\n    return window.fdc3\n      ? window.fdc3.addContextListener(contextTypeOrHandler, handler as ContextHandler)\n      : Promise.reject(UnavailableError);\n  } else {\n    return window.fdc3\n      ? window.fdc3.addContextListener(null, contextTypeOrHandler as ContextHandler)\n      : Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function addEventListener(eventType: FDC3EventTypes, handler: EventHandler): Promise<Listener> {\n  return rejectIfNoGlobal(fdc3 => fdc3.addEventListener(eventType, handler));\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getUserChannels(): Promise<Channel[]> {\n  if (window.fdc3) {\n    //fallback to getSystemChannels for FDC3 <2.0 implementations\n    if (window.fdc3.getUserChannels) {\n      return window.fdc3.getUserChannels();\n    } else {\n      return window.fdc3.getSystemChannels();\n    }\n  } else {\n    return Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getSystemChannels(): Promise<Channel[]> {\n  //fall-forward to getUserChannels for FDC3 2.0+ implementations\n  return getUserChannels();\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function joinUserChannel(channelId: string): Promise<void> {\n  if (window.fdc3) {\n    //fallback to joinChannel for FDC3 <2.0 implementations\n    if (window.fdc3.joinUserChannel) {\n      return window.fdc3.joinUserChannel(channelId);\n    } else {\n      return window.fdc3.joinChannel(channelId);\n    }\n  } else {\n    return Promise.reject(UnavailableError);\n  }\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function joinChannel(channelId: string): Promise<void> {\n  //fall-forward to joinUserChannel for FDC3 2.0+ implementations\n  return joinUserChannel(channelId);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getOrCreateChannel(channelId: string): Promise<Channel> {\n  return window.fdc3 ? window.fdc3.getOrCreateChannel(channelId) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getCurrentChannel(): Promise<Channel | null> {\n  return window.fdc3 ? window.fdc3.getCurrentChannel() : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function leaveCurrentChannel(): Promise<void> {\n  return window.fdc3 ? window.fdc3.leaveCurrentChannel() : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function createPrivateChannel(): Promise<PrivateChannel> {\n  return window.fdc3 ? window.fdc3.createPrivateChannel() : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getInfo(): Promise<ImplementationMetadata> {\n  return window.fdc3 ? window.fdc3.getInfo() : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function getAppMetadata(app: AppIdentifier): Promise<AppMetadata> {\n  return window.fdc3 ? window.fdc3.getAppMetadata(app) : Promise.reject(UnavailableError);\n}\n\n/**\n * @deprecated Importing individual FDC3 API calls is deprecated. Use `getAgent` to retrieve\n * an FDC3 API reference and use the functions that it provides instead.\n */\nexport function findInstances(app: AppIdentifier): Promise<AppIdentifier[]> {\n  return window.fdc3 ? window.fdc3.findInstances(app) : Promise.reject(UnavailableError);\n}\n\n/**\n * Check if the given context is a standard context type.\n * @param contextType\n */\nexport function isStandardContextType(contextType: ContextType): contextType is StandardContextType {\n  return StandardContextsSet.has(contextType as StandardContextType);\n}\n\n/**\n * Check if the given intent is a standard intent.\n * @param intent\n */\nexport function isStandardIntent(intent: Intent): intent is StandardIntent {\n  return StandardIntentsSet.has(intent as StandardIntent);\n}\n\n/**\n * Compare numeric semver version number strings (in the form `1.2.3`).\n *\n * Returns `-1` if the first argument is a lower version number than the second,\n * `1` if the first argument is greater than the second, 0 if the arguments are\n * equal and `null` if an error occurred during the comparison.\n *\n * @param a\n * @param b\n */\nexport const compareVersionNumbers: (a: string, b: string) => number | null = (a, b) => {\n  try {\n    const aVerArr = a.split('.').map(Number);\n    const bVerArr = b.split('.').map(Number);\n    for (let index = 0; index < Math.max(aVerArr.length, bVerArr.length); index++) {\n      /* If one version number has more digits and the other does not, and they are otherwise equal,\n         assume the longer is greater. E.g. 1.1.1 > 1.1 */\n      if (index === aVerArr.length || aVerArr[index] < bVerArr[index]) {\n        return -1;\n      } else if (index === bVerArr.length || aVerArr[index] > bVerArr[index]) {\n        return 1;\n      }\n    }\n    return 0;\n  } catch (e) {\n    console.error('Failed to compare version strings', e);\n    return null;\n  }\n};\n\n/**\n * Check if the FDC3 version in an ImplementationMetadata object is greater than\n * or equal to the supplied numeric semver version number string (in the form `1.2.3`).\n *\n * Returns a boolean or null if an error occurred while comparing the version numbers.\n *\n * @param metadata\n * @param version\n */\nexport const versionIsAtLeast: (metadata: ImplementationMetadata, version: string) => boolean | null = (\n  metadata,\n  version\n) => {\n  const comparison = compareVersionNumbers(metadata.fdc3Version, version);\n  return comparison === null ? null : comparison >= 0 ? true : false;\n};\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/PrivateChannel.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright 2021 FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { Listener } from './Listener.js';\nimport { Channel } from './Channel.js';\nimport { EventHandler, PrivateChannelEventTypes } from './Events.js';\n\n/**\n * Object representing a private context channel, which is intended to support\n * secure communication between applications, and extends the Channel interface\n * with event handlers which provide information on the connection state of both\n * parties, ensuring that desktop agents do not need to queue or retain messages\n * that are broadcast before a context listener is added and that applications\n * are able to stop broadcasting messages when the other party has disconnected.\n *\n * It is intended that Desktop Agent implementations:\n * - SHOULD restrict external apps from listening or publishing on this channel.\n * - MUST prevent private channels from being retrieved via fdc3.getOrCreateChannel.\n * - MUST provide the `id` value for the channel as required by the Channel interface.\n */\nexport interface PrivateChannel extends Channel {\n  /**\n   * Register a handler for events from the PrivateChannel. Whenever the handler function\n   * is called it will be passed an event object with details related to the event.\n   *\n   * ```js\n   * // any event type\n   * const listener = await myPrivateChannel.addEventListener(null, event => {\n   *   console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n   * });\n   *\n   * // listener for a specific event type\n   * const channelChangedListener = await myPrivateChannel.addEventListener(\n   *    \"addContextListener\",\n   *    event => { ... }\n   * );\n   * ```\n   *\n   * @param {PrivateChannelEventType | null} type If non-null, only events of the specified type will be received by the handler.\n   * @param {EventHandler} handler A function that events received will be passed to.\n   *\n   */\n  addEventListener(type: PrivateChannelEventTypes | null, handler: EventHandler): Promise<Listener>;\n\n  /**\n   * May be called to indicate that a participant will no longer interact with this channel.\n   *\n   * After this function has been called, Desktop Agents SHOULD prevent apps from broadcasting\n   * on this channel and MUST automatically call Listener.unsubscribe() for each listener that\n   * they've added (causing any onUnsubscribe handler added by the other party to be called)\n   * before triggering any onDisconnect handler added by the other party.\n   */\n  disconnect(): Promise<void>;\n\n  //---------------------------------------------------------------------------------------------\n  //Deprecated function signatures\n  //---------------------------------------------------------------------------------------------\n\n  /**\n   * @deprecated use `addEventListener(\"addContextListener\", handler)` instead.\n   *\n   * Adds a listener that will be called each time that the remote app invokes\n   * addContextListener on this channel.\n   *\n   * Desktop Agents MUST call this for each invocation of addContextListener on this\n   * channel, including those that occurred before this handler was registered\n   * (to prevent race conditions).\n   */\n  onAddContextListener(handler: (contextType?: string) => void): Listener;\n\n  /**\n   * @deprecated use `addEventListener(\"unsubscribe\", handler)` instead.\n   *\n   * Adds a listener that will be called whenever the remote app invokes\n   * Listener.unsubscribe() on a context listener that it previously added.\n   *\n   * Desktop Agents MUST call this when disconnect() is called by the other party, for\n   * each listener that they have added.\n   */\n  onUnsubscribe(handler: (contextType?: string) => void): Listener;\n\n  /**\n   * @deprecated use `addEventListener(\"disconnect\", handler)` instead.\n   *\n   * Adds a listener that will be called when the remote app terminates, for example\n   * when its window is closed or because disconnect was called. This is in addition\n   * to calls that will be made to onUnsubscribe listeners.\n   */\n  onDisconnect(handler: () => void): Listener;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/RecommendedChannels.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { DisplayMetadata } from './DisplayMetadata.js';\n\n/** Interface representing the data fields of a user channel, without the functions. */\ninterface UserChannelTemplate {\n  readonly id: string;\n  readonly type: 'user';\n  readonly displayMetadata?: DisplayMetadata;\n}\n\nconst recommendedChannels: Array<UserChannelTemplate> = [\n  {\n    id: 'fdc3.channel.1',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 1',\n      color: 'red',\n      glyph: '1',\n    },\n  },\n  {\n    id: 'fdc3.channel.2',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 2',\n      color: 'orange',\n      glyph: '2',\n    },\n  },\n  {\n    id: 'fdc3.channel.3',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 3',\n      color: 'yellow',\n      glyph: '3',\n    },\n  },\n  {\n    id: 'fdc3.channel.4',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 4',\n      color: 'green',\n      glyph: '4',\n    },\n  },\n  {\n    id: 'fdc3.channel.5',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 5',\n      color: 'cyan',\n      glyph: '5',\n    },\n  },\n  {\n    id: 'fdc3.channel.6',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 6',\n      color: 'blue',\n      glyph: '6',\n    },\n  },\n  {\n    id: 'fdc3.channel.7',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 7',\n      color: 'magenta',\n      glyph: '7',\n    },\n  },\n  {\n    id: 'fdc3.channel.8',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 8',\n      color: 'purple',\n      glyph: '8',\n    },\n  },\n];\n\nexport default recommendedChannels;\n"
  },
  {
    "path": "packages/fdc3-standard/src/api/Types.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { Context } from '@finos/fdc3-context';\nimport { Channel } from './Channel.js';\nimport { ContextMetadata } from './ContextMetadata.js';\n\n/**\n * Describes a callback that handles a context event.\n * Used when attaching listeners for context broadcasts.\n *\n * Optional metadata about the context message, including the app that originated\n * the message, SHOULD be provided by the desktop agent implementation.\n */\nexport type ContextHandler = (context: Context, metadata?: ContextMetadata) => void;\n/**\n * Intents can return results that are either context data objects\n * or a reference to a Channel.\n */\nexport type IntentResult = Context | Channel | void;\n/**\n * Describes a callback that handles a context event and may return a\n * promise of a Context, Channel object or void to be returned to the\n * application that raised the intent.\n * Used when attaching listeners for raised intents.\n *\n * Optional metadata about the raised intent, including the app that originated\n * the message, SHOULD be provided by the desktop agent implementation.\n */\nexport type IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise<IntentResult> | void;\n"
  },
  {
    "path": "packages/fdc3-standard/src/app-directory/specification/appd.schema.json",
    "content": "{\n\t\"openapi\": \"3.0.0\",\n\t\"info\": {\n\t  \"title\": \"FDC3 Application Directory\",\n\t  \"version\": \"next\",\n\t  \"description\": \"Application Directory specification providing both interface definition and objects necessary to construct an application directory service.\",\n\t  \"x-logo\": {\n\t\t\"url\": \"/img/fdc3-logo-2019-color.png\",\n\t\t\"altText\": \"FDC3 logo\"\n\t  }\n\t},\n\t\"security\": [\n\t  {\n\t\t\"bearerAuth\": []\n\t  }\n\t],\n\t\"paths\": {\n\t  \"/v2/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"MyAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/MyAppDefinition\"\n\t\t\t\t\t},\n\t\t\t\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/FDC3WorkbenchAppDefinition\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v2/apps\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve all application definitions\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/AllApplicationsResponse\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"AllAppsResponse\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/AllAppsResponse\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps\": {\n\t\t\"post\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Create a new application definition\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ],\n\t\t  \"requestBody\": {\n\t\t\t\"content\": {\n\t\t\t  \"application/json\": {\n\t\t\t\t\"schema\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"required\": true\n\t\t  }\n\t\t}\n\t  },\n\t  \"/v1/apps/search\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter values should self describe search format and type (e.g. Regex)\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"version\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"title\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"tooltip\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"description\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"name of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_displayName\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"displayName of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_context\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"search contexts list\"\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  }\n\t},\n\t\"servers\": [\n\t  {\n\t\t\"url\": \"/appd\"\n\t  }\n\t],\n\t\"components\": {\n\t  \"securitySchemes\": {\n\t\t\"bearerAuth\": {\n\t\t  \"type\": \"http\",\n\t\t  \"scheme\": \"bearer\",\n\t\t  \"bearerFormat\": \"JWT\"\n\t\t}\n\t  },\n\t  \"schemas\": {\n\t\t\"ErrorDTO\": {\n\t\t  \"type\": \"object\",\n\t\t  \"properties\": {\n\t\t\t\"code\": {\n\t\t\t  \"type\": \"integer\",\n\t\t\t  \"format\": \"int32\"\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"BaseApplication\": {\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Title for the application, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Type\"\n\t\t\t},\n\t\t\t\"details\": {\n\t\t\t  \"$ref\": \"#/components/schemas/LaunchDetails\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Deprecated in favour of using `appId` to identify apps and `title` for their display names. The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"lang\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"pattern\": \"^[a-z]{2}(-[a-zA-Z0-9]{2,8}){0,1}$\",\n\t\t\t  \"description\": \"A language tag that specifies the primary language of both the application and its AppD entry, as defined by IETF RFC 5646.\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. \"\n\t\t\t},\n\t\t\t\"categories\": {\n\t\t\t  \"description\": \"An array of string categories that describe the application. These are meant as a hint to catalogs or stores listing FDC3-enabled apps and it is expected that these will make a best effort to find appropriate categories (or category) under which to list the app. AppD record authors are encouraged to use lower-case and, where possible, to select categories from the following list:\\n\\n- allocations\\n- analytics\\n- charts\\n- chat\\n- communication\\n- compliance\\n- crm\\n- developer tools\\n- events\\n- execution management\\n- file sharing\\n- market data\\n- news\\n- networking\\n- office apps\\n- order management\\n- other\\n- portfolio management\\n- presentation\\n- pricing\\n- productivity\\n- research\\n- risk\\n- screen sharing\\n- security\\n- spreadsheet\\n- trade cost analysis\\n- trading system\\n- training\\n- travel\\n- video\\n- visualization\\n- weather\\n\",\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Icon\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"screenshots\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Screenshot\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"moreInfo\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Optional URL that provides more information about the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher. Deprecated due to a lack of a standard means of retrieval via the Desktop Agent API. To be replaced in a future version with an `applicationConfig` element and standard API to retrieve it. See issue  [#1006](https://github.com/finos/FDC3/issues/1006) for details.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"$ref\": \"#/components/schemas/HostManifests\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Interop\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Application\": {\n\t\t  \"description\": \"Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"title\",\n\t\t\t\"type\",\n\t\t\t\"details\"\n\t\t  ],\n\t\t  \"allOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/LocalizedVersions\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"AllApplicationsResponse\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"NameValuePair\": {\n\t\t  \"description\": \"Simple name value pair\",\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"name\"\n\t\t\t},\n\t\t\t\"value\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"value\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Icon\": {\n\t\t  \"description\": \"Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Icon dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t    \"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Screenshot\": {\n\t\t  \"description\": \"Images representing the app in common usage scenarios\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional caption for the image\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t\t\"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Type\": {\n\t\t  \"type\": \"string\",\n\t\t  \"description\": \"The technology type that is used to launch and run the application. Each application type implies a particular set of launch `details`.\\nThe supported types include:\\n\\n- `web`: Web applications launched via a URL\\n- `native`: Native applications pre-installed on a device and launch via a filesystem path\\n- `citrix`: Apps virtualized via Citrix\\n- `onlineNative`: Native apps that have an online launcher, e.g. online ClickOnce app deployments.\\n- `other`: Used to represent apps that do not conform to or cannot be launched via the other types, and are likely to be defined solely by a hostManifest.\\n\\nFDC3 Desktop Agents MUST support at least the `web` application type and MAY support any or all of the other types.\",\n\t\t  \"enum\": [\n\t\t\t\"web\",\n\t\t\t\"native\",\n\t\t\t\"citrix\",\n\t\t\t\"onlineNative\",\n\t\t\t\"other\"\n\t\t  ]\n\t\t},\n\t\t\"LaunchDetails\": {\n\t\t  \"description\": \"The type specific launch details of the application. These details are intended to be vendor-agnostic and MAY be duplicated or overridden by details provided in the hostManifests object for a specific host.\",\n\t\t  \"anyOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/WebAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/NativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/CitrixAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OnlineNativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OtherAppDetails\"\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"WebAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps with `type: web`.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application start URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"NativeAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps with `type: native` that are already installed on the device.\",\n\t\t  \"required\": [\n\t\t\t\"path\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"path\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The path on disk from which the application is launched.\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"CitrixAppDetails\": {\n\t      \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps virtualized apps with `type: citrix`.\",\n\t\t  \"required\": [\n\t\t\t\"alias\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"alias\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The Citrix alias / name of the virtual app (passed to the Citrix SelfService qlaunch parameter).\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OnlineNativeAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch a native apps with `type: onlineNative` that have an online launcher, e.g. online ClickOnce app deployments.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OtherAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Apps with `type: other` are defined by a hostManifest and do not require other details.\",\n\t\t  \"properties\": {},\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"HostManifests\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"A mapping from host name to a host-specific application manifest object or URI from which that manifest can be retrieved. The manifest should provide details required to launch and use the application within the specified host. The manifest _MAY_ duplicate or  override information provided in the `details` field.\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Host name\",\n\t\t\t\"oneOf\": [\n\t\t\t  {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"format\": \"uri\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"$ref\": \"#/components/schemas/HostManifest\"\n\t\t\t  }\n\t\t\t]\n\t\t  }\n\t\t},\n\t\t\"HostManifest\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Object containing all host specific properties.\"\n\t\t},\n\t\t\"LocalizedVersions\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Provides localized alternatives to any field of the AppD record, which may also refer to an alternative version of the application that is also localized (e.g. by providing an alternative URL).  The keys to this object should be language tags as defined by IETF RFC 5646, e.g. en, en-GB or fr-FR.\\n\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Language tag\",\n\t\t\t\"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t  }\n\t\t},\n\t\t\"Intent\": {\n\t\t  \"description\": \"Definition of an intent that an app listens for\",\n\t\t  \"required\": [\n\t\t\t\"contexts\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional display name for the intent. Deprecated in favour of the intent name, which is common amongst all apps that support it, where the display name may vary as it is defined in the app's AppD record.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"resultType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional type for output returned by the application, if any, when resolving this intent. May indicate a context type by type name (e.g. \\\"fdc3.instrument\\\"), a channel (e.g. \\\"channel\\\") or a combination that indicates a channel that returns a particular context type (e.g. \\\"channel<fdc3.instrument>\\\").\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Interop\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Metadata that describes how the application uses FDC3 APIs. This metadata serves multiple purposes:\\n\\n- It supports intent resolution by a desktop agent, by declaring what intents an app listens for.\\n- It may be used, for example in an app catalog UI, to find apps that 'interoperate with' other apps. \\n- It provides a standard location to document how the app interacts with user channels, app channels, and intents, for use by other app developers and desktop assemblers.\",\n\t\t  \"properties\": {\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the app's interactions with intents.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intents names that an app listens for via `fdc3.addIntentListener()` to their configuration. \\n\\nUsed to support intent resolution by desktop agents. Replaces the `intents` element used in appD records prior to FDC3 2.0.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Intent\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intent names that an app raises (via `fdc3.raiseIntent`) to an array of context type names that it may be raised with.\\n\\nUse the intent name \\\"any\\\" to represent use of the `fdc3.raiseIntentForContext` and `fdc3.findIntentForContext` functions, which allow the user to select from intents available for a specified context type.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the intent may be raised with.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"userChannels\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the application's use of context types on User Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"broadcasts\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that are broadcast by the application.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that the application listens for.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"appChannels\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Describes the application's use of App Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": [\n\t\t\t\t  \"id\"\n\t\t\t\t],\n\t\t\t\t\"properties\": {\n\t\t\t\t  \"id\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The id of the App Channel. N.b. in FDC3 2.0 this field was incorrectly called `name`.\"\n\t\t\t\t  },\n\t\t\t\t  \"description\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"A description of how the channel is used.\"\n\t\t\t\t  },\n\t\t\t\t  \"broadcasts\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that are broadcast by the application on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"listensFor\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the application listens for on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"AppImageV1\": {\n\t\t  \"description\": \"App Image holder\",\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IconV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"icon\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IntentV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) An intent definition as defined by spec https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t  \"required\": [\n\t\t\t\"name\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the intent to 'launch'. In this case the name of an Intent supported by an application.\"\n\t\t\t},\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional display name for the intent that may be used in UI instead of the name.\"\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"name\",\n\t\t\t\"manifest\",\n\t\t\t\"manifestType\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t\"manifest\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"URI or full JSON of the application manifest providing all details related to launch and use requirements as described by the vendor. The format of this manifest is vendor specific, but can be identified by the manifestType attribute.\"\n\t\t\t},\n\t\t\t\"manifestType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The manifest type which relates to the format and structure of the manifest content. The definition is based on the vendor specific format and definition outside of this specification.\"\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t\"images\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/AppImageV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IconV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"The list of intents implemented by the application as defined by https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IntentV1\"\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationSearchResponseV1\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t}\n\t  },\n\t  \"examples\": {\n\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\"categories\": [\n\t\t\t  \"developer tools\",\n\t\t\t  \"training\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"https://fdc3.finos.org\",\n\t\t\t\"publisher\": \"FDC3\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 640,\n\t\t\t\t  \"width\": 560,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 800,\n\t\t\t\t  \"height\": 750,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition for the FDC3 Workbench\"\n\t\t},\n\t\t\"MyAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"my-application\",\n\t\t\t\"title\": \"My Application\",\n\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\"categories\": [\n\t\t\t  \"market data\",\n\t\t\t  \"research\",\n\t\t\t  \"news\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\"type\": \"image/png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"intents\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t],\n\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t  ],\n\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"userChannels\": {\n\t\t\t\t\"broadcasts\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t],\n\t\t\t\t\"listensFor\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t]\n\t\t\t  },\n\t\t\t  \"appChannels\": [\n\t\t\t\t{\n\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t  ],\n\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition that describes the app's use of interop.\"\n\t\t},\n\t\t\"AllAppsResponse\": {\n\t\t  \"value\": {\n\t\t\t\"applications\": [\n\t\t\t  {\n\t\t\t\t\"appId\": \"my-application\",\n\t\t\t\t\"title\": \"My Application\",\n\t\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"market data\",\n\t\t\t\t  \"research\",\n\t\t\t\t  \"news\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\t\"type\": \"image/png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  },\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t]\n\t\t\t\t\t  },\n\t\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"raises\": {\n\t\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"userChannels\": {\n\t\t\t\t\t\"broadcasts\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t],\n\t\t\t\t\t\"listensFor\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"appChannels\": [\n\t\t\t\t\t{\n\t\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  ]\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"developer tools\",\n\t\t\t\t  \"training\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png,\",\n\t\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"publisher\": \"FDC3,\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 640,\n\t\t\t\t\t  \"width\": 560,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 800,\n\t\t\t\t\t  \"height\": 750,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t],\n\t\t\t\"message\": \"OK\"\n\t\t  },\n\t\t  \"summary\": \"A sample 'all applications' listing response\"\n\t\t},\n\t\t\"Error400Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 400,\n\t\t\t\"message\": \"There was an error in your request.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Bad Request error.\"\n\t\t},\n\t\t\"Error403Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 403,\n\t\t\t\"message\": \"Certificate authentication failed for the requested user.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Forbidden error.\"\n\t\t},\n\t\t\"Error500Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 500,\n\t\t\t\"message\": \"An internal server error occurred. See the response body for further details.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Server error.\"\n\t\t}\n\t  }\n\t}\n  }"
  },
  {
    "path": "packages/fdc3-standard/src/app-directory/specification/examples/application/fdc3-workbench.json",
    "content": "{\n  \"appId\": \"fdc3-workbench\",\n  \"name\": \"fdc3-workbench\",\n  \"title\": \"FDC3 Workbench\",\n  \"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n  \"categories\": [\n    \"developer tools\",\n    \"training\"\n  ],\n  \"version\": \"1.0.0\",\n  \"tooltip\": \"FDC3 Workbench\",\n  \"lang\": \"en-US\",\n  \"icons\": [\n    {\n      \"src\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n    }\n  ],\n  \"screenshots\": [\n    {\n      \"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n      \"label\": \"FDC3 logo\"\n    }\n  ],\n  \"contactEmail\": \"fdc3@finos.org\",\n  \"supportEmail\": \"fdc3-maintainers@finos.org\",\n  \"publisher\": \"FDC3,\",\n  \"type\": \"web\",\n  \"details\": {\n    \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n  },\n  \"hostManifests\": {\n    \"Glue42\": {\n      \"type\": \"window\",\n      \"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n      \"details\": {\n        \"height\": 640,\n        \"width\": 560,\n        \"left\": 120,\n        \"top\": 120,\n        \"mode\": \"tab\",\n        \"allowChannels\": true,\n        \"loader\": {\n          \"enabled\": true,\n          \"hideOnLoad\": true\n        }\n      },\n      \"customProperties\": {\n        \"folder\": \"FDC3 Toolbox\"\n      }\n    },\n    \"Finsemble\": {\n      \"window\": {\n        \"left\": 120,\n        \"top\": 120,\n        \"width\": 800,\n        \"height\": 750,\n        \"options\": {\n          \"minWidth\": 75\n        }\n      },\n      \"foreign\": {\n        \"components\": {\n          \"App Launcher\": {\n            \"launchableByUser\": true\n          },\n          \"Toolbar\": {\n            \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n          },\n          \"Window Manager\": {\n            \"FSBLHeader\": true,\n            \"persistWindowState\": true\n          }\n        }\n      },\n      \"interop\": {\n        \"autoConnect\": true\n      }\n    },\n    \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n  },\n  \"localizedVersions\": {\n    \"fr-FR\": {\n      \"title\": \"FDC3 Table de travail\",\n      \"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/app-directory/specification/examples/application/myApplication.json",
    "content": "{\n\t\"appId\": \"my-application\",\n\t\"name\": \"my-application\",\n\t\"title\": \"My Application\",\n\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\"categories\": [\n\t  \"market data\",\n\t  \"research\",\n\t  \"news\"\n\t],\n\t\"version\": \"1.0.0\",\n\t\"tooltip\": \"My example application definition\",\n\t\"lang\": \"en-US\",\n\t\"icons\": [\n\t  {\n\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\"size\": \"256x256\",\n\t\t\"type\": \"image/png\"\n\t  }\n\t],\n\t\"screenshots\": [\n\t  {\n\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\"type\": \"image/png\",\n\t\t\"size\": \"800x600\"\n\t  },\n\t  {\n\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\"type\": \"image/png\",\n\t\t\"size\": \"800x600\"\n\t  }\n\t],\n\t\"contactEmail\": \"fdc3@finos.org\",\n\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\"moreInfo\": \"http://example.domain.com/\",\n\t\"publisher\": \"Example App, Inc.\",\n\t\"type\": \"web\",\n\t\"details\": {\n\t  \"url\": \"http://example.domain.com/app.html\"\n\t},\n\t\"hostManifests\": {\n\t  \"Finsemble\": {\n\t\t\"window\": {\n\t\t  \"left\": 120,\n\t\t  \"top\": 120,\n\t\t  \"width\": 600,\n\t\t  \"height\": 800,\n\t\t  \"options\": {\n\t\t\t\"minWidth\": 75\n\t\t  }\n\t\t},\n\t\t\"foreign\": {\n\t\t  \"components\": {\n\t\t\t\"App Launcher\": {\n\t\t\t  \"launchableByUser\": true\n\t\t\t},\n\t\t\t\"Window Manager\": {\n\t\t\t  \"FSBLHeader\": true,\n\t\t\t  \"persistWindowState\": true\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"interop\": {\n\t\t  \"autoConnect\": true\n\t\t}\n\t  },\n\t  \"Glue42\": {\n\t\t\"type\": \"window\",\n\t\t\"details\": {\n\t\t  \"height\": 800,\n\t\t  \"width\": 600,\n\t\t  \"left\": 120,\n\t\t  \"top\": 120,\n\t\t  \"mode\": \"tab\",\n\t\t  \"allowChannels\": true,\n\t\t  \"loader\": {\n\t\t\t\"enabled\": true,\n\t\t\t\"hideOnLoad\": true\n\t\t  }\n\t\t},\n\t\t\"customProperties\": {\n\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t}\n\t  },\n\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t},\n\t\"interop\": {\n\t  \"intents\": {\n\t\t\"listensFor\": {\n\t\t  \"ViewChart\": {\n\t\t\t\"displayName\": \"View Chart\",\n\t\t\t\"contexts\": [\n\t\t\t  \"fdc3.instrument\"\n\t\t\t]\n\t\t  },\n\t\t  \"myApp.GetPrice\": {\n\t\t\t\"displayName\": \"Get Price\",\n\t\t\t\"contexts\": [\n\t\t\t  \"fdc3.instrument\"\n\t\t\t],\n\t\t\t\"resultType\": \"myApp.quote\"\n\t\t  }\n\t\t},\n\t\t\"raises\": {\n\t\t  \"ViewOrders\": [\n\t\t\t\"fdc3.instrument\",\n\t\t\t\"fdc3.organization\"\n\t\t  ],\n\t\t  \"StartEmail\": [\n\t\t\t\"fdc3.email\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"userChannels\": {\n\t\t\"broadcasts\": [\n\t\t  \"fdc3.instrument\",\n\t\t  \"fdc3.organization\"\n\t\t],\n\t\t\"listensFor\": [\n\t\t  \"fdc3.instrument\",\n\t\t  \"fdc3.organization\"\n\t\t]\n\t  },\n\t  \"appChannels\": [\n\t\t{\n\t\t  \"id\": \"myApp.quotes,\",\n\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t  \"broadcasts\": [\n\t\t\t\"myApp.quote\"\n\t\t  ],\n\t\t  \"listensFor\": [\n\t\t\t\"fdc3.instrument\"\n\t\t  ]\n\t\t}\n\t  ]\n\t},\n\t\"localizedVersions\": {\n\t  \"fr-FR\": {\n\t\t\"title\": \"Mon application,\",\n\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t  }\n\t}\n  }"
  },
  {
    "path": "packages/fdc3-standard/src/context/ContextType.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * @see https://fdc3.finos.org/docs/context/spec#standard-context-types\n */\nexport type StandardContextType =\n  | 'fdc3.action'\n  | 'fdc3.chart'\n  | 'fdc3.chat.initSettings'\n  | 'fdc3.chat.message'\n  | 'fdc3.chat.room'\n  | 'fdc3.chat.searchCriteria'\n  | 'fdc3.contact'\n  | 'fdc3.contactList'\n  | 'fdc3.country'\n  | 'fdc3.currency'\n  | 'fdc3.email'\n  | 'fdc3.fileAttachment'\n  | 'fdc3.instrument'\n  | 'fdc3.instrumentList'\n  | 'fdc3.interaction'\n  | 'fdc3.message'\n  | 'fdc3.nothing'\n  | 'fdc3.organization'\n  | 'fdc3.portfolio'\n  | 'fdc3.position'\n  | 'fdc3.timeRange'\n  | 'fdc3.transactionResult'\n  | 'fdc3.valuation';\n\n/**\n * @see https://fdc3.finos.org/docs/context/spec#standard-context-types\n */\nexport type ExperimentalContextType =\n  | 'fdc3.order'\n  | 'fdc3.orderList'\n  | 'fdc3.product'\n  | 'fdc3.trade'\n  | 'fdc3.tradeList';\n\n/**\n * @see https://fdc3.finos.org/docs/context/spec\n */\nexport type ContextType = StandardContextType | ExperimentalContextType | (string & {});\n\n/**\n * @deprecated Use {@link StandardContextType} instead\n */\nexport enum ContextTypes {\n  Action = 'fdc3.action',\n  Chart = 'fdc3.chart',\n  ChatInitSettings = 'fdc3.chat.initSettings',\n  ChatMessage = 'fdc3.chat.message',\n  ChatRoom = 'fdc3.chat.room',\n  ChatSearchCriteria = 'fdc3.chat.searchCriteria',\n  Contact = 'fdc3.contact',\n  ContactList = 'fdc3.contactList',\n  Country = 'fdc3.country',\n  Currency = 'fdc3.currency',\n  Email = 'fdc3.email',\n  FileAttachment = 'fdc3.fileAttachment',\n  Instrument = 'fdc3.instrument',\n  InstrumentList = 'fdc3.instrumentList',\n  Interaction = 'fdc3.interaction',\n  Message = 'fdc3.message',\n  Nothing = 'fdc3.nothing',\n  Order = 'fdc3.order',\n  OrderList = 'fdc3.orderList',\n  Organization = 'fdc3.organization',\n  Portfolio = 'fdc3.portfolio',\n  Position = 'fdc3.position',\n  Product = 'fdc3.product',\n  TimeRange = 'fdc3.timeRange',\n  Trade = 'fdc3.trade',\n  TradeList = 'fdc3.tradeList',\n  TransactionResult = 'fdc3.transactionResult',\n  Valuation = 'fdc3.valuation',\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/index.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright 2019 FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { DesktopAgent } from './api/DesktopAgent.js';\n\n//explicit overwrite of conflicting & equivalent export from ContextTypes\nexport { AppIdentifier } from './api/AppIdentifier.js';\nexport * from './api/AppIntent.js';\nexport * from './api/AppMetadata.js';\nexport * from './api/Channel.js';\nexport * from './api/ContextMetadata.js';\nexport * from './api/DesktopAgent.js';\nexport * from './api/DisplayMetadata.js';\nexport * from './api/Errors.js';\nexport * from './api/GetAgent.js';\nexport * from './api/Icon.js';\nexport * from './api/Image.js';\nexport * from './api/ImplementationMetadata.js';\nexport * from './api/IntentMetadata.js';\nexport * from './api/IntentResolution.js';\nexport * from './api/Listener.js';\nexport * from './api/Methods.js';\nexport * from './api/PrivateChannel.js';\nexport * from './api/RecommendedChannels.js';\nexport * from './api/Types.js';\nexport * from './api/Events.js';\nexport * from './api/GetAgent.js';\nexport * from './context/ContextType.js';\nexport * from './intents/Intents.js';\nexport * from './ui/IntentResolver.js';\nexport * from './ui/ChannelSelector.js';\nexport * from './ui/Connectable.js';\n\nexport const FDC3_VERSION = '2.2';\n\ndeclare global {\n  interface Window {\n    fdc3?: DesktopAgent;\n  }\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/intents/Intents.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/**\n * @see https://fdc3.finos.org/docs/intents/spec#standard-intents\n */\nexport type StandardIntent =\n  | 'CreateInteraction'\n  | 'CreateOrUpdateProfile'\n  | 'SendChatMessage'\n  | 'StartCall'\n  | 'StartChat'\n  | 'StartEmail'\n  | 'ViewAnalysis'\n  | 'ViewChat'\n  | 'ViewChart'\n  | 'ViewContact'\n  | 'ViewHoldings'\n  | 'ViewInstrument'\n  | 'ViewInteractions'\n  | 'ViewMessages'\n  | 'ViewNews'\n  | 'ViewOrders'\n  | 'ViewProfile'\n  | 'ViewQuote'\n  | 'ViewResearch';\n\n/**\n * @see https://fdc3.finos.org/docs/intents/spec\n */\nexport type Intent = StandardIntent | (string & {});\n\n/**\n * @deprecated Use {@link StandardIntent} instead\n */\nexport enum Intents {\n  CreateInteraction = 'CreateInteraction',\n  CreateOrUpdateProfile = 'CreateOrUpdateProfile',\n  SendChatMessage = 'SendChatMessage',\n  StartCall = 'StartCall',\n  StartChat = 'StartChat',\n  StartEmail = 'StartEmail',\n  ViewAnalysis = 'ViewAnalysis',\n  ViewChat = 'ViewChat',\n  ViewChart = 'ViewChart',\n  ViewContact = 'ViewContact',\n  ViewHoldings = 'ViewHoldings',\n  ViewInstrument = 'ViewInstrument',\n  ViewInteractions = 'ViewInteractions',\n  ViewMessages = 'ViewMessages',\n  ViewNews = 'ViewNews',\n  ViewOrders = 'ViewOrders',\n  ViewProfile = 'ViewProfile',\n  ViewQuote = 'ViewQuote',\n  ViewResearch = 'ViewResearch',\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/intents/standard intents.json",
    "content": "{\n  \"intents\": [\n    \"CreateInteraction\",\n    \"CreateOrUpdateProfile\",\n    \"SendChatMessage\",\n    \"StartCall\",\n    \"StartChat\",\n    \"StartEmail\",\n    \"ViewAnalysis\",\n    \"ViewChat\",\n    \"ViewChart\",\n    \"ViewContact\",\n    \"ViewHoldings\",\n    \"ViewInstrument\",\n    \"ViewInteractions\",\n    \"ViewMessages\",\n    \"ViewNews\",\n    \"ViewOrders\",\n    \"ViewProfile\",\n    \"ViewQuote\",\n    \"ViewResearch\"\n  ]\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/internal/contextConfiguration.ts",
    "content": "import { StandardContextType } from '../context/ContextType.js';\nimport { exhaustiveStringTuple } from './typeHelpers.js';\n\nconst STANDARD_CONTEXT_TYPES = exhaustiveStringTuple<StandardContextType>()(\n  'fdc3.action',\n  'fdc3.chart',\n  'fdc3.chat.initSettings',\n  'fdc3.chat.message',\n  'fdc3.chat.room',\n  'fdc3.chat.searchCriteria',\n  'fdc3.contact',\n  'fdc3.contactList',\n  'fdc3.country',\n  'fdc3.currency',\n  'fdc3.email',\n  'fdc3.fileAttachment',\n  'fdc3.instrument',\n  'fdc3.instrumentList',\n  'fdc3.interaction',\n  'fdc3.message',\n  'fdc3.nothing',\n  'fdc3.organization',\n  'fdc3.portfolio',\n  'fdc3.position',\n  'fdc3.timeRange',\n  'fdc3.transactionResult',\n  'fdc3.valuation'\n);\n\n// used internally to check if a given intent/context is a standard one\nexport const StandardContextsSet = new Set(STANDARD_CONTEXT_TYPES);\n"
  },
  {
    "path": "packages/fdc3-standard/src/internal/intentConfiguration.ts",
    "content": "import { StandardIntent } from '../intents/Intents.js';\nimport { exhaustiveStringTuple } from './typeHelpers.js';\n\nconst STANDARD_INTENTS = exhaustiveStringTuple<StandardIntent>()(\n  'CreateInteraction',\n  'CreateOrUpdateProfile',\n  'SendChatMessage',\n  'StartCall',\n  'StartChat',\n  'StartEmail',\n  'ViewAnalysis',\n  'ViewChat',\n  'ViewChart',\n  'ViewContact',\n  'ViewHoldings',\n  'ViewInstrument',\n  'ViewInteractions',\n  'ViewMessages',\n  'ViewNews',\n  'ViewOrders',\n  'ViewProfile',\n  'ViewQuote',\n  'ViewResearch'\n);\n\n// used internally to check if a given intent/context is a standard one\nexport const StandardIntentsSet = new Set(STANDARD_INTENTS);\n"
  },
  {
    "path": "packages/fdc3-standard/src/internal/typeHelpers.ts",
    "content": "type AtLeastOne<T> = [T, ...T[]];\n\n/**\n * Ensures at compile time that the given string tuple is exhaustive on a given union type, i.e. contains ALL possible values of the given UNION_TYPE.\n */\nexport const exhaustiveStringTuple =\n  <UNION_TYPE extends string>() =>\n  <L extends AtLeastOne<UNION_TYPE>>(\n    ...tuple: L extends any\n      ? Exclude<UNION_TYPE, L[number]> extends never\n        ? L\n        : Exclude<UNION_TYPE, L[number]>[]\n      : never\n  ) =>\n    tuple;\n"
  },
  {
    "path": "packages/fdc3-standard/src/ui/ChannelSelector.ts",
    "content": "import { Channel } from '../api/Channel.js';\nimport { Connectable } from '../ui/Connectable.js';\n\n/**\n * Interface used by the desktop agent proxy to handle the channel selection process.\n */\nexport interface ChannelSelector extends Connectable {\n  /**\n   * Called when the list of user channels is updated, or the selected channel changes.\n   */\n  updateChannel(channelId: string | null, availableChannels: Channel[]): Promise<void>;\n\n  /**\n   * Called on initialization. The channel selector will invoke the callback after the\n   * channel is changed.\n   */\n  setChannelChangeCallback(callback: (channelId: string | null) => void): void;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/ui/Connectable.ts",
    "content": "//TODO: move this out of fdc3-standard into another package - its an implementation detail of GetAgent and used in fdc3-get-agent and fdc3-agent-proxy\nexport interface Connectable {\n  connect(): Promise<void>;\n\n  disconnect(): Promise<void>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/src/ui/IntentResolver.ts",
    "content": "import { Context } from '@finos/fdc3-context';\nimport { AppIdentifier } from '../api/AppIdentifier.js';\nimport { AppIntent } from '../api/AppIntent.js';\nimport { Connectable } from './Connectable.js';\n\nexport type IntentResolutionChoice = {\n  intent: string;\n  appId: AppIdentifier;\n};\n\n/**\n * Interface used by the desktop agent proxy to handle the intent resolution process.\n */\nexport interface IntentResolver extends Connectable {\n  /**\n   * Called when the user needs to resolve an intent.  Returns either the app chosen to\n   * resolve the intent or void if the operation was cancelled.\n   */\n  chooseIntent(appIntents: AppIntent[], context: Context): Promise<IntentResolutionChoice | void>;\n}\n"
  },
  {
    "path": "packages/fdc3-standard/test/AppDirectory.test.ts",
    "content": "import SwaggerParser from '@apidevtools/swagger-parser';\nimport { Validator } from 'jsonschema';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { beforeAll, expect, it, describe } from 'vitest';\n\n// Get the directory path for loading schema and example files\nconst specificationDir = join(__dirname, '..', 'src', 'app-directory', 'specification');\n\ndescribe('App Directory Schema Validation', () => {\n  let api: unknown;\n  let applicationSchema: unknown;\n  let validator: Validator;\n\n  beforeAll(async () => {\n    // Parse and validate the OpenAPI schema\n    const schemaPath = join(specificationDir, 'appd.schema.json');\n    const schema = JSON.parse(readFileSync(schemaPath, 'utf-8'));\n    api = await SwaggerParser.validate(schema);\n    applicationSchema = (api as { components: { schemas: { Application: unknown } } }).components.schemas.Application;\n    validator = new Validator();\n  });\n\n  it('should have valid API name and version', () => {\n    const apiInfo = (api as { info: { title: string; version: string } }).info;\n    expect(apiInfo.title).toBeDefined();\n    expect(apiInfo.version).toBeDefined();\n  });\n\n  it('should validate myApplication.json example against the Application schema', () => {\n    const examplePath = join(specificationDir, 'examples', 'application', 'myApplication.json');\n    const exampleApplication = JSON.parse(readFileSync(examplePath, 'utf-8'));\n\n    const result = validator.validate(exampleApplication, applicationSchema);\n\n    if (!result.valid) {\n      throw new Error(`Validation errors: ${JSON.stringify(result.errors, null, 2)}`);\n    }\n    expect(result.valid).toBe(true);\n  });\n\n  it('should validate fdc3-workbench.json example against the Application schema', () => {\n    const examplePath = join(specificationDir, 'examples', 'application', 'fdc3-workbench.json');\n    const exampleApplication = JSON.parse(readFileSync(examplePath, 'utf-8'));\n\n    const result = validator.validate(exampleApplication, applicationSchema);\n\n    expect(result.valid).toBe(true);\n    if (!result.valid) {\n      console.error('Validation errors:', result.errors);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-standard/test/ContextTypeSync.test.ts",
    "content": "import { describe, it, expect } from 'vitest';\nimport { readdirSync, readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { createRequire } from 'module';\nimport { ContextTypes } from '../src/context/ContextType.js';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Extracts the fdc3 context type string from a schema file by finding\n * the \"const\" value of the \"type\" property.\n */\nfunction extractContextType(schemaPath: string): string | null {\n  const schema = JSON.parse(readFileSync(schemaPath, 'utf-8'));\n  for (const entry of schema.allOf ?? []) {\n    const typeConst = entry?.properties?.type?.const;\n    if (typeof typeConst === 'string' && typeConst.startsWith('fdc3.')) {\n      return typeConst;\n    }\n  }\n  return null;\n}\n\n/**\n * Reads all context schemas from the fdc3-context package and returns\n * the set of fdc3.* type strings they define.\n */\nfunction getSchemaContextTypes(): Set<string> {\n  const fdc3ContextEntry = require.resolve('@finos/fdc3-context');\n  const schemasDir = resolve(dirname(fdc3ContextEntry), '../schemas/context');\n  const types = new Set<string>();\n\n  for (const file of readdirSync(schemasDir)) {\n    if (!file.endsWith('.schema.json')) continue;\n    const contextType = extractContextType(resolve(schemasDir, file));\n    if (contextType) types.add(contextType);\n  }\n\n  return types;\n}\n\ndescribe('Context type definitions stay in sync with fdc3-context schemas', () => {\n  const schemaTypes = getSchemaContextTypes();\n  const enumValues = new Set(Object.values(ContextTypes));\n\n  it('should find context types in the schemas', () => {\n    expect(schemaTypes.size).toBeGreaterThan(0);\n  });\n\n  it('ContextTypes enum should include every schema-defined context type', () => {\n    const missingFromEnum = [...schemaTypes].filter(t => !enumValues.has(t)).sort();\n\n    if (missingFromEnum.length > 0) {\n      console.error(\n        '\\n❌ Context types defined in fdc3-context schemas but missing from ContextTypes enum:\\n' +\n          missingFromEnum.map(t => `  • ${t}`).join('\\n')\n      );\n    }\n\n    expect(missingFromEnum).toEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-standard/test/ContextTypes.test.ts",
    "content": "import { describe, it, expect } from 'vitest';\nimport { Convert, Contact } from '@finos/fdc3-context';\n\nconst json = '{ \"type\": \"fdc3.contact\", \"id\": { \"email\": \"joe@mail.com\" } }';\nconst contact: Contact = {\n  type: 'fdc3.contact',\n  id: {\n    email: 'joe@mail.com',\n  },\n};\n\n// To be expanded\ndescribe('Context types', () => {\n  it('Convert contact from json', () => {\n    expect(Convert.toContact(json)).toEqual(contact);\n  });\n\n  it('Convert contact to json', () => {\n    expect(JSON.parse(Convert.contactToJson(contact))).toEqual(JSON.parse(json));\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-standard/test/Methods.test.ts",
    "content": "import { vi, beforeEach, afterAll, describe, test, expect } from 'vitest';\nimport { mock } from 'vitest-mock-extended';\nimport {\n  addContextListener,\n  addIntentListener,\n  addEventListener,\n  broadcast,\n  compareVersionNumbers,\n  ContextHandler,\n  DesktopAgent,\n  findIntent,\n  findIntentsByContext,\n  getCurrentChannel,\n  getInfo,\n  getAppMetadata,\n  getOrCreateChannel,\n  getUserChannels,\n  getSystemChannels,\n  ImplementationMetadata,\n  joinChannel,\n  joinUserChannel,\n  leaveCurrentChannel,\n  open,\n  raiseIntent,\n  raiseIntentForContext,\n  versionIsAtLeast,\n  createPrivateChannel,\n  findInstances,\n  isStandardContextType,\n  isStandardIntent,\n} from '../src/index.js';\n\nconst UnavailableError = new Error('FDC3 DesktopAgent not available at `window.fdc3`.');\nconst TimeoutError = new Error('Timed out waiting for `fdc3Ready` event.');\nconst UnexpectedError = new Error('`fdc3Ready` event fired, but `window.fdc3` not set to DesktopAgent.');\n\nconst ContactContext = {\n  type: 'fdc3.contact',\n  id: { email: 'test@example.com' },\n};\n\nexpect.extend({\n  toRejectWithUnavailableError(received) {\n    expect(received).rejects.toEqual(UnavailableError);\n    return { pass: true, message: () => '' };\n  },\n  toThrowUnavailableError(received) {\n    expect(received).toThrowError(UnavailableError);\n    return { pass: true, message: () => '' };\n  },\n});\n\nbeforeEach(() => {\n  vi.resetAllMocks();\n});\n\ndescribe('test ES6 module', () => {\n  describe('without `window.fdc3` global', () => {\n    test('open (via name) should reject', async () => {\n      await expect(open(expect.any(String))).rejects.toEqual(UnavailableError);\n    });\n\n    test('open (via AppIdentifier) should reject', async () => {\n      await expect(open(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('findIntent should reject', async () => {\n      await expect(findIntent(expect.any(String))).rejects.toEqual(UnavailableError);\n    });\n\n    test('findIntentsByContext should reject', async () => {\n      await expect(findIntentsByContext(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('broadcast should reject', async () => {\n      await expect(broadcast(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('raiseIntent should reject', async () => {\n      await expect(raiseIntent(expect.any(String), expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('raiseIntentForContext should reject', async () => {\n      await expect(raiseIntentForContext(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('addIntentListener should reject', async () => {\n      await expect(addIntentListener(expect.any(String), expect.any(Function))).rejects.toEqual(UnavailableError);\n    });\n\n    test('addContextListener should reject', async () => {\n      await expect(addContextListener(expect.any(Object))).rejects.toEqual(UnavailableError);\n\n      await expect(addContextListener(expect.any(String), expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('getUserChannels should reject', async () => {\n      await expect(getUserChannels()).rejects.toEqual(UnavailableError);\n    });\n\n    test('addEventListener should reject', async () => {\n      await expect(addEventListener(expect.any(String), expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('joinChannel should reject', async () => {\n      await expect(joinChannel(expect.any(String))).rejects.toEqual(UnavailableError);\n    });\n\n    test('joinUserChannel should reject', async () => {\n      await expect(joinUserChannel(expect.any(String))).rejects.toEqual(UnavailableError);\n    });\n\n    test('getOrCreateChannel should reject', async () => {\n      await expect(getOrCreateChannel(expect.any(String))).rejects.toEqual(UnavailableError);\n    });\n\n    test('getCurrentChannel should reject', async () => {\n      await expect(getCurrentChannel()).rejects.toEqual(UnavailableError);\n    });\n\n    test('leaveCurrentChannel should reject', async () => {\n      await expect(leaveCurrentChannel()).rejects.toEqual(UnavailableError);\n    });\n\n    test('getInfo should reject', async () => {\n      await expect(() => getInfo()).rejects.toEqual(UnavailableError);\n    });\n\n    test('createPrivateChannel should reject', async () => {\n      await expect(() => createPrivateChannel()).rejects.toEqual(UnavailableError);\n    });\n\n    test('findInstances should reject', async () => {\n      await expect(() => findInstances(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n\n    test('getAppMetadata should reject', async () => {\n      await expect(() => getAppMetadata(expect.any(Object))).rejects.toEqual(UnavailableError);\n    });\n  });\n\n  describe('with `window.fdc3` global', () => {\n    beforeEach(() => {\n      window.fdc3 = mock<DesktopAgent>();\n    });\n\n    afterAll(() => {\n      window.fdc3 = undefined as unknown as DesktopAgent;\n    });\n\n    test('open should delegate to window.fdc3?.open', async () => {\n      const target = 'MyApp';\n\n      await open(target, ContactContext);\n\n      expect(window.fdc3?.open).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.open).toHaveBeenCalledWith(target, ContactContext);\n    });\n\n    test('findIntent should delegate to window.fdc3?.findIntent', async () => {\n      const intent = 'ViewChart';\n\n      await findIntent(intent, ContactContext);\n\n      expect(window.fdc3?.findIntent).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.findIntent).toHaveBeenLastCalledWith(intent, ContactContext, undefined);\n    });\n\n    test('findIntent should delegate to window.fdc3?.findIntent (with additional output type argument)', async () => {\n      const intent = 'ViewChart';\n\n      await findIntent(intent, ContactContext, 'fdc3.contact');\n\n      expect(window.fdc3?.findIntent).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.findIntent).toHaveBeenLastCalledWith(intent, ContactContext, 'fdc3.contact');\n    });\n\n    test('findIntentsByContext should delegate to window.fdc3?.findIntentsByContext', async () => {\n      await findIntentsByContext(ContactContext);\n\n      expect(window.fdc3?.findIntentsByContext).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.findIntentsByContext).toHaveBeenLastCalledWith(ContactContext, undefined);\n    });\n\n    test('findIntentsByContext should delegate to window.fdc3?.findIntentsByContext (with additional output type argument)', async () => {\n      await findIntentsByContext(ContactContext, 'fdc3.contact');\n\n      expect(window.fdc3?.findIntentsByContext).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.findIntentsByContext).toHaveBeenLastCalledWith(ContactContext, 'fdc3.contact');\n    });\n\n    test('broadcast should delegate to window.fdc3?.broadcast', async () => {\n      await broadcast(ContactContext);\n\n      expect(window.fdc3?.broadcast).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.broadcast).toHaveBeenCalledWith(ContactContext);\n    });\n\n    test('raiseIntent should delegate to window.fdc3?.raiseIntent', async () => {\n      const intent = 'ViewChart';\n      const target = 'MyApp';\n\n      await raiseIntent(intent, ContactContext, target);\n\n      expect(window.fdc3?.raiseIntent).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.raiseIntent).toHaveBeenCalledWith(intent, ContactContext, target);\n    });\n\n    test('raiseIntentForContext should delegate to window.fdc3?.raiseIntentForContext', async () => {\n      const app = 'MyApp';\n\n      await raiseIntentForContext(ContactContext, app);\n\n      expect(window.fdc3?.raiseIntentForContext).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.raiseIntentForContext).toHaveBeenCalledWith(ContactContext, app);\n    });\n\n    test('addIntentListener should delegate to window.fdc3?.addIntentListener', async () => {\n      const intent = 'ViewChart';\n      const handler: ContextHandler = _ => {};\n\n      await addIntentListener(intent, handler);\n\n      expect(window.fdc3?.addIntentListener).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.addIntentListener).toHaveBeenCalledWith(intent, handler);\n    });\n\n    test('addContextListener should delegate to window.fdc3?.addContextListener', async () => {\n      const type = 'fdc3.instrument';\n      const handler1: ContextHandler = _ => {};\n      const handler2: ContextHandler = _ => {};\n\n      await addContextListener(type, handler1);\n      await addContextListener(handler2);\n\n      expect(window.fdc3?.addContextListener).toHaveBeenCalledTimes(2);\n      expect(window.fdc3?.addContextListener).toHaveBeenNthCalledWith(1, type, handler1);\n      expect(window.fdc3?.addContextListener).toHaveBeenNthCalledWith(2, null, handler2);\n    });\n\n    test('getUserChannels should delegate to window.fdc3?.getUserChannels', async () => {\n      await getUserChannels();\n\n      expect(window.fdc3?.getUserChannels).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getUserChannels).toHaveBeenCalledWith();\n    });\n\n    test('getSystemChannels should delegate to window.fdc3?.getUserChannels', async () => {\n      await getSystemChannels();\n\n      expect(window.fdc3?.getUserChannels).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getUserChannels).toHaveBeenCalledWith();\n    });\n\n    test('joinChannel should delegate to window.fdc3?.joinUserChannel', async () => {\n      const channelId = 'channel';\n\n      await joinChannel(channelId);\n\n      expect(window.fdc3?.joinUserChannel).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.joinUserChannel).toHaveBeenCalledWith(channelId);\n    });\n\n    test('joinUserChannel should delegate to window.fdc3?.joinUserChannel', async () => {\n      const channelId = 'channel';\n\n      await joinUserChannel(channelId);\n\n      expect(window.fdc3?.joinUserChannel).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.joinUserChannel).toHaveBeenCalledWith(channelId);\n    });\n\n    test('getOrCreateChannel should delegate to window.fdc3?.getOrCreateChannel', async () => {\n      const channelId = 'channel';\n\n      await getOrCreateChannel(channelId);\n\n      expect(window.fdc3?.getOrCreateChannel).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getOrCreateChannel).toHaveBeenCalledWith(channelId);\n    });\n\n    test('getCurrentChannel should delegate to window.fdc3?.getCurrentChannel', async () => {\n      await getCurrentChannel();\n\n      expect(window.fdc3?.getCurrentChannel).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getCurrentChannel).toHaveBeenCalledWith();\n    });\n\n    test('leaveCurrentChannel should delegate to window.fdc3?.leaveCurrentChannel', async () => {\n      await leaveCurrentChannel();\n\n      expect(window.fdc3?.leaveCurrentChannel).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.leaveCurrentChannel).toHaveBeenCalledWith();\n    });\n\n    test('getInfo should delegate to window.fdc3?.getInfo', async () => {\n      await getInfo();\n\n      expect(window.fdc3?.getInfo).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getInfo).toHaveBeenCalledWith();\n    });\n\n    test('getAppMetadata should delegate to window.fdc3?.getAppMetadata', async () => {\n      const dummyApp = { appId: 'dummy' };\n      await getAppMetadata(dummyApp);\n\n      expect(window.fdc3?.getAppMetadata).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.getAppMetadata).toHaveBeenCalledWith(dummyApp);\n    });\n\n    test('createPrivateChannel should delegate to window.fdc3?.createPrivateChannel', async () => {\n      await createPrivateChannel();\n\n      expect(window.fdc3?.createPrivateChannel).toHaveBeenCalledTimes(1);\n    });\n\n    test('findInstances should delegate to window.fdc3?.findInstances', async () => {\n      const dummyApp = { appId: 'dummy' };\n      await findInstances(dummyApp);\n\n      expect(window.fdc3?.findInstances).toHaveBeenCalledTimes(1);\n      expect(window.fdc3?.findInstances).toHaveBeenCalledWith(dummyApp);\n    });\n  });\n});\n\ndescribe('test version comparison functions', () => {\n  test('compareVersionNumbers', () => {\n    expect(compareVersionNumbers('1.1', '1.2')).toBe(-1);\n    expect(compareVersionNumbers('1.2', '1.1')).toBe(1);\n    expect(compareVersionNumbers('1.2', '1.2')).toBe(0);\n    expect(compareVersionNumbers('1.1.1', '1.2')).toBe(-1);\n    expect(compareVersionNumbers('1.1.1', '1.1')).toBe(1);\n    expect(compareVersionNumbers('1.1', '1.1.1')).toBe(-1);\n    expect(compareVersionNumbers('1.1.1', '1.1.1')).toBe(0);\n  });\n\n  test('versionIsAtLeast', () => {\n    const metaOneTwo: ImplementationMetadata = {\n      fdc3Version: '1.2',\n      provider: 'test',\n      appMetadata: { appId: 'dummy', name: 'dummy' },\n      optionalFeatures: {\n        OriginatingAppMetadata: true,\n        UserChannelMembershipAPIs: false,\n        DesktopAgentBridging: false,\n      },\n    };\n    expect(versionIsAtLeast(metaOneTwo, '1.1')).toBe(true);\n    expect(versionIsAtLeast(metaOneTwo, '1.2')).toBe(true);\n    expect(versionIsAtLeast(metaOneTwo, '1.2.1')).toBe(false);\n    expect(versionIsAtLeast(metaOneTwo, '2.0')).toBe(false);\n\n    const metaOneTwoOne: ImplementationMetadata = {\n      fdc3Version: '1.2.1',\n      provider: 'test',\n      appMetadata: { appId: 'dummy', name: 'dummy' },\n      optionalFeatures: {\n        OriginatingAppMetadata: true,\n        UserChannelMembershipAPIs: false,\n        DesktopAgentBridging: false,\n      },\n    };\n    expect(versionIsAtLeast(metaOneTwoOne, '1.1')).toBe(true);\n    expect(versionIsAtLeast(metaOneTwoOne, '1.2')).toBe(true);\n    expect(versionIsAtLeast(metaOneTwoOne, '1.2.1')).toBe(true);\n    expect(versionIsAtLeast(metaOneTwoOne, '2.0')).toBe(false);\n  });\n\n  test('isStandardContextType should return TRUE for standard context types', () => {\n    expect(isStandardContextType('fdc3.action')).toBe(true);\n    expect(isStandardContextType('fdc3.chart')).toBe(true);\n    expect(isStandardContextType('fdc3.chat.initSettings')).toBe(true);\n    expect(isStandardContextType('fdc3.chat.message')).toBe(true);\n    expect(isStandardContextType('fdc3.chat.room')).toBe(true);\n    expect(isStandardContextType('fdc3.chat.searchCriteria')).toBe(true);\n    expect(isStandardContextType('fdc3.contact')).toBe(true);\n    expect(isStandardContextType('fdc3.contactList')).toBe(true);\n    expect(isStandardContextType('fdc3.country')).toBe(true);\n    expect(isStandardContextType('fdc3.currency')).toBe(true);\n    expect(isStandardContextType('fdc3.email')).toBe(true);\n    expect(isStandardContextType('fdc3.instrument')).toBe(true);\n    expect(isStandardContextType('fdc3.instrumentList')).toBe(true);\n    expect(isStandardContextType('fdc3.interaction')).toBe(true);\n    expect(isStandardContextType('fdc3.message')).toBe(true);\n    expect(isStandardContextType('fdc3.organization')).toBe(true);\n    expect(isStandardContextType('fdc3.portfolio')).toBe(true);\n    expect(isStandardContextType('fdc3.position')).toBe(true);\n    expect(isStandardContextType('fdc3.nothing')).toBe(true);\n    expect(isStandardContextType('fdc3.timeRange')).toBe(true);\n    expect(isStandardContextType('fdc3.transactionResult')).toBe(true);\n    expect(isStandardContextType('fdc3.valuation')).toBe(true);\n  });\n\n  test('isStandardContextType should return FALSE for custom context types', () => {\n    expect(isStandardContextType('myApp.customContext')).toBe(false);\n  });\n\n  test('isStandardIntent should return TRUE for standard intents', () => {\n    expect(isStandardIntent('CreateInteraction')).toBe(true);\n    expect(isStandardIntent('SendChatMessage')).toBe(true);\n    expect(isStandardIntent('StartCall')).toBe(true);\n    expect(isStandardIntent('StartChat')).toBe(true);\n    expect(isStandardIntent('StartEmail')).toBe(true);\n    expect(isStandardIntent('ViewAnalysis')).toBe(true);\n    expect(isStandardIntent('ViewChat')).toBe(true);\n    expect(isStandardIntent('ViewChart')).toBe(true);\n    expect(isStandardIntent('ViewContact')).toBe(true);\n    expect(isStandardIntent('ViewHoldings')).toBe(true);\n    expect(isStandardIntent('ViewInstrument')).toBe(true);\n    expect(isStandardIntent('ViewInteractions')).toBe(true);\n    expect(isStandardIntent('ViewMessages')).toBe(true);\n    expect(isStandardIntent('ViewNews')).toBe(true);\n    expect(isStandardIntent('ViewOrders')).toBe(true);\n    expect(isStandardIntent('ViewProfile')).toBe(true);\n    expect(isStandardIntent('ViewQuote')).toBe(true);\n    expect(isStandardIntent('ViewResearch')).toBe(true);\n  });\n\n  test('isStandardIntent should return FALSE for custom intents', () => {\n    expect(isStandardIntent('myApp.CustomIntent')).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-standard/test/window.test.ts",
    "content": "import { describe, it, expect } from 'vitest';\n\ndescribe('Window object', () => {\n  it('fdc3 property should be present but undefined', () => {\n    expect(window.fdc3).toBe(undefined);\n  });\n});\n"
  },
  {
    "path": "packages/fdc3-standard/tsconfig.json",
    "content": "{\n    \"extends\": \"../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"rootDirs\": [\n            \"src\"\n        ],\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src\",\n    ],\n    \"exclude\": [\n        \"test/**\",\n        \"dist/**\"\n    ],\n    \"references\": [\n        {\n            \"path\": \"../fdc3-schema\"\n        },\n        {\n            \"path\": \"../fdc3-context\"\n        }\n    ]\n}"
  },
  {
    "path": "packages/fdc3-standard/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    include: ['test/**/*.test.ts'],\n    environment: 'jsdom',\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n    coverage: {\n      enabled: true,\n      provider: 'v8',\n      reporter: ['text', 'lcov', 'json'],\n      reportsDirectory: './coverage',\n      include: ['src/**/*.ts'],\n      exclude: ['src/**/*.d.ts'],\n    },\n  },\n});\n"
  },
  {
    "path": "packages/testing/package.json",
    "content": "{\n  \"name\": \"@finos/testing\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/src/index.d.ts\",\n      \"import\": \"./dist/src/index.js\",\n      \"require\": \"./dist/src/index.js\"\n    }\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"clean\": \"rimraf dist\",\n    \"test\": \"tsc\"\n  },\n  \"dependencies\": {\n    \"@cucumber/cucumber\": \"10.3.1\",\n    \"pixelmatch\": \"^7.1.0\",\n    \"quickpickle\": \"^1.4.1\",\n    \"@cucumber/html-formatter\": \"11.0.4\",\n    \"@cucumber/pretty-formatter\": \"1.0.1\",\n    \"@finos/fdc3-standard\": \"2.2.2\",\n    \"@types/expect\": \"24.3.0\",\n    \"@types/lodash\": \"4.14.167\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"ajv\": \"^8.18.0\",\n    \"ajv-formats\": \"^3.0.1\",\n    \"eslint-plugin-import\": \"^2.31.0\",\n    \"eslint-plugin-prettier\": \"3.3.1\",\n    \"expect\": \"^29.7.0\",\n    \"is-ci\": \"2.0.0\",\n    \"jsonpath-plus\": \"^10.1.0\",\n    \"nyc\": \"17.1.0\",\n    \"ts-node\": \"^10.9.2\",\n    \"uuid\": \"^9.0.1\"\n  },\n  \"overrides\": {\n    \"ajv-formats\": {\n      \"ajv\": \"8.18.0\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/testing/src/agent/index.ts",
    "content": "import { AppIntent, Channel, IntentResult } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { IntentResolver, IntentResolutionChoice, ChannelSelector } from '@finos/fdc3-standard';\nimport { PropsWorldLike } from '../world/PropsWorldLike.js';\n\n/**\n * This super-simple intent resolver just resolves to the first\n * intent / app in the list, unless the context is fdc3.cancel-me  and then it just cancels.\n */\nexport class SimpleIntentResolver implements IntentResolver {\n  cw: PropsWorldLike;\n\n  constructor(cw: PropsWorldLike) {\n    this.cw = cw;\n  }\n\n  async connect(): Promise<void> {}\n\n  async disconnect(): Promise<void> {}\n\n  async intentChosen(ir: IntentResult): Promise<IntentResult> {\n    this.cw.props['intent-result'] = ir;\n    return ir;\n  }\n\n  async chooseIntent(appIntents: AppIntent[], ctx: Context): Promise<IntentResolutionChoice | void> {\n    if (ctx.type == 'fdc3.cancel-me') {\n      return;\n    }\n\n    const out = {\n      intent: appIntents[0].intent,\n      chosenApp: appIntents[0].apps[0],\n    };\n\n    this.cw.props['intent-resolution'] = out;\n    return {\n      appId: appIntents[0].apps[0],\n      intent: appIntents[0].intent.name,\n    };\n  }\n}\n\nexport const CHANNEL_STATE = 'CHANNEL_STATE';\n\nexport class SimpleChannelSelector implements ChannelSelector {\n  cw: PropsWorldLike;\n\n  constructor(cw: PropsWorldLike) {\n    this.cw = cw;\n  }\n\n  async updateChannel(channelId: string | null, availableChannels: Channel[]): Promise<void> {\n    this.cw.props['channelId'] = channelId;\n    this.cw.props['channels'] = availableChannels;\n  }\n\n  setChannelChangeCallback(_callback: (channelId: string | null) => void): void {}\n\n  async connect(): Promise<void> {}\n\n  async disconnect(): Promise<void> {}\n}\n"
  },
  {
    "path": "packages/testing/src/index.ts",
    "content": "import { setupGenericSteps } from './steps/generic.steps.js';\nimport { doesRowMatch, handleResolve, indexOf, matchData, HashesProvider } from './support/matching.js';\nimport { PropsWorldLike } from './world/PropsWorldLike.js';\nimport Ajv2019 from 'ajv/dist/2019.js';\nimport addFormats from 'ajv-formats';\nimport { SimpleIntentResolver, SimpleChannelSelector, CHANNEL_STATE } from './agent/index.js';\n\nexport {\n  PropsWorldLike,\n  HashesProvider,\n  doesRowMatch,\n  handleResolve,\n  indexOf,\n  matchData,\n  setupGenericSteps,\n  SimpleIntentResolver,\n  SimpleChannelSelector,\n  addFormats,\n  Ajv2019,\n  CHANNEL_STATE,\n};\n"
  },
  {
    "path": "packages/testing/src/steps/generic.impl.ts",
    "content": "import { PropsWorldLike } from '../world/PropsWorldLike.js';\nimport { handleResolve, matchData, doesRowMatch, HashesProvider } from '../support/matching.js';\nimport { expect } from 'vitest';\nimport * as AjvModule from 'ajv/dist/2019.js';\nimport * as draft7MetaSchema from 'ajv/dist/refs/json-schema-draft-07.json' with { type: 'json' };\nimport * as addFormatsModule from 'ajv-formats';\nimport fs from 'fs';\nimport path from 'path';\n\n// Workaround for AJV ESM default export\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst AjvCtor = (AjvModule as any).default ?? AjvModule;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst addFormatsFn = (addFormatsModule as any).default ?? addFormatsModule;\n\nexport async function promiseShouldResolve(world: PropsWorldLike, field: string): Promise<void> {\n  try {\n    const promise = handleResolve(field, world) as Promise<unknown>;\n    const object = await promise;\n    world.props['result'] = object;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport async function promiseShouldResolveWithin10Seconds(world: PropsWorldLike, field: string): Promise<void> {\n  try {\n    const promise = handleResolve(field, world) as Promise<unknown>;\n    const object = await promise;\n    world.props['result'] = object;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport async function callWithMethod(world: PropsWorldLike, field: string, fnName: string): Promise<void> {\n  try {\n    const object = handleResolve(field, world) as Record<string, (...args: unknown[]) => unknown>;\n    const fn = object[fnName];\n    const result = await fn.call(object);\n    world.props['result'] = result;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport async function callWithMethodAndParam(\n  world: PropsWorldLike,\n  field: string,\n  fnName: string,\n  param: string\n): Promise<void> {\n  try {\n    const object = handleResolve(field, world) as Record<string, (...args: unknown[]) => unknown>;\n    const fn = object[fnName];\n    const result = await fn.call(object, handleResolve(param, world));\n    world.props['result'] = result;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport async function callWithMethodAndTwoParams(\n  world: PropsWorldLike,\n  field: string,\n  fnName: string,\n  param1: string,\n  param2: string\n): Promise<void> {\n  try {\n    const object = handleResolve(field, world) as Record<string, (...args: unknown[]) => unknown>;\n    const fn = object[fnName];\n    const result = await fn.call(object, handleResolve(param1, world), handleResolve(param2, world));\n    world.props['result'] = result;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport async function callWithMethodAndThreeParams(\n  world: PropsWorldLike,\n  field: string,\n  fnName: string,\n  param1: string,\n  param2: string,\n  param3: string\n): Promise<void> {\n  try {\n    const object = handleResolve(field, world) as Record<string, (...args: unknown[]) => unknown>;\n    const fn = object[fnName];\n    const result = await fn.call(\n      object,\n      handleResolve(param1, world),\n      handleResolve(param2, world),\n      handleResolve(param3, world)\n    );\n    world.props['result'] = result;\n  } catch (error) {\n    world.props['result'] = error;\n  }\n}\n\nexport function referToAs(world: PropsWorldLike, from: string, to: string): void {\n  world.props[to] = handleResolve(from, world);\n}\n\nexport function isArrayOfObjectsWithContents(world: PropsWorldLike, field: string, dt: HashesProvider): void {\n  matchData(world, handleResolve(field, world) as unknown[], dt);\n}\n\nexport function isArrayOfObjectsWithLength(world: PropsWorldLike, field: string, field2: string): void {\n  expect((handleResolve(field, world) as unknown[]).length).toEqual(\n    Number.parseInt(handleResolve(field2, world) as string)\n  );\n}\n\nexport function isArrayOfStringsWithValues(world: PropsWorldLike, field: string, dt: HashesProvider): void {\n  const values = (handleResolve(field, world) as string[]).map((s: string) => {\n    return { value: s };\n  });\n  matchData(world, values, dt);\n}\n\nexport function isObjectWithContents(world: PropsWorldLike, field: string, params: HashesProvider): void {\n  const table = params.hashes();\n  expect(doesRowMatch(world, table[0], handleResolve(field, world))).toBeTruthy();\n}\n\nexport function isNull(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeNull();\n}\n\nexport function isNotNull(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeDefined();\n}\n\nexport function isTrue(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeTruthy();\n}\n\nexport function isFalse(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeFalsy();\n}\n\nexport function isUndefined(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeUndefined();\n}\n\nexport function isEmpty(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toHaveLength(0);\n}\n\nexport function isEqual(world: PropsWorldLike, field: string, expected: string): void {\n  const fVal = handleResolve(field, world);\n  const eVal = handleResolve(expected, world);\n  expect('' + fVal).toEqual('' + eVal);\n}\n\nexport function isErrorWithMessage(world: PropsWorldLike, field: string, errorType: string): void {\n  expect((handleResolve(field, world) as { message: string })['message']).toBe(errorType);\n}\n\nexport function isError(world: PropsWorldLike, field: string): void {\n  expect(handleResolve(field, world)).toBeInstanceOf(Error);\n}\n\nexport function isInvocationCounter(world: PropsWorldLike, handlerName: string, field: string): void {\n  world.props[handlerName] = () => {\n    let amount = world.props[field] as number;\n    amount++;\n    world.props[field] = amount;\n  };\n  world.props[field] = 0;\n}\n\nexport function isFunctionReturningPromiseOf(world: PropsWorldLike, fnName: string, field: string): void {\n  const value = handleResolve(field, world);\n  world.props[fnName] = async () => {\n    return value;\n  };\n}\n\nexport function waitForPeriod(_world: PropsWorldLike, ms: string): Promise<void> {\n  return new Promise<void>((resolve, _reject) => {\n    setTimeout(() => resolve(), parseInt(ms));\n  });\n}\n\nexport async function schemasLoaded(world: PropsWorldLike, schemaBasePath: string): Promise<void> {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const ajv = new AjvCtor() as any;\n  ajv.addMetaSchema(draft7MetaSchema);\n  addFormatsFn(ajv);\n\n  const schemaDir = path.join(schemaBasePath, 'fdc3-schema/schemas');\n  const contextDir = path.join(schemaBasePath, 'fdc3-context/schemas');\n\n  const abspath = path.join(schemaDir, 'api');\n\n  try {\n    fs.readdirSync(abspath).forEach(file => {\n      if (file.endsWith('.json')) {\n        const filePath = path.join(abspath, file);\n        const contents = fs.readFileSync(filePath, 'utf8');\n        const schema = JSON.parse(contents);\n        ajv.addSchema(schema);\n      }\n    });\n  } catch (error) {\n    console.log(error);\n  }\n\n  const contextPath = path.join(contextDir, 'context/context.schema.json');\n  const contents = fs.readFileSync(contextPath, 'utf8');\n  const schema = JSON.parse(contents);\n  ajv.addSchema(schema);\n\n  world.props['ajv'] = ajv;\n}\n"
  },
  {
    "path": "packages/testing/src/steps/generic.steps.ts",
    "content": "import { Given, When, Then } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { PropsWorldLike } from '../world/PropsWorldLike.js';\nimport * as impl from './generic.impl.js';\n\nexport function setupGenericSteps(schemaBasePath: string): void {\n  Then('the promise {string} should resolve', async (world: PropsWorldLike, field: string) => {\n    await impl.promiseShouldResolve(world, field);\n  });\n\n  Then('the promise {string} should resolve within 10 seconds', async (world: PropsWorldLike, field: string) => {\n    await impl.promiseShouldResolveWithin10Seconds(world, field);\n  });\n\n  When('I call {string} with {string}', async (world: PropsWorldLike, field: string, fnName: string) => {\n    await impl.callWithMethod(world, field, fnName);\n  });\n\n  When(\n    'I call {string} with {string} with parameter {string}',\n    async (world: PropsWorldLike, field: string, fnName: string, param: string) => {\n      await impl.callWithMethodAndParam(world, field, fnName, param);\n    }\n  );\n\n  When(\n    'I call {string} with {string} with parameters {string} and {string}',\n    async (world: PropsWorldLike, field: string, fnName: string, param1: string, param2: string) => {\n      await impl.callWithMethodAndTwoParams(world, field, fnName, param1, param2);\n    }\n  );\n\n  When(\n    'I call {string} with {string} with parameters {string} and {string} and {string}',\n    async (world: PropsWorldLike, field: string, fnName: string, param1: string, param2: string, param3: string) => {\n      await impl.callWithMethodAndThreeParams(world, field, fnName, param1, param2, param3);\n    }\n  );\n\n  When('I refer to {string} as {string}', (world: PropsWorldLike, from: string, to: string) => {\n    impl.referToAs(world, from, to);\n  });\n\n  Then(\n    '{string} is an array of objects with the following contents',\n    (world: PropsWorldLike, field: string, dt: DataTable) => {\n      impl.isArrayOfObjectsWithContents(world, field, dt);\n    }\n  );\n\n  Then(\n    '{string} is an array of objects with length {string}',\n    (world: PropsWorldLike, field: string, field2: string) => {\n      impl.isArrayOfObjectsWithLength(world, field, field2);\n    }\n  );\n\n  Then(\n    '{string} is an array of strings with the following values',\n    (world: PropsWorldLike, field: string, dt: DataTable) => {\n      impl.isArrayOfStringsWithValues(world, field, dt);\n    }\n  );\n\n  Then(\n    '{string} is an object with the following contents',\n    (world: PropsWorldLike, field: string, params: DataTable) => {\n      impl.isObjectWithContents(world, field, params);\n    }\n  );\n\n  Then('{string} is null', (world: PropsWorldLike, field: string) => {\n    impl.isNull(world, field);\n  });\n\n  Then('{string} is not null', (world: PropsWorldLike, field: string) => {\n    impl.isNotNull(world, field);\n  });\n\n  Then('{string} is true', (world: PropsWorldLike, field: string) => {\n    impl.isTrue(world, field);\n  });\n\n  Then('{string} is false', (world: PropsWorldLike, field: string) => {\n    impl.isFalse(world, field);\n  });\n\n  Then('{string} is undefined', (world: PropsWorldLike, field: string) => {\n    impl.isUndefined(world, field);\n  });\n\n  Then('{string} is empty', (world: PropsWorldLike, field: string) => {\n    impl.isEmpty(world, field);\n  });\n\n  Then('{string} is {string}', (world: PropsWorldLike, field: string, expected: string) => {\n    impl.isEqual(world, field, expected);\n  });\n\n  Then('{string} is an error with message {string}', (world: PropsWorldLike, field: string, errorType: string) => {\n    impl.isErrorWithMessage(world, field, errorType);\n  });\n\n  Then('{string} is an error', (world: PropsWorldLike, field: string) => {\n    impl.isError(world, field);\n  });\n\n  Given(\n    '{string} is a invocation counter into {string}',\n    (world: PropsWorldLike, handlerName: string, field: string) => {\n      impl.isInvocationCounter(world, handlerName, field);\n    }\n  );\n\n  Given(\n    '{string} is a function which returns a promise of {string}',\n    (world: PropsWorldLike, fnName: string, field: string) => {\n      impl.isFunctionReturningPromiseOf(world, fnName, field);\n    }\n  );\n\n  Given('we wait for a period of {string} ms', (world: PropsWorldLike, ms: string) => {\n    return impl.waitForPeriod(world, ms);\n  });\n\n  Given('schemas loaded', async (world: PropsWorldLike) => {\n    await impl.schemasLoaded(world, schemaBasePath);\n  });\n}\n"
  },
  {
    "path": "packages/testing/src/support/matching.ts",
    "content": "import { JSONPath } from 'jsonpath-plus';\nimport { PropsWorldLike } from '../world/PropsWorldLike.js';\nimport { expect } from 'vitest';\n\nexport interface HashesProvider {\n  hashes(): Record<string, string>[];\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function doesRowMatch(cw: PropsWorldLike, t: Record<string, string>, data: any): boolean {\n  for (const [field, actual] of Object.entries(t)) {\n    if (field.endsWith('matches_type')) {\n      // validation mode\n      var valdata = data;\n\n      if (field.length > 'matches_type'.length) {\n        // deals with the case where we're validating part of the object\n        const path = field.substring(0, field.length - 'matches_type'.length - 1);\n        valdata = JSONPath({ path: path, json: data })[0];\n      }\n\n      const validator = cw.props['ajv'];\n      const validate = validator.getSchema('https://fdc3.finos.org/schemas/next/api/' + actual + '.schema.json');\n      if (validate == undefined) {\n        throw Error('No schema found for ' + actual);\n      }\n      const valid = validate(valdata);\n      if (!valid) {\n        try {\n          cw.log(`Comparing Validation failed: ${JSON.stringify(data, null, 2)} \\n ${JSON.stringify(validate.errors)}`);\n        } catch (e) {\n          cw.log(`Comparing Validation failed: ${JSON.stringify(validate.errors)}`);\n        }\n        return false;\n      }\n    } else {\n      const found = JSONPath({ path: field, json: data })[0];\n      const resolved = handleResolve(actual, cw);\n\n      if (found != resolved) {\n        try {\n          cw.log(\n            `Comparing Validation failed: ${JSON.stringify(data, null, 2)} \\n Match failed on ${field} '${found}' vs '${resolved}'`\n          );\n        } catch (e) {\n          cw.log('Match failed on ' + field + \" '\" + found + \"' vs '\" + resolved + \"'\");\n        }\n        return false;\n      }\n    }\n  }\n\n  return true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function indexOf(cw: PropsWorldLike, rows: Record<string, string>[], data: any): number {\n  for (var i = 0; i < rows.length; i++) {\n    if (doesRowMatch(cw, rows[i], data)) {\n      return i;\n    }\n  }\n\n  return -1;\n}\n\nfunction isNumeric(n: string) {\n  return !isNaN(parseFloat(n)) && isFinite(n as unknown as number);\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handleResolve(name: string, on: PropsWorldLike): any {\n  if (name.startsWith('{') && name.endsWith('}')) {\n    const stripped = name.substring(1, name.length - 1);\n    if (stripped == 'null') {\n      return null;\n    } else if (stripped == 'true') {\n      return true;\n    } else if (stripped == 'false') {\n      return false;\n    } else if (isNumeric(stripped)) {\n      return Number.parseFloat(stripped);\n    } else {\n      const out = JSONPath({ path: stripped, json: on.props })[0];\n      return out;\n    }\n  } else {\n    return name;\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function matchData(cw: PropsWorldLike, actual: any[], dt: HashesProvider) {\n  const tableData = dt.hashes();\n  const rowCount = tableData.length;\n\n  var resultCopy = JSON.parse(JSON.stringify(actual)) as any[];\n  cw.log(`result ${JSON.stringify(resultCopy, null, 2)} length ${resultCopy.length}`);\n  expect(resultCopy).toHaveLength(rowCount);\n  var row = 0;\n\n  resultCopy = resultCopy.filter(rr => {\n    const matchingRow = tableData[row];\n    row++;\n    if (doesRowMatch(cw, matchingRow, rr)) {\n      return false;\n    } else {\n      cw.log(`Couldn't match row: ${JSON.stringify(rr, null, 2)}`);\n      return true;\n    }\n  });\n\n  expect(resultCopy).toHaveLength(0);\n}\n"
  },
  {
    "path": "packages/testing/src/world/PropsWorldLike.ts",
    "content": "export interface PropsWorldLike {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  props: Record<string, any>;\n  log(message: string): void;\n}\n"
  },
  {
    "path": "packages/testing/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.root.json\",\n  \"compilerOptions\": {\n    \"rootDirs\": [\n      \"src\"\n    ],\n    \"outDir\": \"dist\",\n  },\n  \"include\": [\n    \"src\"\n  ],\n  \"exclude\": [\n    \"test/**\",\n    \"dist/**\"\n  ],\n  \"references\": [\n    {\n      \"path\": \"../fdc3-standard\"\n    }\n  ]\n}"
  },
  {
    "path": "scripts/version-check.js",
    "content": "const fs = require('fs');\n\nconst root = JSON.parse(fs.readFileSync('package.json', 'utf8'));\nconst workspaces = root.workspaces || [];\n\nconst mismatched = workspaces\n  .map(dir => ({\n    dir,\n    ...JSON.parse(fs.readFileSync(`${dir}/package.json`, 'utf8')),\n  }))\n  .filter(pkg => !pkg.private && pkg.version !== root.version);\n\nif (mismatched.length) {\n  console.error(\n    `ERROR: Root version (${root.version}) does not match:\\n` +\n      mismatched.map(p => `  ${p.dir}: ${p.version}`).join('\\n')\n  );\n  process.exit(1);\n}\n\nconsole.log(`All public workspace versions match root: ${root.version}`);\n"
  },
  {
    "path": "toolbox/fdc3-conformance/README.md",
    "content": "\n# FDC3 Conformance Framework\n\nA framework for testing whether desktop containers implement the [FDC3 standard](https://fdc3.finos.org/).\n\nThe tests implemented for each FDC3 version are based on the FDC3 Conformance tests specifications defined by the FDC3 maintainers and hosted on the [FDC3 website](https://fdc3.finos.org/docs/api/conformance/Conformance-Overview). \n\nTests in this module currently implement versions 2.0 and 2.2 of the FDC3 Standard.  For old 1.2 conformance testing, please see the [archived FDC3 Conformance project](https://github.com/finos/FDC3-Conformance-Framework).\n\n## What Is It?\n\n- There are many vendors implementing Desktop Agents for the FDC3 standard.\n- Developers building apps interoperating with the FDC3 standard want to be sure that their apps will work with every Desktop Agent.\n- This suite of conformance tests allows for programmatic verification of an FDC3 Desktop Agent implementation.\n\n## Why Is This Important?\n\n✔️ **Multiple Platforms**\n\nIt can be annoying for users to find that features in their apps that they rely on don't work when changing between Desktop Agents.  Hopefully these conformance tests will add security around that.\n\n✔️ **Marketing**\n\nFINOS has created _badges_ to indicate conformance with the FDC3 standard.   By passing the conformance tests and joining the conformance program, firms are able to use those badges in their own marketing materials.\n\n✔️ **Backwards Compatibility**\n\nThere are multiple versions of the FDC3 standard.  A Desktop Agent could host apps written in _any one of these versions_.  For that reason, it's important that Desktop Agents are tested to make sure that they keep on supporting apps written against older versions of FDC3.\n\n## How Does It Work?\n\nThere are two main parts to conformance:\n  \n  - Running the tests _locally_\n  - Joining the Conformance Program\n\n### Running The Conformance Tests\n\nYou can either run the hosted conformance tests on the FDC3 Website, or run them on your local machine (useful if you are making changes).  Instructions for doing either of those things are here:\n\n#### Running From fdc3.finos.org\n\nYou can run the FDC3 conformance tests straight from the FDC3 website.  If you have a Desktop Agent supporting the [AppD v2 standard](https://fdc3.finos.org/docs/app-directory/spec), you can run the tests from the following URL:\n\n - [https://fdc3.finos.org/toolbox/fdc3-conformance/directories/website-conformance.v2.json](https://fdc3.finos.org/toolbox/fdc3-conformance/directories/website-conformance.v2.json)\n\n#### Local Installation\n\nAlternatively, you can run the conformance suite from your local machine by following these steps:\n\n1.  **Check Out This Repo**\n\nThe FDC3 project is a monorepo and the `toolbox/fdc3-conformance` folder contains the conformance tests.  \n\n2. **Install Dependencies**\n\nIn order to get started, install all the dependencies with:\n\n```sh\nnpm install\n```\n\n3.  **Run The Apps Locally**\n\nTo run the conformance suite (and all of the other FDC3 project components such as the workbench and demo desktop agent) locally on port 3001:\n\n```sh\nnpm run dev\n```\n\n4.  **Set Up Your Desktop Agent**\n\nYou will need to set up your desktop agent so that it has an _App Directory containing all the conformance apps_.   \nThis step is vendor-dependent, but examples of `AppD` records can be found in `/toolbox/fdc3-for-web/demo/static/da/local-conformance.v2.json`.\n\n### Running The Tests\n\nOnce you have configured your desktop agent correctly, open the conformance app and select the tests you wish to run:\n\n<img src=\"static/selecting.png\" alt=\"Selecting Tests\" width=\"400px\" />\n\nThe tests run and produce an output in the window.  Failure are shown with a stack trace in red:\n\n<img src=\"static/failing.png\" alt=\"Running Tests\" width=\"400px\" />\n\nSuccessful runs look something like this:\n\n<img src=\"static/running.png\" alt=\"Success\" width=\"400px\" />\n\n### Joining The Conformance Program\n\nIf you've had a clean run of all the tests locally, why not join the conformance program?\n\n[Instructions to join the Certified FDC3 Desktop Agent Conformance Program](instructions.md)\n\nOnce you have followed these steps, you will be allowed to display the FDC3 Compliance Badges within your marketing literature.\n\n<img src=\"terms-conditions/graphics/1.2/2022_FDC3_CompliantBadge_1.2.png\" alt=\"Conformance with FDC3 1.2\" width=\"100px\"><img src=\"terms-conditions/graphics/2.0/2022_FDC3_CompliantBadge_2.0.png\" alt=\"Conformance with FDC3 2.0\"  width=\"100px\">\n\n### Which Desktop Agents Are Conformant?\n\nWe publish the details of conformant desktop agents on the [FDC3 Home Page](https://fdc3.finos.org#conformance).  Please check there to find out who FINOS has certified! \n\n"
  },
  {
    "path": "toolbox/fdc3-conformance/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "toolbox/fdc3-conformance/instructions.md",
    "content": "# How to Apply For FDC3 Certification for a Desktop Agent\n\n## 1. Run The Conformance Tests Yourself\n\nSee [Readme](README.md) about how to do this.  \n\n## 2. Raise An Issue On This project\n\n[Raise An Issue](https://github.com/finos/FDC3/issues) tagging it with `conformance`.  \n\nIn all likelihood, you will need to liaise with the maintainers of this project in order to get the conformance tests to work with your desktop agent.  \n\nThis will also kick off the process of applying for the \"FDC3 Certified\" mark.\n\n- Provide details in the issue about how you configured and ran the conformance tests in step 1 above.\n- Provide the test results (number of passes / fails, details of failed tests, versions used) in the issue.\n\n## 3.  Replication\n\nMaintainers of the FDC3 Conformance Framework will aim to replicate your test results.  You must work with them to provide the correct version(s) of your software and resolve any issues around licensing that may arise in order  that they can proceed.  \n\n## 4.  Fees\n\nFees for certification are:\n\n|FINOS Membership Level        |Fee per Unit*     |\n|------------------------------|------------------|\n|Platinum|Free (unlimited units) |\n|Gold    |Free (up to 3 units each membership year) |\n|Silver |Free (first unit each membership year)|\n|Additional Units / Non Members |$20,000 per unit|\n\nThese fees are to cover work done by the FINOS for the formal certification process and badge issuance. \n\n*A _unit_ here refers to a particular vendor software version and FDC3 version _combination_, as described in the [Terms and Conditions](terms-conditions/participation-form.md)\n\n## 5.  Failed Tests\n\nIf your desktop agent fails any of the conformance tests, the maintainers will inform you via the issue you opened in order that you can make fixes to your software and retry the process.\n\n## 6.  Terms\n\nOnce your desktop agent has passed the complete suite of tests, you will be required to accept the terms and conditions via the completion of the [Participation Form](terms-conditions/participation-form.md).\n\n## 7.  Badge\n\nOn completion of the above steps you will be given your certificate via the [Credly](https://cred.ly) platform for use in your own materials / publicity.\n\n## 8.  Re-Certification\n\nCertification only applies to a single version of your software product. FINOS reserves the right to allow certification to carry over at no additional cost for minor/maintenance version changes of your desktop agent if no backward incompatible changes are introduced in those versions.\n"
  },
  {
    "path": "toolbox/fdc3-conformance/package.json",
    "content": "{\n  \"name\": \"fdc3-conformance\",\n  \"version\": \"2.2.2\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"private\": true,\n  \"license\": \"Apache-2.0\",\n  \"scripts\": {\n    \"copy\": \"shx mkdir -p ./dist && shx cp -R static/* ./dist\",\n    \"build\": \"webpack build && npm run copy\",\n    \"serve\": \"npx http-server ./dist -p 3001 -c-1\",\n    \"dev\": \"npm run clean && npm run build && npm run serve\",\n    \"clean\": \"rimraf dist\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3\": \"2.2.2\",\n    \"buffer\": \"^6.0.3\",\n    \"chai\": \"^4.3.6\",\n    \"get-func-name\": \"^2.0.2\",\n    \"mocha\": \"^10.0.0\",\n    \"process\": \"^0.11.10\",\n    \"source-map-support\": \"^0.5.21\",\n    \"stream-browserify\": \"^3.0.0\",\n    \"type-detect\": \"^4.1.0\",\n    \"util\": \"^0.12.4\",\n    \"window\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/chai\": \"^4.3.0\",\n    \"@types/mocha\": \"^10.0.10\",\n    \"css-loader\": \"^6.7.2\",\n    \"http-server\": \"^14.1.1\",\n    \"prettier\": \"3.4.1\",\n    \"replace-in-file\": \"^6.3.5\",\n    \"shx\": \"^0.3.4\",\n    \"style-loader\": \"^3.3.1\",\n    \"ts-loader\": \"^9.2.7\",\n    \"typescript\": \"^5.6.3\",\n    \"webpack\": \"^5.69.1\",\n    \"webpack-cli\": \"^4.9.2\"\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/constants.ts",
    "content": "/**\n * Constants used in compliance testing\n */\nconst constants = {\n  ShortWait: 1000,\n  Fdc3Timeout: 500, // The amount of time to wait for the FDC3Ready event during initialisation\n  TestTimeout: 20000, // Tests that take longer than this (in milliseconds) will fail\n  WaitTime: 5000, // The amount of time to wait for mock apps to finish processing\n  WindowCloseWaitTime: 2000, // The amount of time to allow for clean-up of closed windows\n  NoListenerTimeout: 120000, // the amount of time to allow for a DA to timeout waiting on a context or intent listener\n  // FDC3 does not define this timeout so this should be extended if the DA uses a longer timeout\n  ControlChannel: 'app-control', //app channel used for passing messages between mock apps and tests\n} as const;\n\nexport default constants;\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/context-types.ts",
    "content": "export interface CommonContext {\n  id?: {\n    [key: string]: string;\n  };\n  name?: string;\n  type: string;\n}\n\nexport interface AppControlContext extends CommonContext {\n  testId?: string;\n  instanceId?: string;\n  Context?: CommonContext;\n  errorMessage?: string;\n}\n\nexport interface AppControlContextListener {\n  listenerPromise: Promise<AppControlContext>;\n}\n\nexport interface IntentUtilityContext extends CommonContext {\n  delayBeforeReturn?: number;\n  onUnsubscribedTriggered?: boolean;\n  number?: number;\n  instanceId?: string;\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/basic.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { AppControlContext } from '../context-types';\nimport { ControlContextType, Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  try {\n    await fdc3.addContextListener(null, async context => {\n      // broadcast that this app has received context\n      if (context.type === 'fdc3.instrument') {\n        await sendContextToTests(fdc3, {\n          type: ControlContextType.CONTEXT_RECEIVED,\n          context: context,\n        } as AppControlContext);\n      }\n    });\n  } catch (ex) {\n    const message = ex instanceof Error ? ex.message : String(ex);\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.CONTEXT_RECEIVED,\n      errorMessage: message,\n    } as AppControlContext);\n  }\n\n  fdc3.addIntentListener(Intent.lTestingIntent, async context => {\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/channel-command.ts",
    "content": "import { Channel } from '@finos/fdc3';\nimport { ChannelsAppConfig } from '../test/support/channel-control';\nimport { commands } from './constants';\nimport { IChannelService } from './interfaces';\n\nexport class Fdc3CommandExecutor {\n  async executeCommands(orderedCommands: string[], config: ChannelsAppConfig, channelService: IChannelService) {\n    let channel: Channel | undefined;\n\n    //close ChannelsApp when test is complete\n    await channelService.closeWindowOnCompletion(config.testId);\n\n    for (const command of orderedCommands) {\n      switch (command) {\n        case commands.joinRetrievedUserChannel: {\n          channel = await channelService.joinRetrievedUserChannel(config.channelId);\n          break;\n        }\n        case commands.retrieveTestAppChannel: {\n          if (!config.channelId) {\n            throw new Error('Provide `channelId` of an app channel in the config');\n          }\n          channel = await channelService.retrieveTestAppChannel(config.channelId);\n          break;\n        }\n        case commands.broadcastInstrumentContext: {\n          const contextType = config.contextId ? `fdc3.instrument.${config.contextId}` : 'fdc3.instrument';\n          await channelService.broadcastContextItem(contextType, channel!, config.historyItems ?? 1, config.testId);\n          break;\n        }\n        case commands.broadcastContactContext: {\n          const contextType = config.contextId ? `fdc3.contact.${config.contextId}` : 'fdc3.contact';\n          await channelService.broadcastContextItem(contextType, channel!, config.historyItems ?? 1, config.testId);\n          break;\n        }\n      }\n    }\n\n    //notify app A that ChannelsApp has finished executing\n    if (config.notifyAppAOnCompletion) {\n      await channelService.notifyTestOnCompletion(config.testId);\n    }\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/channel.ts",
    "content": "import { ChannelServiceImpl } from './support/channel-support';\nimport { Context, getAgent } from '@finos/fdc3';\nimport { Fdc3CommandExecutor } from './channel-command';\n\ngetAgent().then(fdc3 => {\n  let firedOnce = false;\n\n  fdc3.addContextListener('channelsAppContext', (context: Context) => {\n    if (firedOnce === false && context.type == 'channelsAppContext') {\n      firedOnce = true;\n      const commandExecutor = new Fdc3CommandExecutor();\n      commandExecutor.executeCommands(context.commands, context.config, new ChannelServiceImpl(fdc3));\n    }\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/constants.ts",
    "content": "export const channelType = {\n  system: 'system',\n  app: 'app',\n};\n\nexport const commands = {\n  joinRetrievedUserChannel: 'joinRetrievedUserChannel',\n  retrieveTestAppChannel: 'retrieveTestAppChannel',\n  broadcastInstrumentContext: 'broadcastInstrumentContext',\n  broadcastContactContext: 'broadcastContactContext',\n  joinUserChannelOne: 'joinUserChannelOne',\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/general.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent, Context } from '@finos/fdc3';\nimport { AppControlContext } from '../context-types';\nimport { appIdMatches } from '../utils';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  //used in AOpensB1\n  const implementationMetadata = await fdc3.getInfo();\n  const { appId } = implementationMetadata.appMetadata;\n\n  const appOpenedContext: AppControlContext = {\n    type: 'fdc3-conformance-opened',\n  };\n\n  if (!appIdMatches(appId, 'MockAppId')) {\n    appOpenedContext.errorMessage = `Incorrect appId retrieved from getInfo(). Expected MockAppId, got ${appId}`;\n  }\n\n  // broadcast that this app has opened\n  await sendContextToTests(fdc3, appOpenedContext as AppControlContext);\n\n  // Context listeners used by tests.\n  await fdc3.addContextListener('fdc3.instrument', async context => {\n    // broadcast that this app has received context\n    await sendContextToTests(fdc3, {\n      type: 'context-received',\n      context: context,\n    } as ContextSender);\n  });\n});\n\nexport interface ContextSender extends Context {\n  context?: Context;\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-a.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests, validateContext } from './mock-functions';\nimport { wait } from '../utils';\nimport { IntentUtilityContext } from '../context-types';\nimport { IntentResult, getAgent } from '@finos/fdc3';\nimport { ContextType, ControlContextType, Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  //used in 'Raise Intent Result (void result)' and 'Raise Intent (Ignoring any results)'\n  fdc3.addIntentListener(Intent.aTestingIntent, async (context: IntentUtilityContext): Promise<IntentResult> => {\n    validateContext(fdc3, context.type, ContextType.testContextX);\n    await delayExecution(context.delayBeforeReturn);\n\n    const { appMetadata } = await fdc3.getInfo();\n\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED,\n      instanceId: appMetadata.instanceId,\n    });\n\n    return;\n  });\n\n  fdc3.addIntentListener(Intent.sharedTestingIntent1, async (context: IntentUtilityContext): Promise<IntentResult> => {\n    validateContext(fdc3, context.type, ContextType.testContextY);\n    await delayExecution(context.delayBeforeReturn);\n\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.SHARED_TESTING_INTENT1_LISTENER_TRIGGERED,\n    });\n\n    return context;\n  });\n\n  await sendContextToTests(fdc3, {\n    type: ControlContextType.INTENT_APP_A_OPENED,\n  });\n});\n\nasync function delayExecution(delayMilliseconds: number | undefined): Promise<void> {\n  if (delayMilliseconds && delayMilliseconds > 0) {\n    await wait(delayMilliseconds);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-b.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { wait } from '../utils';\nimport { AppControlContext, IntentUtilityContext } from '../context-types';\nimport { ControlContextType, Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  try {\n    //used in AOpensBMultipleListen\n    await fdc3.addContextListener(null, async context => {\n      // broadcast that this app has received context\n      if (context.type === 'fdc3.instrument') {\n        await sendContextToTests(fdc3, {\n          type: ControlContextType.CONTEXT_RECEIVED,\n          context: context,\n        } as AppControlContext);\n      }\n    });\n  } catch (ex) {\n    const message = ex instanceof Error ? ex.message : String(ex);\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.CONTEXT_RECEIVED,\n      errorMessage: message,\n    } as AppControlContext);\n  }\n\n  //used in 'RaiseIntentContextResult5secs'\n  await fdc3.addIntentListener(Intent.sharedTestingIntent1, async (context: IntentUtilityContext) => {\n    if (context.delayBeforeReturn ?? 0 > 0) {\n      await wait(context.delayBeforeReturn);\n    }\n\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.SHARED_TESTING_INTENT1_LISTENER_TRIGGERED,\n    });\n\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-c.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { AppControlContext } from '../context-types';\nimport { ControlContextType, Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  try {\n    await fdc3.addContextListener(null, async context => {\n      // broadcast that this app has received context\n      if (context.type === 'fdc3.instrument') {\n        await sendContextToTests(fdc3, {\n          type: ControlContextType.CONTEXT_RECEIVED,\n          context: context,\n        } as AppControlContext);\n      }\n    });\n  } catch (ex) {\n    const message = ex instanceof Error ? ex.message : String(ex);\n    await sendContextToTests(fdc3, {\n      type: ControlContextType.CONTEXT_RECEIVED,\n      errorMessage: message,\n    } as AppControlContext);\n  }\n\n  fdc3.addIntentListener(Intent.cTestingIntent, async context => {\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-d.ts",
    "content": "import { closeWindowOnCompletion } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n  fdc3.addIntentListener(Intent.sharedTestingIntent2, async context => {\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-e.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests, validateContext } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { ContextType, ControlContextType, Intent } from '../test/support/intent-support';\nimport constants from '../constants';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n  const { appMetadata } = await fdc3.getInfo();\n\n  fdc3.addIntentListener(Intent.sharedTestingIntent2, async context => {\n    validateContext(fdc3, context.type, ContextType.testContextY);\n    const channel = await fdc3.getOrCreateChannel('test-channel');\n\n    //set-up alert to test framework that the task was completed after a short delay\n    setTimeout(async () => {\n      await sendContextToTests(fdc3, {\n        type: ControlContextType.SHARED_TESTING_INTENT_2_RESULT_SENT,\n        id: { key: 'uniqueId' },\n        instanceId: appMetadata.instanceId,\n      });\n    }, constants.ShortWait);\n\n    return channel;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-f.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests, validateContext } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { ContextType, ControlContextType, Intent } from '../test/support/intent-support';\nimport constants from '../constants';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  const { appMetadata } = await fdc3.getInfo();\n\n  fdc3.addIntentListener(Intent.sharedTestingIntent2, async context => {\n    validateContext(fdc3, context.type, ContextType.testContextY);\n    const privateChannel = await fdc3.createPrivateChannel();\n\n    //set-up alert to test framework that the task was completed after a short delay\n    setTimeout(async () => {\n      await sendContextToTests(fdc3, {\n        type: ControlContextType.SHARED_TESTING_INTENT_2_RESULT_SENT,\n        id: { key: 'uniqueId' },\n        instanceId: appMetadata.instanceId,\n      });\n    }, constants.ShortWait);\n\n    return privateChannel;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-g.ts",
    "content": "import { closeWindowOnCompletion } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n  fdc3.addIntentListener(Intent.sharedTestingIntent2, async context => {\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-h.ts",
    "content": "import { getAgent } from '@finos/fdc3';\nimport { closeWindowOnCompletion } from './mock-functions';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-i.ts",
    "content": "import { closeWindowOnCompletion } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n  fdc3.addIntentListener('MadeUpIntent', async context => {\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-j.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests, validateContext } from './mock-functions';\nimport { ChannelError, getAgent } from '@finos/fdc3';\nimport { ContextType, ControlContextType, Intent } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  //used in 'PrivateChannelsAreNotAppChannels'\n  fdc3.addIntentListener(Intent.privateChannelIsPrivate, async context => {\n    validateContext(fdc3, context.type, ContextType.privateChannelDetails);\n\n    try {\n      await fdc3.getOrCreateChannel(context?.id?.key ?? 'some-new-channel');\n      await sendContextToTests(fdc3, {\n        type: ControlContextType.ERROR,\n        errorMessage: \"No error thrown when calling fdc3.getOrCreateChannel('<idPassedInContext>') from the mock app\",\n      });\n    } catch (ex) {\n      const message = ex instanceof Error ? ex.message : String(ex);\n\n      if (message !== ChannelError.AccessDenied) {\n        await sendContextToTests(fdc3, {\n          type: ControlContextType.ERROR,\n          errorMessage: `Incorrect error received when calling fdc3.getOrCreateChannel('<idPassedInContext>'). Expected AccessDenied, got ${message}`,\n        });\n      }\n    }\n\n    return context;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/intent-k.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests, validateContext } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { wait } from '../utils';\nimport { IntentUtilityContext } from '../context-types';\nimport { ContextType, ControlContextType, Intent } from '../test/support/intent-support';\n\n//used in 'PrivateChannelsLifecycleEvents'\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  fdc3.addIntentListener(Intent.kTestingIntent, async context => {\n    validateContext(fdc3, context.type, ContextType.testContextX);\n    const privChan = await fdc3.createPrivateChannel();\n\n    await privChan.addContextListener(ContextType.testContextX, async () => {\n      await sendContextToTests(fdc3, { type: ContextType.testContextX }); //let test know addContextListener was triggered\n    });\n\n    let contextStreamNumber = 1;\n    privChan.addEventListener('addContextListener', async () => {\n      await wait(100); //wait for listener in test to initialise\n\n      //stream multiple contexts to test in short succession\n      for (let i = 0; i < 5; i++) {\n        const intentKContext: IntentUtilityContext = {\n          type: ContextType.testContextZ,\n          number: contextStreamNumber,\n        };\n\n        await privChan.broadcast(intentKContext);\n        contextStreamNumber++;\n\n        //give broadcast time to run\n        await wait(50);\n      }\n    });\n\n    await privChan.addEventListener('unsubscribe', async () => {\n      //let test know onUnsubscribe was triggered\n      await sendContextToTests(fdc3, { type: ControlContextType.ON_UNSUBSCRIBE_TRIGGERED });\n    });\n\n    await privChan.addEventListener('disconnect', async () => {\n      //let test know onUnsubscribe was triggered\n      await sendContextToTests(fdc3, { type: ControlContextType.ON_DISCONNECT_TRIGGERED });\n    });\n\n    return privChan;\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/interfaces.ts",
    "content": "import { Channel } from '@finos/fdc3';\n\nexport interface IChannelService {\n  joinRetrievedUserChannel(channelId: string): Promise<Channel>;\n\n  retrieveTestAppChannel(channelId: string): Promise<Channel>;\n\n  broadcastContextItem(contextType: string, channel: Channel, historyItems: number, testId: string): Promise<void>;\n\n  closeWindowOnCompletion(testId: string): Promise<void>;\n\n  notifyTestOnCompletion(testId: string): Promise<void>;\n}\n\nexport interface IBroadcastService {\n  broadcast(contextType: string, historyItems: number, channel: Channel, testId: string): Promise<void>;\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/metadata.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { ControlContextType } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n\n  //get context from tests\n  await fdc3.addContextListener('metadataAppContext', async () => {\n    //execute command from test app and send back metadata\n    const implMetadata = await fdc3.getInfo();\n    const metadataContext = {\n      type: ControlContextType.CONTEXT_LISTENER_TRIGGERED,\n      implMetadata: implMetadata,\n    };\n\n    sendContextToTests(fdc3, metadataContext);\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/mock-functions.ts",
    "content": "import { DesktopAgent } from '@finos/fdc3';\nimport constants from '../constants';\nimport { AppControlContext } from '../context-types';\n\nexport const closeWindowOnCompletion = async (fdc3: DesktopAgent) => {\n  const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel);\n  await appControlChannel.addContextListener('closeWindow', async (context: AppControlContext) => {\n    //notify app A that window was closed\n    const closedContext: AppControlContext = {\n      type: 'windowClosed',\n      testId: context.testId,\n    };\n    await appControlChannel.broadcast(closedContext);\n    setTimeout(() => {\n      //yield to make sure the broadcast gets out before we close\n      window.close();\n    }, 5);\n  });\n};\n\nexport const sendContextToTests = async (fdc3: DesktopAgent, context: AppControlContext) => {\n  const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel);\n  await appControlChannel.broadcast(context);\n};\n\nexport const validateContext = (fdc3: DesktopAgent, receivedContextType: string, expectedContextType: string): void => {\n  if (expectedContextType !== receivedContextType) {\n    sendContextToTests(fdc3, {\n      type: 'error',\n      errorMessage: `Incorrect context received for intent 'aTestingIntent. Expected ${expectedContextType}, got ${receivedContextType}`,\n    });\n  }\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/open-a.ts",
    "content": "import { closeWindowOnCompletion, sendContextToTests } from './mock-functions';\nimport { getAgent } from '@finos/fdc3';\nimport { AppControlContext } from '../context-types';\nimport { ControlContextType } from '../test/support/intent-support';\n\ngetAgent().then(async fdc3 => {\n  await closeWindowOnCompletion(fdc3);\n  await fdc3.addContextListener('shouldNotReceiveThisContext', async context => {\n    // broadcast that this app has received context\n    if (context.type !== 'shouldNotReceiveThisContext') {\n      await sendContextToTests(fdc3, {\n        type: ControlContextType.CONTEXT_RECEIVED,\n        errorMessage: `Listener received incorrect context type. Listener listening for 'shouldNotReceiveThisContext' type received '${context.type}' type`,\n      } as AppControlContext);\n    }\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/mock/support/channel-support.ts",
    "content": "import { Channel, DesktopAgent } from '@finos/fdc3';\nimport constants from '../../constants';\nimport { AppControlContext } from '../../context-types';\nimport { channelType } from '../constants';\nimport { IBroadcastService, IChannelService } from '../interfaces';\n\nexport class ChannelServiceImpl implements IChannelService {\n  constructor(fdc3: DesktopAgent) {\n    this.fdc3 = fdc3;\n  }\n\n  private fdc3: DesktopAgent;\n\n  async joinRetrievedUserChannel(channelId: string): Promise<Channel> {\n    const userChannels = await this.fdc3.getUserChannels();\n    const joinedChannel = userChannels.find(c => c.id === channelId);\n    if (joinedChannel) {\n      await this.fdc3.joinUserChannel(channelId);\n      return joinedChannel;\n    } else {\n      throw new Error(`Channel with ID ${channelId} not found in user channels.`);\n    }\n  }\n\n  async retrieveTestAppChannel(channelId: string): Promise<Channel> {\n    return await this.fdc3.getOrCreateChannel(channelId);\n  }\n\n  async broadcastContextItem(\n    contextType: string,\n    channel: Channel,\n    historyItems: number,\n    testId: string\n  ): Promise<void> {\n    const broadcastService = this.getBroadcastService(channel.type);\n    await broadcastService.broadcast(contextType, historyItems, channel, testId);\n  }\n\n  async closeWindowOnCompletion(testId: string): Promise<void> {\n    console.log(Date.now() + ` Setting up closeWindow listener`);\n    const appControlChannel = await this.fdc3.getOrCreateChannel(constants.ControlChannel);\n    await appControlChannel.addContextListener('closeWindow', async () => {\n      console.log(Date.now() + ` Received closeWindow message`);\n      await appControlChannel.broadcast({ type: 'windowClosed', testId: testId } as AppControlContext);\n      setTimeout(() => {\n        //yield to make sure the broadcast gets out before we close\n        window.close();\n      }, 1);\n    });\n  }\n\n  async notifyTestOnCompletion(testId: string): Promise<void> {\n    const appControlChannel = await this.fdc3.getOrCreateChannel(constants.ControlChannel);\n    await this.broadcastContextItem('executionComplete', appControlChannel, 1, testId);\n  }\n\n  //get app/system channel broadcast service\n  private getBroadcastService(currentChannelType: string): IBroadcastService {\n    if (currentChannelType === channelType.app) {\n      return this.appChannelBroadcastService;\n    } else {\n      return this.systemChannelBroadcastService;\n    }\n  }\n\n  //app channel broadcast service\n  private appChannelBroadcastService: IBroadcastService = {\n    broadcast: async (contextType: string, historyItems: number, channel: Channel, testId: string) => {\n      if (channel !== undefined) {\n        for (let i = 0; i < historyItems; i++) {\n          const context: AppControlContext = {\n            type: contextType,\n            name: `History-item-${i + 1}`,\n            testId,\n          };\n          await channel.broadcast(context);\n        }\n      }\n    },\n  };\n\n  //system channel broadcast service\n  private systemChannelBroadcastService: IBroadcastService = {\n    broadcast: async (contextType: string, historyItems: number, _ignored: Channel, testId: string) => {\n      for (let i = 0; i < historyItems; i++) {\n        const context: AppControlContext = {\n          type: contextType,\n          name: `History-item-${i + 1}`,\n          testId,\n        };\n        await this.fdc3.broadcast(context);\n      }\n    },\n  };\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.app-channels.ts",
    "content": "import { assert, expect } from 'chai';\nimport { wait } from '../../utils';\nimport constants from '../../constants';\nimport { APP_CHANNEL_AND_BROADCAST, APP_CHANNEL_AND_BROADCAST_TWICE } from '../support/channel-control';\nimport { ChannelControlImpl } from '../support/channels-support';\nimport { getAgent } from '@finos/fdc3';\nimport { APIDocumentation } from '../support/apiDocuments';\n\nconst documentation = '\\r\\nDocumentation: ' + APIDocumentation.desktopAgent + '\\r\\nCause:';\n\nexport default async () => {\n  const fdc3 = await getAgent();\n  const cc = new ChannelControlImpl(fdc3);\n\n  return describe('fdc3.appChannels', () => {\n    beforeEach(cc.leaveChannel);\n\n    afterEach(async function afterEach() {\n      await cc.closeMockApp(this.currentTest!.title);\n    });\n\n    const acTestId =\n      '(ACBasicUsage1) Should receive context when app a adds a listener and app B broadcasts to the same app channel';\n    it(acTestId, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A adds adds a context listener of type null\\r\\n- App B retrieves the same app channel as A\\r\\n- App B broadcasts context of type fdc3.instrument${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId);\n      let receivedContext = false;\n      const listener1 = await cc.setupAndValidateListener(testChannel, null, 'fdc3.instrument', errorMessage, () => {\n        receivedContext = true;\n      });\n      await cc.openChannelApp(acTestId, testChannel.id, APP_CHANNEL_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener1]);\n      }\n    });\n\n    const acTestId2 =\n      '(ACBasicUsage2) Should receive context when app B broadcasts context to an app channel before A retrieves current context';\n    it(acTestId2, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A & B retrieve the same app channel\\r\\n- App B broadcasts context of type fdc3.instrument\\r\\n- App A retrieves current context of type null${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId2);\n      await cc.openChannelApp(acTestId2, testChannel.id, APP_CHANNEL_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n      let receivedContext = false;\n      await cc.setupContextChecker(testChannel, null, 'fdc3.instrument', errorMessage, () => (receivedContext = true));\n\n      if (!receivedContext) {\n        //allow upto a second for the context to arrive\n        await wait(constants.ShortWait);\n        if (!receivedContext) {\n          assert.fail(`No context received!\\n${errorMessage}`);\n        }\n      }\n    });\n\n    const acTestId4 =\n      '(ACFilteredContext1) Should only receive the listened context when app B broadcasts multiple contexts to the same app channel';\n    it(acTestId4, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A adds a context listener of type fdc3.instrument\\r\\n- App B retrieves the same app channel as A\\r\\n- App B broadcasts a context of type fdc3.instrument and fdc3.contact${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId4);\n      let receivedContext = false;\n      const listener1 = await cc.setupAndValidateListener(\n        testChannel,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => {\n          receivedContext = true;\n        }\n      );\n      await cc.openChannelApp(acTestId4, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener1]);\n      }\n    });\n\n    const acTestId6 =\n      '(ACUnsubscribe) Should not receive context when unsubscribing an app channel before app B broadcasts to that channel';\n    it(acTestId6, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A adds a context listener of type fdc3.instrument\\r\\n- App A unsubscribes the app channel\\r\\n- App B retrieves the same app channel\\r\\n- App B broadcasts a context of type fdc3.instrument and fdc3.contact${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId6);\n\n      const listener = await cc.setupAndValidateListener(\n        testChannel,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /*noop*/\n        }\n      );\n      await cc.unsubscribeListeners([listener]);\n      await cc.openChannelApp(acTestId6, testChannel.id, APP_CHANNEL_AND_BROADCAST);\n\n      await resolveExecutionCompleteListener;\n    });\n\n    const acTestId7 =\n      '(ACFilteredContext2) Should not receive context when app B broadcasts context to a different app channel';\n    it(acTestId7, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A adds a context listener of type fdc3.instrument\\r\\n- App B retrieves a different app channel\\r\\n- App B broadcasts a context of type fdc3.instrument${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const listener = await cc.setupAndValidateListener(\n        testChannel,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /*noop*/\n        }\n      );\n      const differentTestChannel = await cc.createRandomTestChannel();\n      await cc.openChannelApp(acTestId7, differentTestChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await wait(constants.ShortWait); // give listener time to receive context\n      cc.unsubscribeListeners([listener]);\n    });\n\n    const acTestId8 =\n      '(ACFilteredContext3) Should not receive context when retrieving two different app channels before app B broadcasts the listened type to the first channel that was retrieved';\n    it(acTestId8, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A switches to a different app channel\\r\\n- App A adds a context listener of type fdc3.instrument\\r\\n- App B retrieves the first channel that A retrieved\\r\\n- App B broadcasts a context of type fdc3.instrument${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      let receivedContext = false;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId8);\n      const differentAppChannel = await cc.createRandomTestChannel();\n      const listener = await cc.setupAndValidateListener(\n        testChannel,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => {\n          receivedContext = true;\n        }\n      );\n      const listener2 = await cc.setupAndValidateListener(\n        differentAppChannel,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /*noop*/\n        }\n      );\n      await cc.openChannelApp(acTestId8, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener, listener2]);\n      }\n    });\n\n    const acTestId9 =\n      '(ACFilteredContext4) Should not receive context when retrieving two different app channels before the second app broadcasts the listened type to the first channel that was retrieved';\n    it(acTestId9, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App A switches to a different app channel\\r\\n- App A adds a context listener of type fdc3.instrument\\r\\n- App B retrieves the first channel that A retrieved\\r\\n- App B broadcasts a context of type fdc3.instrument${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      let receivedContext = false;\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId9);\n      const differentAppChannel = await cc.createRandomTestChannel();\n      const listener = await cc.setupAndValidateListener(\n        testChannel,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => {\n          receivedContext = true;\n        }\n      );\n      const listener2 = await cc.setupAndValidateListener(\n        differentAppChannel,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /*noop*/\n        }\n      );\n      await cc.openChannelApp(acTestId9, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener, listener2]);\n      }\n    });\n\n    const acTestId10 =\n      '(ACContextHistoryTyped) Should receive both contexts when app B broadcasts both contexts to the same app channel and A gets current context for each type';\n    it(acTestId10, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App B retrieves the same app channel\\r\\n- App B broadcasts a context of type fdc3.instrument and fdc3.contact\\r\\n- App A gets current context for types fdc3.instrument and fdc3.contact${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId10);\n\n      await cc.openChannelApp(acTestId10, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n\n      await cc.setupContextChecker(testChannel, 'fdc3.instrument', 'fdc3.instrument', errorMessage, context => {\n        expect(context.name).to.be.equals('History-item-1', errorMessage);\n      });\n      await cc.setupContextChecker(testChannel, 'fdc3.contact', 'fdc3.contact', errorMessage, context => {\n        expect(context.name).to.be.equals('History-item-1', errorMessage);\n      });\n    });\n\n    const acTestId11 =\n      '(ACContextHistoryMultiple) Should retrieve the last broadcast context item when app B broadcasts a context with multiple history items to the same app channel and A gets current context';\n    it(acTestId11, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App B retrieves the same app channel\\r\\n- App B broadcasts two different contexts of type fdc3.instrument\\r\\n- App A gets current context for types fdc3.instrument${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId11);\n\n      await cc.openChannelApp(acTestId11, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE, 2);\n      await resolveExecutionCompleteListener;\n      await cc.setupContextChecker(testChannel, 'fdc3.instrument', 'fdc3.instrument', errorMessage, context => {\n        expect(context.name).to.be.equals('History-item-2', errorMessage);\n      });\n      await cc.setupContextChecker(testChannel, 'fdc3.contact', 'fdc3.contact', errorMessage, context => {\n        expect(context.name).to.be.equals('History-item-2', errorMessage);\n      });\n    });\n\n    const acTestId12 =\n      '(ACContextHistoryLast) Should retrieve the last broadcast context item when app B broadcasts two different contexts to the same app channel and A gets current context';\n    it(acTestId12, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves an app channel\\r\\n- App B retrieves the same app channel\\r\\n- App B broadcasts a context of type fdc3.instrument and fdc3.contact\\r\\n- App B gets current context with no filter applied${documentation}`;\n\n      const testChannel = await cc.createRandomTestChannel();\n      const resolveExecutionCompleteListener = cc.initCompleteListener(acTestId12);\n      await cc.openChannelApp(acTestId12, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n\n      const context = await testChannel.getCurrentContext();\n\n      if (context === null) {\n        assert.fail('No Context retrieved', errorMessage);\n      } else if (context.type === 'fdc3.instrument') {\n        assert.fail('Did not retrieve last broadcast context from app B', errorMessage);\n      } else {\n        expect(context.type).to.be.equals('fdc3.contact', errorMessage);\n      }\n    });\n  });\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.findInstances.ts",
    "content": "import { assert, expect } from 'chai';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { handleFail, wrapPromise } from '../../utils';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport { IntentUtilityContext } from '../../context-types';\nimport { MetadataFdc3Api } from '../support/metadata-support';\nimport { ContextType, ControlContextType, Intent, IntentApp, RaiseIntentControl } from '../support/intent-support';\nimport { AppIdentifier, DesktopAgent, getAgent, IntentResolution, Listener } from '@finos/fdc3';\n\nconst findInstancesDocs = '\\r\\nDocumentation: ' + APIDocumentation.findInstances + '\\r\\nCause: ';\n\nexport default async () =>\n  describe('fdc3.findInstances', function () {\n    this.timeout(5000);\n\n    let control: RaiseIntentControl;\n    let fdc3: DesktopAgent;\n\n    beforeEach(async () => {\n      fdc3 = await getAgent();\n      control = new RaiseIntentControl(fdc3);\n    });\n\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test', 2);\n    });\n\n    const findInstances = '(FindInstances) valid appID when opening multiple instances of the same app';\n    it(findInstances, async () => {\n      const api = new MetadataFdc3Api();\n      let listener: Listener | undefined;\n\n      try {\n        const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA); // open IntentAppA\n        const appIdentifier2 = await control.openIntentApp(IntentApp.IntentAppA); // open second instance of IntentAppA\n\n        //confirm that the instanceId for both app instantiations is different\n        expect(\n          appIdentifier.instanceId,\n          `The AppIdentifier's instanceId property for both instances of the opened app should not be the same.${findInstancesDocs}`\n        ).to.not.equal(appIdentifier2.instanceId);\n\n        const instances = await control.findInstances(IntentApp.IntentAppA);\n        validateInstances(instances, appIdentifier, appIdentifier2);\n\n        const wrapper = wrapPromise();\n        const appControlChannel = await api.retrieveAppControlChannel();\n\n        //ensure appIdentifier received the raised intent\n        listener = await appControlChannel.addContextListener(\n          ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED,\n          (context: IntentUtilityContext) => {\n            expect(\n              context['instanceId'],\n              'the raised intent was received by a different instance of the mock app than expected'\n            ).to.be.equals(appIdentifier.instanceId);\n            wrapper.resolve();\n          }\n        );\n\n        const resolution = await api.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, appIdentifier); // raise an intent that targets appIdentifier\n        validateResolutionSource(resolution, appIdentifier);\n        await wrapper.promise; // wait for context from IntentAppA\n      } catch (ex) {\n        handleFail(findInstancesDocs, ex);\n      } finally {\n        if (listener) {\n          control.unsubscribeListener(listener);\n        }\n      }\n    });\n  });\n\nfunction validateResolutionSource(resolution: IntentResolution, appIdentifier: AppIdentifier) {\n  // check that resolution.source matches the appIdentifier\n  expect(\n    resolution.source.appId,\n    \"IntentResolution.source.appId did not match the mock app's AppIdentifier's appId\"\n  ).to.be.equal(appIdentifier.appId);\n  expect(\n    resolution.source.instanceId,\n    \"IntentResolution.source.instanceId did not match the mock app's AppIdentifier's instanceId\"\n  ).to.be.equal(appIdentifier.instanceId);\n}\n\nfunction validateInstances(instances: AppIdentifier[], appIdentifier: AppIdentifier, appIdentifier2: AppIdentifier) {\n  // check that the retrieved instances match both the retrieved appIdentifiers\n  const compareAppIdentifiers = (a: AppIdentifier, b: AppIdentifier) =>\n    a.appId === b.appId && a.instanceId === b.instanceId;\n\n  if (\n    !(\n      instances.some(instance => compareAppIdentifiers(instance, appIdentifier)) &&\n      instances.some(instance => compareAppIdentifiers(instance, appIdentifier2))\n    )\n  ) {\n    assert.fail(\n      `At least one AppIdentifier object is missing from the AppIdentifier array returned after calling fdc3.findInstances(app: AppIdentifier)${findInstancesDocs}`\n    );\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.findIntent.ts",
    "content": "import { AppIntent, IntentMetadata, ResolveError, DesktopAgent } from '@finos/fdc3';\nimport { assert, expect } from 'chai';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { ContextType, IntentApp, Intent } from '../support/intent-support';\nimport { appIdMatches } from '../../utils';\n\ndeclare let fdc3: DesktopAgent;\nconst findIntentDocs = '\\r\\nDocumentation: ' + APIDocumentation.findIntent + '\\r\\nCause';\n\n/**\n * Details on the mock apps used in these tests can be found in /mock/README.md\n */\nexport default async () =>\n  describe('fdc3.findIntent', () => {\n    it(\"(FindIntentAppD) Should find intent 'aTestingIntent' belonging only to app intent-a\", async () => {\n      const appIntent = await fdc3.findIntent(Intent.aTestingIntent);\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.aTestingIntent, displayName: 'A Testing Intent' },\n        IntentApp.IntentAppA\n      );\n    });\n\n    it('(FindNonExistentIntentAppD) Should throw NoAppsFound error when intent does not exist', async () => {\n      try {\n        await fdc3.findIntent('nonExistentIntent');\n        assert.fail('No error was thrown', findIntentDocs);\n      } catch (ex) {\n        expect(ex).to.have.property('message', ResolveError.NoAppsFound, findIntentDocs);\n      }\n    });\n\n    it(\"(FindIntentAppDRightContext) Should find intent 'aTestingIntent' belonging only to app intent-a with context 'testContextX'\", async () => {\n      const appIntent = await fdc3.findIntent(Intent.aTestingIntent, { type: ContextType.testContextX });\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.aTestingIntent, displayName: 'A Testing Intent' },\n        IntentApp.IntentAppA\n      );\n    });\n\n    it('(FindIntentAppDWrongContext) Should throw NoAppsFound error when intent exists but context does not', async () => {\n      try {\n        await fdc3.findIntent(Intent.aTestingIntent, { type: ContextType.testContextY });\n        assert.fail('No error was thrown', findIntentDocs);\n      } catch (ex) {\n        expect(ex).to.have.property('message', ResolveError.NoAppsFound, findIntentDocs);\n      }\n    });\n\n    it(\"(FindIntentAppDMultiple1) Should find intent 'sharedTestingIntent2' belonging to multiple apps (intent-a & intent-b)\", async () => {\n      const appIntent = await fdc3.findIntent(Intent.sharedTestingIntent2);\n      validateAppIntent(\n        appIntent,\n        6,\n        { name: Intent.sharedTestingIntent2, displayName: 'Shared Testing Intent 2' },\n        IntentApp.IntentAppD\n      );\n    });\n\n    it(\"(IntentAppDMultiple2) Should find intent 'sharedTestingIntent2' belonging to multiple apps (intent-a & intent-b) filtered by specific context 'testContextY'\", async () => {\n      const appIntent = await fdc3.findIntent(Intent.sharedTestingIntent2, { type: ContextType.testContextY });\n      validateAppIntent(\n        appIntent,\n        5,\n        { name: Intent.sharedTestingIntent2, displayName: 'Shared Testing Intent 2' },\n        IntentApp.IntentAppE\n      );\n    });\n\n    it(\"(FindIntentAppDByResultSingle) Should find intent 'cTestingIntent' belonging only to app intent-c with context 'testContextX' and result type 'testContextZ'\", async () => {\n      const appIntent = await fdc3.findIntent(\n        Intent.cTestingIntent,\n        { type: ContextType.testContextX },\n        ContextType.testContextZ\n      );\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.cTestingIntent, displayName: 'C Testing Intent' },\n        IntentApp.IntentAppC\n      );\n    });\n\n    it(\"(FindIntentAppDByResultSingleNullContext) Should find intent 'cTestingIntent' belonging only to app intent-c with a null context and result type 'testContextZ'\", async () => {\n      const appIntent = await fdc3.findIntent(Intent.cTestingIntent, undefined, ContextType.testContextZ);\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.cTestingIntent, displayName: 'C Testing Intent' },\n        IntentApp.IntentAppC\n      );\n    });\n\n    it(\"(FindIntentAppDByResultMultiple) Should find intent 'sharedTestingIntent1' belonging only to app intent-b with context 'testContextX' and result type 'testContextY'\", async () => {\n      const appIntent = await fdc3.findIntent(\n        Intent.sharedTestingIntent1,\n        { type: ContextType.testContextX },\n        ContextType.testContextY\n      );\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.sharedTestingIntent1, displayName: 'Shared Testing Intent 1' },\n        IntentApp.IntentAppB\n      );\n    });\n\n    it(\"(FindIntentAppDByResultChannel1) Should find intent 'sharedTestingIntent2' belonging only to apps intent-e and itent-f with context 'testContextY' and result type 'channel\", async () => {\n      const appIntent = await fdc3.findIntent(\n        Intent.sharedTestingIntent2,\n        { type: ContextType.testContextY },\n        'channel'\n      );\n      validateAppIntent(\n        appIntent,\n        2,\n        { name: Intent.sharedTestingIntent2, displayName: 'Shared Testing Intent 2' },\n        IntentApp.IntentAppE\n      );\n    });\n\n    it(\"(FindIntentAppDByResultChannel2) Should find intent 'sharedTestingIntent2' belonging only to app intent-c with context 'testContextY' and result type 'channel<testContextZ>'\", async () => {\n      const appIntent = await fdc3.findIntent(\n        Intent.sharedTestingIntent2,\n        { type: ContextType.testContextY },\n        'channel<testContextZ>'\n      );\n      validateAppIntent(\n        appIntent,\n        1,\n        { name: Intent.sharedTestingIntent2, displayName: 'Shared Testing Intent 2' },\n        IntentApp.IntentAppF\n      );\n    });\n  });\n\nfunction validateAppIntent(\n  appIntent: AppIntent,\n  expectedNumberOfApps: number,\n  expectedIntentMetadata: IntentMetadata,\n  firstIntentAppToValidate: IntentApp\n) {\n  expect(appIntent.intent).to.deep.eq(\n    {\n      name: expectedIntentMetadata.name,\n      displayName: expectedIntentMetadata.displayName,\n    },\n    findIntentDocs\n  );\n\n  expect(\n    appIntent.apps,\n    `Unexpected AppIntent.apps.length. Expected ${expectedNumberOfApps}, got ${appIntent.apps.length}${findIntentDocs}`\n  ).to.have.length(expectedNumberOfApps);\n\n  const intentApps = Object.values(IntentApp);\n  const position = intentApps.indexOf(firstIntentAppToValidate);\n  const appsThatNeedValidating = intentApps.splice(position, expectedNumberOfApps);\n\n  appsThatNeedValidating.forEach((appId, index) => {\n    expect(\n      appIntent.apps[index],\n      `AppIntent.apps[${index}] did not have expected property 'appId' ${findIntentDocs}`\n    ).to.have.property('appId');\n    expect(\n      appIdMatches(appIntent.apps[index].appId, appId),\n      `AppIntent.apps[${index}].appId '${appIntent.apps[index].appId}' did not match expected '${appId}' ${findIntentDocs}`\n    ).to.be.true;\n  });\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.findIntentsByContext.ts",
    "content": "import { AppIntent, ResolveError } from '@finos/fdc3';\nimport { assert, expect } from 'chai';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { DesktopAgent } from '@finos/fdc3';\nimport { ContextType, IntentApp, Intent } from '../support/intent-support';\nimport { appIdMatches, handleFail } from '../../utils';\n\ndeclare let fdc3: DesktopAgent;\nconst findIntentsByContextDocs = '\\r\\nDocumentation: ' + APIDocumentation.findIntentsByContext;\n\n/**\n * Details on the mock apps used in these tests can be found in /mock/README.md\n */\nexport default async () =>\n  describe('fdc3.findIntentsByContext', () => {\n    it(\"(FindIntentByContextSingleContext) Should find intents by context 'testContextX'\", async () => {\n      try {\n        const intents = await fdc3.findIntentsByContext({ type: ContextType.testContextX });\n        expect(intents).to.have.length(5);\n        const intentNames = intents.map(appIntent => appIntent.intent.name);\n        expect(intentNames).to.have.all.members([\n          Intent.aTestingIntent,\n          Intent.sharedTestingIntent1,\n          Intent.cTestingIntent,\n          Intent.sharedTestingIntent2,\n          Intent.kTestingIntent,\n        ]);\n\n        validateIntents(intents, Intent.aTestingIntent, 1, [IntentApp.IntentAppA]);\n        validateIntents(intents, Intent.sharedTestingIntent1, 2, [IntentApp.IntentAppA, IntentApp.IntentAppB]);\n        validateIntents(intents, Intent.cTestingIntent, 1, [IntentApp.IntentAppC]);\n        validateIntents(intents, Intent.sharedTestingIntent2, 1, [IntentApp.IntentAppD]);\n        validateIntents(intents, Intent.kTestingIntent, 1, [IntentApp.IntentAppK]);\n      } catch (ex) {\n        handleFail(findIntentsByContextDocs, ex);\n      }\n    });\n\n    it('(FindIntentByContextWrongIntentAppD) Passing an invalid context causes a NoAppsFound error to be thrown', async () => {\n      const context = {\n        type: 'ThisContextDoesNotExist',\n      };\n      try {\n        await fdc3.findIntentsByContext(context);\n        assert.fail('Expected error NoAppsFound not thrown', findIntentsByContextDocs);\n      } catch (ex) {\n        expect(ex).to.have.property('message', ResolveError.NoAppsFound, findIntentsByContextDocs);\n      }\n    });\n  });\n\nfunction validateIntents(\n  intents: AppIntent[],\n  intentFilter: string,\n  expectedAppCount: number,\n  expectedAppIds: string[]\n) {\n  const firstIntent = intents.find(appIntent => appIntent.intent.name === intentFilter);\n  assert.isDefined(firstIntent);\n  if (firstIntent !== undefined) {\n    expect(firstIntent.apps).to.have.length(expectedAppCount);\n    const sharedAppIds = firstIntent.apps.map(app => app.appId);\n    const missingAppIds = expectedAppIds.filter(\n      expected => !sharedAppIds.some(received => appIdMatches(received, expected))\n    );\n    expect(missingAppIds, `Expected app IDs not found in [${sharedAppIds.join(', ')}]`).to.be.empty;\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.getAppMetadata.ts",
    "content": "import { expect } from 'chai';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { MetadataFdc3Api, MetadataValidator } from '../support/metadata-support';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport { handleFail } from '../../utils';\n\nconst getMetadataDocs = '\\r\\nDocumentation: ' + APIDocumentation.appMetadata + '\\r\\nCause: ';\nconst validator = new MetadataValidator();\nconst api = new MetadataFdc3Api();\n\nexport default async () =>\n  describe('fdc3.getAppMetadata', () => {\n    after(async () => {\n      await closeMockAppWindow(appInstanceMetadata);\n    });\n\n    it('Method is callable', async () => {\n      try {\n        await api.getAppMetadata();\n      } catch (ex) {\n        handleFail(getMetadataDocs, ex);\n      }\n    });\n\n    it('(GetAppMetadata) Valid metadata object', async () => {\n      try {\n        //retrieve AppMetadata object\n        const metadata = await api.getAppMetadata();\n        validator.validateAppMetadata(metadata);\n      } catch (ex) {\n        handleFail(getMetadataDocs, ex);\n      }\n    });\n\n    const appInstanceMetadata = '(AppInstanceMetadata) App instance metadata is valid';\n    it(appInstanceMetadata, async () => {\n      try {\n        const appIdentifier1 = await api.openMetadataApp();\n        validator.validateAppIdentifier(appIdentifier1);\n\n        const appIdentifier2 = await api.openMetadataApp(); //open a second instance of the same app\n        validator.validateAppIdentifier(appIdentifier2);\n\n        // check instanceId is different for both instantiations of the app\n        expect(\n          appIdentifier1.instanceId,\n          `The AppIdentifier instanceId properties for both instances of the opened app should not match.${getMetadataDocs}`\n        ).to.not.equal(appIdentifier2.instanceId);\n\n        const metadata1 = await api.getAppMetadata(appIdentifier1);\n        validator.validateAppMetadata(metadata1);\n\n        validateMatchingInstanceIds(\n          metadata1.instanceId ?? 'unknown-md1-id',\n          appIdentifier1.instanceId ?? 'unknown-app1-id'\n        );\n\n        const metadata2 = await api.getAppMetadata(appIdentifier2);\n\n        expect(\n          metadata2,\n          `The AppIdentifier object should contain an instanceId property.${getMetadataDocs}`\n        ).to.have.property('instanceId');\n\n        validateMatchingInstanceIds(\n          metadata2.instanceId ?? 'unknown-md2-id',\n          appIdentifier2.instanceId ?? 'unknown-app2-id'\n        );\n      } catch (ex) {\n        handleFail(getMetadataDocs, ex);\n      }\n    });\n  });\n\nfunction validateMatchingInstanceIds(instanceId1: string, instanceId2: string) {\n  expect(instanceId1, 'The AppMetaData instanceId properties do not match').to.be.equal(instanceId2);\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.getInfo.ts",
    "content": "import { expect } from 'chai';\nimport { handleFail, wrapPromise } from '../../utils';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport { ImplementationMetadata, Listener } from '@finos/fdc3';\nimport { MetadataValidator, MetadataContext, MetadataFdc3Api } from '../support/metadata-support';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { ControlContextType } from '../support/intent-support';\n\nconst getInfoDocs = '\\r\\nDocumentation: ' + APIDocumentation.getInfo + '\\r\\nCause';\nconst validator = new MetadataValidator();\nconst api = new MetadataFdc3Api();\n\nexport default async () =>\n  describe('fdc3.getInfo', () => {\n    let listener: Listener | undefined;\n\n    it('Method is callable', async () => {\n      try {\n        await api.getInfo();\n      } catch (ex) {\n        handleFail(getInfoDocs, ex);\n      }\n    });\n\n    it('(GetInfo1) Returns a valid ImplementationMetadata object', async () => {\n      try {\n        const implMetadata = await api.getInfo();\n        validator.validateImplementationMetadata(implMetadata);\n      } catch (ex) {\n        handleFail(getInfoDocs, ex);\n      }\n    });\n\n    it('(GetInfo2) Returns a valid ImplementationMetadata object', async function () {\n      this.timeout(10000);\n\n      try {\n        let implMetadata: ImplementationMetadata | undefined;\n        const appControlChannel = await api.retrieveAppControlChannel();\n\n        const wrapper = wrapPromise();\n\n        listener = await appControlChannel.addContextListener(\n          ControlContextType.CONTEXT_LISTENER_TRIGGERED,\n          async (context: MetadataContext) => {\n            implMetadata = context.implMetadata;\n            wrapper.resolve();\n          }\n        );\n\n        const appIdentifier = await api.openMetadataApp('metadataAppContext');\n        validator.validateAppIdentifier(appIdentifier);\n\n        await wrapper.promise; // wait for listener above to receive context\n\n        // validate ImplementationMetadata\n        expect(implMetadata, `ImplementationMetadata did not have property appMetadata${getInfoDocs}`).to.have.property(\n          'appMetadata'\n        );\n        validator.validateAppIdentifier(implMetadata?.appMetadata);\n\n        // make sure appId and instanceId from the imlMetadata and appIdentifier objects match\n        expect(\n          implMetadata!.appMetadata.appId,\n          `ImplementationMetadata.appMetadata.appId did not match the ApplicationIdentifier.appId retrieved from the opened app`\n        ).to.be.equal(appIdentifier.appId);\n        expect(\n          implMetadata!.appMetadata.instanceId,\n          `ImplementationMetadata.appMetadata.instanceId did not match the ApplicationIdentifier.instanceId retrieved from the opened app`\n        ).to.be.equal(appIdentifier.instanceId);\n\n        // validate AppMetadata\n        const metadata = await api.getAppMetadata();\n        validator.validateAppMetadata(metadata);\n      } finally {\n        await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n\n        if (listener) {\n          listener.unsubscribe();\n          listener = undefined;\n        }\n      }\n    });\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.open.ts",
    "content": "import constants from '../../constants';\nimport { openApp, OpenCommonConfig } from '../support/open-control';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { OpenControlImpl } from '../support/open-support';\nimport { DesktopAgent, getAgent } from '@finos/fdc3';\nimport { assert, expect } from 'chai';\nimport { ControlContextType } from '../support/intent-support';\nimport { appIdMatches } from '../../utils';\n\nconst documentation = '\\r\\nDocumentation: ' + APIDocumentation + '\\r\\nCause:';\n\nconst config: OpenCommonConfig = {\n  target: 'AppIdentifier',\n  targetMultiple: 'AppIdentifier',\n};\n\nexport default async () => {\n  let control: OpenControlImpl;\n  let fdc3: DesktopAgent;\n\n  beforeEach(async () => {\n    fdc3 = await getAgent();\n    control = new OpenControlImpl(fdc3);\n  });\n\n  return describe('fdc3.open', () => {\n    const AOpensB3 = `(AOpensB3) Can open app B from app A with no context and ${config.targetMultiple} as config.target`;\n    it(AOpensB3, async () => {\n      const targetApp = control.createTargetAppIdentifier(openApp.b.id);\n      const result = control.contextReceiver('fdc3-conformance-opened');\n      await control.openMockApp(targetApp);\n      await result;\n      await control.closeMockApp(AOpensB3);\n    });\n\n    const AFailsToOpenB3 = `(AFailsToOpenB3) Receive AppNotFound error when targeting non-existent app AppMetadata (${config.targetMultiple}) as config.target`;\n    it(AFailsToOpenB3, async () => {\n      try {\n        const targetApp = control.createTargetAppIdentifier('ThisAppDoesNotExist');\n        await control.openMockApp(targetApp);\n        assert.fail('No error was not thrown', documentation);\n      } catch (ex) {\n        control.confirmAppNotFoundErrorReceived(ex);\n      }\n    });\n\n    const AOpensBWithContext3 = `(AOpensBWithContext3) Can open app B from app A with context and AppMetadata (${config.targetMultiple}) as target, app B adds generic listener`;\n    it(AOpensBWithContext3, async () => {\n      const context = { type: 'fdc3.instrument', name: 'context' };\n      const targetApp = control.createTargetAppIdentifier(openApp.b.id);\n      const receiver = control.contextReceiver(ControlContextType.CONTEXT_RECEIVED);\n      await control.openMockApp(targetApp, context);\n      await control.validateReceivedContext(await receiver, 'fdc3.instrument');\n      await control.closeMockApp(AOpensBWithContext3);\n    });\n\n    const AOpensBWithSpecificContext = `(AOpensBWithSpecificContext) Can open app B from app A with context and ${config.targetMultiple} as config.target and app B is expecting context`;\n    it(AOpensBWithSpecificContext, async () => {\n      const context = { type: 'fdc3.instrument', name: 'context' };\n      const targetApp = control.createTargetAppIdentifier(openApp.b.id);\n      const receiver = control.contextReceiver(ControlContextType.CONTEXT_RECEIVED);\n      await control.openMockApp(targetApp, context);\n      await control.validateReceivedContext(await receiver, 'fdc3.instrument');\n      await control.closeMockApp(AOpensBWithSpecificContext);\n    });\n\n    const AOpensBMultipleListen = `(AOpensBMultipleListen) Can open app B from app A with context and ${config.targetMultiple} as config.target but app B has multiple listeners added before the correct one`;\n    it(AOpensBMultipleListen, async () => {\n      const context = { type: 'fdc3.instrument', name: 'context' };\n      const targetApp = control.createTargetAppIdentifier(openApp.b.id);\n      const receiver = control.contextReceiver(ControlContextType.CONTEXT_RECEIVED);\n      await control.openMockApp(targetApp, context);\n      await receiver;\n      await control.validateReceivedContext(await receiver, 'fdc3.instrument');\n      await control.closeMockApp(AOpensBMultipleListen);\n    });\n\n    const AOpensBWithWrongContext = `(AOpensBWithWrongContext) Received App timeout when opening app B with fake context, app b listening for different context`;\n    it(AOpensBWithWrongContext, async () => {\n      await control.addListenerAndFailIfReceived();\n      const targetApp = control.createTargetAppIdentifier(openApp.b.id);\n      let closed = false;\n      setTimeout(() => {\n        if (!closed) {\n          control.closeMockApp(AOpensBWithWrongContext);\n          closed = true;\n        }\n      }, constants.NoListenerTimeout + 100);\n\n      await control.expectAppTimeoutErrorOnOpen(targetApp);\n      if (!closed) {\n        control.closeMockApp(AOpensBWithWrongContext);\n        closed = true;\n      }\n    }).timeout(constants.NoListenerTimeout + 2000);\n\n    const AOpensB4 =\n      '(AOpensB4) Can open app B from app A with appId as config.target, and recieves the same appId and also contains InstanceId';\n    it(AOpensB4, async () => {\n      const result = control.contextReceiver('fdc3-conformance-opened');\n      const targetApp = { appId: openApp.b.id };\n      const instanceIdentifier = await control.openMockApp(targetApp);\n      expect(appIdMatches(instanceIdentifier.appId, openApp.b.id)).to.be.true;\n      expect(instanceIdentifier).to.have.property('instanceId');\n      await result;\n      await control.closeMockApp(AOpensB4);\n    });\n  });\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.raiseIntent-NoAppsFound.ts",
    "content": "import { DesktopAgent, getAgent, ResolveError } from '@finos/fdc3';\nimport { assert, expect } from 'chai';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { ContextType, IntentApp, Intent, RaiseIntentControl } from '../support/intent-support';\nimport constants from '../../constants';\nimport { wait } from '../../utils';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\n\nconst raiseIntentDocs = '\\r\\nDocumentation: ' + APIDocumentation.raiseIntent + '\\r\\nCause';\n\n/**\n * Details on the mock apps used in these tests can be found in /mock/README.md\n */\nexport default async () =>\n  describe('fdc3.raiseIntent (throws error)', () => {\n    let control: RaiseIntentControl;\n    let fdc3: DesktopAgent;\n\n    beforeEach(async () => {\n      fdc3 = await getAgent();\n      control = new RaiseIntentControl(fdc3);\n    });\n\n    const RaiseIntentFailedResolve =\n      \"(RaiseIntentFailedResolve) Should fail to raise intent when targeted app intent-a, context 'testContextY' and intent 'aTestingIntent' do not correlate\";\n\n    it(RaiseIntentFailedResolve, async () => {\n      try {\n        await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextY);\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.NoAppsFound);\n      }\n    });\n\n    const RaiseIntentFailTargetedAppInstanceResolve1 =\n      \"(RaiseIntentFailTargetedAppInstanceResolve1) Should fail to raise intent when targeted app intent-a instance, context 'testContextY', intent 'aTestingIntent' and AppIdentifier IntentAppAId do not correlate\";\n    it(RaiseIntentFailTargetedAppInstanceResolve1, async () => {\n      try {\n        const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA);\n        await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextY, appIdentifier);\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.NoAppsFound);\n      }\n    });\n\n    const RaiseIntentFailTargetedAppInstanceResolve2 =\n      \"(RaiseIntentFailTargetedAppInstanceResolve2) Should fail to raise intent when targeted app intent-a, context 'testContextY', intent 'aTestingIntent' and AppIdentifier IntentAppAId with instanceId property NonExistentInstanceId do not correlate\";\n    it(RaiseIntentFailTargetedAppInstanceResolve2, async () => {\n      try {\n        await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, {\n          appId: IntentApp.IntentAppA,\n          instanceId: 'NonExistentInstanceId',\n        });\n        await wait(); // give test time to throw error\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex).to.have.property('message', ResolveError.TargetInstanceUnavailable);\n      }\n    });\n\n    const RaiseIntentFailTargetedAppResolve1 =\n      \"(RaiseIntentFailTargetedAppResolve1) Should fail to raise intent when targeted app intent-a, context 'testContextY', intent 'aTestingIntent' and AppIdentifier IntentAppAId do not correlate\";\n    it(RaiseIntentFailTargetedAppResolve1, async () => {\n      try {\n        await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextY, { appId: IntentApp.IntentAppA });\n        await wait(); // give test time to throw error\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.NoAppsFound);\n      }\n    });\n\n    const RaiseIntentFailTargetedAppResolve2 =\n      \"(RaiseIntentFailTargetedAppResolve2) Should fail to raise intent when targeting non-existent app id, context 'testContextY', intent 'aTestingIntent' and throw TargetAppUnavailable error\";\n    it(RaiseIntentFailTargetedAppResolve2, async () => {\n      try {\n        await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, { appId: 'NonExistentApp' });\n        await wait(); // give test time to throw error\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.TargetAppUnavailable);\n      }\n    });\n\n    const RaiseIntentFailTargetedAppResolve3 =\n      \"(RaiseIntentFailTargetedAppResolve3) Should fail to raise intent when targeting an app that doesn't add an intent listener, context 'testContextY', intent 'sharedTestingIntent2' and throw IntentDeliveryFailed error\";\n    it(RaiseIntentFailTargetedAppResolve3, async () => {\n      try {\n        await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, {\n          appId: IntentApp.IntentAppH,\n        });\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.IntentDeliveryFailed);\n      }\n      await closeMockAppWindow(RaiseIntentFailTargetedAppResolve3);\n    }).timeout(constants.NoListenerTimeout + 1000);\n\n    const RaiseIntentFailTargetedAppResolve4 =\n      \"(RaiseIntentFailTargetedAppResolve4) Should fail to raise intent when targeting an app that doesn't add an intent listener of the matching type, context 'testContextY', intent 'sharedTestingIntent2' and throw IntentDeliveryFailed error\";\n    it(RaiseIntentFailTargetedAppResolve4, async () => {\n      try {\n        await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, {\n          appId: IntentApp.IntentAppI,\n        });\n        assert.fail('Expected the raised intent to be rejected with an error but no error was thrown');\n      } catch (ex) {\n        expect(ex, raiseIntentDocs).to.have.property('message', ResolveError.IntentDeliveryFailed);\n      }\n      await closeMockAppWindow(RaiseIntentFailTargetedAppResolve4);\n    }).timeout(constants.NoListenerTimeout + 1000);\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.raiseIntent-Result.ts",
    "content": "import { DesktopAgent, getAgent, Listener } from '@finos/fdc3';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport {\n  RaiseIntentControl,\n  IntentResultType,\n  IntentApp,\n  ContextType,\n  Intent,\n  ControlContextType,\n} from '../support/intent-support';\nimport constants from '../../constants';\n\nexport default async () =>\n  describe('fdc3.raiseIntent (Result)', () => {\n    let errorListener: Listener | undefined = undefined;\n    let control: RaiseIntentControl;\n    let fdc3: DesktopAgent;\n\n    beforeEach(async () => {\n      fdc3 = await getAgent();\n      control = new RaiseIntentControl(fdc3);\n    });\n\n    afterEach(async function afterEach() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown test');\n\n      if (errorListener) {\n        errorListener.unsubscribe();\n        errorListener = undefined;\n      }\n    });\n\n    const RaiseIntentVoidResult0secs = '(RaiseIntentVoidResult0secs) App A receives a void IntentResult';\n    it(RaiseIntentVoidResult0secs, async () => {\n      errorListener = await control.listenForError();\n      const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX);\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n      const intentResult = await control.getIntentResult(intentResolution);\n      control.validateIntentResult(intentResult, IntentResultType.Void);\n    });\n\n    const RaiseIntentVoidResult5secs =\n      '(RaiseIntentVoidResult5secs) App A receives a void IntentResult after a 5 second delay';\n    it(RaiseIntentVoidResult5secs, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED, 8000);\n      const intentResolution = await control.raiseIntent(\n        Intent.aTestingIntent,\n        ContextType.testContextX,\n        undefined,\n        5000\n      );\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.Void);\n      }\n    });\n\n    const RaiseIntentContextResult0secs = '(RaiseIntentContextResult0secs) IntentResult resolves to testContextY';\n    it(RaiseIntentContextResult0secs, async () => {\n      errorListener = await control.listenForError();\n      const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextY);\n      control.validateIntentResolution(IntentApp.IntentAppB, intentResolution);\n      const intentResult = await control.getIntentResult(intentResolution);\n      control.validateIntentResult(intentResult, IntentResultType.Context, ContextType.testContextY);\n    });\n\n    const RaiseIntentContextResult5secs =\n      '(RaiseIntentContextResult5secs) IntentResult resolves to testContextY instance after a 5 second delay';\n    it(RaiseIntentContextResult5secs, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(ControlContextType.SHARED_TESTING_INTENT1_LISTENER_TRIGGERED, 8000);\n      const intentResolution = await control.raiseIntent(\n        Intent.sharedTestingIntent1,\n        ContextType.testContextY,\n        undefined,\n        5000\n      );\n      control.validateIntentResolution(IntentApp.IntentAppB, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.Context, ContextType.testContextY);\n      }\n    });\n\n    const RaiseIntentChannelResult = '(RaiseIntentChannelResult) IntentResult resolves to a Channel object';\n    it(RaiseIntentChannelResult, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(\n        ControlContextType.SHARED_TESTING_INTENT_2_RESULT_SENT,\n        constants.WaitTime\n      );\n      const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, {\n        appId: IntentApp.IntentAppE,\n      });\n      control.validateIntentResolution(IntentApp.IntentAppE, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.Channel, (await receiver).instanceId);\n      }\n    });\n\n    const RaiseIntentPrivateChannelResult =\n      '(RaiseIntentPrivateChannelResult) IntentResult resolves to a private Channel object';\n    it(RaiseIntentPrivateChannelResult, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(\n        ControlContextType.SHARED_TESTING_INTENT_2_RESULT_SENT,\n        constants.WaitTime\n      );\n      const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, {\n        appId: IntentApp.IntentAppF,\n      });\n      control.validateIntentResolution(IntentApp.IntentAppF, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.PrivateChannel, (await receiver).instanceId);\n      }\n    });\n\n    const RaiseIntentVoidResult61secs =\n      '(RaiseIntentVoidResult61secs) App A receives a void IntentResult after a 61 second delay';\n    it(RaiseIntentVoidResult61secs, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED, 64000);\n      const intentResolution = await control.raiseIntent(\n        Intent.aTestingIntent,\n        ContextType.testContextX,\n        undefined,\n        61000\n      );\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.Void);\n      }\n    }).timeout(80000);\n\n    const RaiseIntentContextResult61secs =\n      '(RaiseIntentContextResult61secs) IntentResult resolves to testContextY instance after a 61 second delay';\n    it(RaiseIntentContextResult61secs, async () => {\n      errorListener = await control.listenForError();\n      const receiver = control.receiveContext(ControlContextType.SHARED_TESTING_INTENT1_LISTENER_TRIGGERED, 64000);\n      const intentResolution = await control.raiseIntent(\n        Intent.sharedTestingIntent1,\n        ContextType.testContextY,\n        undefined,\n        61000\n      );\n      control.validateIntentResolution(IntentApp.IntentAppB, intentResolution);\n      const intentResultPromise = control.getIntentResult(intentResolution);\n      await receiver;\n\n      if (intentResultPromise) {\n        const intentResult = await intentResultPromise;\n        control.validateIntentResult(intentResult, IntentResultType.Context, ContextType.testContextY);\n      }\n    }).timeout(80000);\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.raiseIntent.ts",
    "content": "import { ChannelError, PrivateChannel, Listener, getAgent, DesktopAgent } from '@finos/fdc3';\nimport { assert, expect } from 'chai';\nimport {\n  RaiseIntentControl,\n  IntentResultType,\n  IntentApp,\n  ContextType,\n  Intent,\n  ControlContextType,\n} from '../support/intent-support';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\n\n/**\n * Details on the mock apps used in these tests can be found in /mock/README.md\n */\nexport default async () =>\n  describe('fdc3.raiseIntent', () => {\n    let errorListener: Listener | undefined = undefined;\n    let control: RaiseIntentControl;\n    let fdc3: DesktopAgent;\n\n    beforeEach(async () => {\n      fdc3 = await getAgent();\n      control = new RaiseIntentControl(fdc3);\n    });\n\n    afterEach(async function afterEach() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n\n      if (errorListener) {\n        errorListener.unsubscribe();\n        errorListener = undefined;\n      }\n    });\n\n    const RaiseIntentSingleResolve =\n      \"(RaiseIntentSingleResolve) Should start app intent-a when raising intent 'aTestingIntent1' with context 'testContextX'\";\n    it(RaiseIntentSingleResolve, async () => {\n      errorListener = await control.listenForError();\n      const result = control.receiveContext(ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED);\n      const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX);\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n      await result;\n    });\n\n    const RaiseIntentTargetedAppResolve =\n      \"(RaiseIntentTargetedAppResolve) Should start app intent-b when raising intent 'sharedTestingIntent1' with context 'testContextX'\";\n    it(RaiseIntentTargetedAppResolve, async () => {\n      errorListener = await control.listenForError();\n      const result = control.receiveContext(ControlContextType.SHARED_TESTING_INTENT1_LISTENER_TRIGGERED);\n      const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextX, {\n        appId: IntentApp.IntentAppB,\n      });\n      control.validateIntentResolution(IntentApp.IntentAppB, intentResolution);\n      await result;\n    });\n\n    const RaiseIntentTargetedInstanceResolveOpen =\n      \"(RaiseIntentTargetedInstanceResolveOpen) Should target running instance of intent-a app when raising intent 'aTestingIntent1' with context 'testContextX' after opening intent-a app\";\n    it(RaiseIntentTargetedInstanceResolveOpen, async () => {\n      // add app control listeners\n      errorListener = await control.listenForError();\n      const confirmAppOpened = control.receiveContext('intent-app-a-opened');\n      const result = control.receiveContext(ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED);\n\n      const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA);\n      await confirmAppOpened;\n\n      const intentResolution = await control.raiseIntent(\n        Intent.aTestingIntent,\n        ContextType.testContextX,\n        appIdentifier\n      );\n      await result;\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n      const instances = await control.findInstances(IntentApp.IntentAppA);\n      control.validateInstances(instances, 1, appIdentifier.instanceId, (await result).instanceId);\n    });\n\n    const RaiseIntentTargetedInstanceResolveFindInstances =\n      \"(RaiseIntentTargetedInstanceResolveFindInstances) Should start app intent-a when targeted by raising intent 'aTestingIntent1' with context 'testContextX'\";\n    it(RaiseIntentTargetedInstanceResolveFindInstances, async () => {\n      // add app control listeners\n      errorListener = await control.listenForError();\n      const confirmAppOpened = control.receiveContext('intent-app-a-opened');\n      const result = control.receiveContext(ControlContextType.A_TESTING_INTENT_LISTENER_TRIGGERED);\n\n      const appOpen = control.receiveContext(ControlContextType.INTENT_APP_A_OPENED, 2000, 1);\n      const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA);\n\n      await appOpen;\n\n      const instances = await control.findInstances(IntentApp.IntentAppA);\n      control.validateInstances(instances, 1, appIdentifier.instanceId);\n      await confirmAppOpened;\n\n      const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, instances[0]);\n      await result;\n      control.validateIntentResolution(IntentApp.IntentAppA, intentResolution);\n\n      const instances2 = await control.findInstances(IntentApp.IntentAppA);\n      expect(instances2.length).to.be.equal(1); //make sure no other instance is started\n    });\n\n    const PrivateChannelsAreNotAppChannels =\n      '(PrivateChannelsAreNotAppChannels) Cannot create an app channel using a private channel id';\n    it(PrivateChannelsAreNotAppChannels, async () => {\n      errorListener = await control.listenForError();\n      const privChan = await control.createPrivateChannel();\n      control.validatePrivateChannel(privChan);\n      const privChan2 = await control.createPrivateChannel();\n      control.validatePrivateChannel(privChan2);\n\n      expect(privChan.id).to.not.be.equal(privChan2.id); //check that the ids of both private channels are different\n      try {\n        await control.createAppChannel(privChan.id);\n        assert.fail('No error was not thrown when calling fdc3.getOrCreateChannel(privateChannel.id)');\n      } catch (ex) {\n        const message = ex instanceof Error ? ex.message : String(ex);\n\n        expect(ex).to.have.property(\n          'message',\n          ChannelError.AccessDenied,\n          `Incorrect error received when calling fdc3.getOrCreateChannel(privateChannel.id). Expected AccessDenied, got ${message}`\n        );\n      }\n\n      const intentResolution = await control.raiseIntent(\n        Intent.privateChannelIsPrivate,\n        ContextType.privateChannelDetails,\n        undefined,\n        undefined,\n        { key: privChan2.id }\n      );\n      control.validateIntentResolution(IntentApp.IntentAppJ, intentResolution);\n      const result = await control.getIntentResult(intentResolution);\n      control.validateIntentResult(result, IntentResultType.Context, ContextType.privateChannelDetails);\n    });\n\n    const PrivateChannelsLifecycleEvents =\n      '(PrivateChannelsLifecycleEvents) PrivateChannel lifecycle events are triggered when expected';\n    it(PrivateChannelsLifecycleEvents, async () => {\n      errorListener = await control.listenForError();\n      const onUnsubscribeReceiver = control.receiveContext(ControlContextType.ON_UNSUBSCRIBE_TRIGGERED);\n      const intentResolution = await control.raiseIntent(Intent.kTestingIntent, ContextType.testContextX, {\n        appId: IntentApp.IntentAppK,\n      });\n      control.validateIntentResolution(IntentApp.IntentAppK, intentResolution);\n      const result = await control.getIntentResult(intentResolution);\n      control.validateIntentResult(result, IntentResultType.PrivateChannel);\n      const listener = await control.receiveContextStreamFromMockApp(<PrivateChannel>result, 1, 5);\n      control.unsubscribeListener(listener);\n\n      await onUnsubscribeReceiver; //should receive context from privChannel.onUnsubscribe in mock app\n      const textContextXReceiver = control.receiveContext(ContextType.testContextX);\n      control.privateChannelBroadcast(<PrivateChannel>result, ContextType.testContextX);\n      await textContextXReceiver;\n      const onUnsubscribeReceiver2 = control.receiveContext(ControlContextType.ON_UNSUBSCRIBE_TRIGGERED);\n      const onDisconnectReceiver = control.receiveContext(ControlContextType.ON_DISCONNECT_TRIGGERED);\n      const listener2 = await control.receiveContextStreamFromMockApp(<PrivateChannel>result, 6, 10);\n      control.disconnectPrivateChannel(<PrivateChannel>result);\n\n      //confirm that onUnsubscribe and onDisconnect were triggered in intent-k\n      await onUnsubscribeReceiver2;\n      await onDisconnectReceiver;\n      control.unsubscribeListener(listener2);\n    });\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/advanced/fdc3.user-channels.ts",
    "content": "import { assert, expect } from 'chai';\nimport { wait } from '../../utils';\nimport { JOIN_AND_BROADCAST, JOIN_AND_BROADCAST_TWICE } from '../support/channel-control';\nimport constants from '../../constants';\nimport { Context } from '@finos/fdc3';\nimport { ChannelControlImpl } from '../support/channels-support';\nimport { getAgent } from '@finos/fdc3';\nimport { APIDocumentation } from '../support/apiDocuments';\n\nconst documentation = '\\r\\nDocumentation: ' + APIDocumentation.desktopAgent + '\\r\\nCause:';\n\nexport default async () => {\n  const fdc3 = await getAgent();\n  const cc = new ChannelControlImpl(fdc3);\n\n  return describe('fdc3.userChannels', () => {\n    beforeEach(cc.leaveChannel);\n\n    afterEach(async function afterEach() {\n      if (this.currentTest?.title !== UCFilteredUsageJoin)\n        await cc.closeMockApp(this.currentTest?.title ?? 'Some-Test-Title');\n    });\n\n    const scTestId1 =\n      '(UCBasicUsage1) Should receive context when adding a listener then joining a user channel before app B broadcasts context to the same channel';\n    it(scTestId1, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- Add fdc3.instrument context listener to app A\\r\\n- App A joins channel 1\\r\\n- App B joins channel 1\\r\\n- App B broadcasts fdc3.instrument context${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId1);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        null,\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      await cc.openChannelApp(scTestId1, channel.id, JOIN_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const scTestId2 =\n      '(UCBasicUsage2) Should receive context when joining a user channel then adding a context listener before app B broadcasts context to the same channel';\n    it(scTestId2, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A joins channel 1\\r\\n- Add listener of type fdc3.instrument to App A\\r\\n- App B joins channel 1\\r\\n- App B broadcasts fdc3.instrument context${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId2);\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        null,\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await cc.openChannelApp(scTestId2, channel.id, JOIN_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const scTestId3 =\n      '(UCBasicUsage3) Should receive context when app B joins then broadcasts context to a user channel before A adds a listener and then joins the same channel';\n    it(scTestId3, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App B joins channel 1\\r\\n- App B broadcasts fdc3.instrument context\\r\\n- App A adds fdc3.instrument context listener\\r\\n- App A joins channel 1${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId3);\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.openChannelApp(scTestId3, channel.id, JOIN_AND_BROADCAST);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        null,\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await cc.joinChannel(channel);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const UCBasicUsage4 =\n      '(UCBasicUsage4) Should receive context when app B joins then broadcasts context to a user channel before A joins and listens on the same channel';\n    it(UCBasicUsage4, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App B joins channel 1\\r\\n- App B broadcasts fdc3.instrument context\\r\\n- App A joins channel 1\\r\\n- App A adds fdc3.instrument context listener${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(UCBasicUsage4);\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.openChannelApp(UCBasicUsage4, channel.id, JOIN_AND_BROADCAST);\n      await cc.joinChannel(channel);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        null,\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const scTestId4 =\n      '(UCFilteredUsage1) Should receive context when app A adds a listener before joining a user channel and app B broadcasts the listened type to the same user channel';\n    it(scTestId4, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds fdc3.instrument context listener\\r\\n- App A joins channel 1\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument and fdc3.contact${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId4);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      await cc.openChannelApp(scTestId4, channel.id, JOIN_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const UCFilteredUsage2 =\n      '(UCFilteredUsage2 ) Should receive context when app A joins a user channel before adding a listener and app B broadcasts the listened type to the same user channel';\n    it(UCFilteredUsage2, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds fdc3.instrument context listener\\r\\n- App A joins channel 1\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument and fdc3.contact${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(UCFilteredUsage2);\n      let receivedContext = false;\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await cc.openChannelApp(UCFilteredUsage2, channel.id, JOIN_AND_BROADCAST_TWICE);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const UCFilteredUsage3 =\n      '(UCFilteredUsage3) Should receive context when B broadcasts to a user channel before A listens for the broadcast type and joins the same channel as B';\n    it(UCFilteredUsage3, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument and fdc3.contact\\r\\n- App A adds fdc3.instrument context listener\\r\\n- App A joins channel 1${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(UCFilteredUsage3);\n      const userChannel = await cc.getNonGlobalUserChannel();\n      let receivedContext = false;\n      await cc.openChannelApp(UCFilteredUsage3, userChannel.id, JOIN_AND_BROADCAST_TWICE, undefined, true);\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await cc.joinChannel(userChannel);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const UCFilteredUsage4 =\n      '(UCFilteredUsage4) Should receive context when B broadcasts to a user channel before A joins the same channel and listens for the broadcast type';\n    it(UCFilteredUsage4, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument and fdc3.contact\\r\\n- App A joins channel 1\\r\\n- App A adds fdc3.instrument context listener${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(UCFilteredUsage4);\n      const userChannel = await cc.getNonGlobalUserChannel();\n      await cc.openChannelApp(UCFilteredUsage4, userChannel.id, JOIN_AND_BROADCAST_TWICE, undefined, true);\n      await cc.joinChannel(userChannel);\n      let receivedContext = false;\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'fdc3.instrument',\n        errorMessage,\n        () => (receivedContext = true)\n      );\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener]);\n      }\n    });\n\n    const scTestId5 =\n      '(UCFilteredUsage5) Should receive multiple contexts when app B broadcasts the listened types to the same user channel';\n    it(scTestId5, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds fdc3.instrument and fdc3.contact context listener\\r\\n- App A joins channel 1\\r\\n- App B joins channel 1\\r\\n- App B broadcasts both context types${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId5);\n      const contextTypes: string[] = [];\n      let receivedContext = false;\n      const contextId = cc.getRandomId();\n\n      function checkIfBothContextsReceived() {\n        if (contextTypes.length === 2) {\n          if (\n            !contextTypes.includes(`fdc3.contact.${contextId}`) ||\n            !contextTypes.includes(`fdc3.instrument.${contextId}`)\n          ) {\n            assert.fail('Incorrect context received', errorMessage);\n          } else {\n            receivedContext = true;\n          }\n        }\n      }\n\n      const listener = await cc.setupAndValidateListener(\n        null,\n        `fdc3.instrument.${contextId}`,\n        `fdc3.instrument.${contextId}`,\n        errorMessage,\n        (context: Context) => {\n          contextTypes.push(context.type);\n          checkIfBothContextsReceived();\n        }\n      );\n\n      const listener2 = await cc.setupAndValidateListener(\n        null,\n        `fdc3.contact.${contextId}`,\n        `fdc3.contact.${contextId}`,\n        errorMessage,\n        (context: Context) => {\n          contextTypes.push(context.type);\n          checkIfBothContextsReceived();\n        }\n      );\n\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      await cc.openChannelApp(scTestId5, channel.id, JOIN_AND_BROADCAST_TWICE, undefined, true, contextId);\n      await resolveExecutionCompleteListener;\n      try {\n        if (!receivedContext) {\n          //allow upto a second for the context to arrive\n          await wait(constants.ShortWait);\n          if (!receivedContext) {\n            assert.fail(`No context received!\\n${errorMessage}`);\n          }\n        }\n      } finally {\n        cc.unsubscribeListeners([listener, listener2]);\n      }\n    });\n\n    const scTestId6 =\n      '(UCFilteredUsage6) Should not receive context when A & B join different user channels and app B broadcasts a listened type';\n    it(scTestId6, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds fdc3.instrument and fdc3.contact context listener\\r\\n- App A joins channel 2\\r\\n- App B joins channel 1\\r\\n- App B broadcasts both context types${documentation}`;\n\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /* noop */\n        }\n      );\n      const listener2 = await cc.setupAndValidateListener(\n        null,\n        'fdc3.contact',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /* noop */\n        }\n      );\n\n      const channels = await cc.getNonGlobalUserChannels();\n      if (channels.length < 1) assert.fail('No system channels available for app A');\n\n      await cc.joinChannel(channels[0]);\n      await cc.openChannelApp(scTestId6, channels[1].id, JOIN_AND_BROADCAST_TWICE);\n      await wait(constants.ShortWait); // give listeners time to receive context\n      cc.unsubscribeListeners([listener, listener2]);\n    });\n\n    const scTestId7 =\n      '(UCFilteredUsageUnsubscribe) Should not receive context when unsubscribing a user channel before app B broadcasts the listened type to that channel';\n    it(scTestId7, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds context listener of type fdc3.instrument\\r\\n- App A joins channel 1\\r\\n- App A unsubscribes the listener\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId7);\n      const listener = await cc.setupAndValidateListener(\n        null,\n        'fdc3.instrument',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /* noop */\n        }\n      );\n      const listener2 = await cc.setupAndValidateListener(\n        null,\n        'fdc3.contact',\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /* noop */\n        }\n      );\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      cc.unsubscribeListeners([listener, listener2]);\n      await cc.openChannelApp(scTestId7, channel.id, JOIN_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n    });\n\n    const scTestId8 =\n      '(UCFilteredUsageChange) Should not receive context when joining two different user channels before app B broadcasts the listened type to the first channel that was joined';\n    it(scTestId8, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds context listener of type fdc3.instrument\\r\\n- App A joins channel 1\\r\\n- App A joins channel 2\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument${documentation}`;\n\n      const contextId = cc.getRandomId();\n      const listener = await cc.setupAndValidateListener(\n        null,\n        `fdc3.instrument.${contextId}`,\n        'unexpected-context',\n        errorMessage,\n        async () => {\n          /* noop */\n        }\n      );\n      const listener2 = await cc.setupAndValidateListener(\n        null,\n        `fdc3.contact.${contextId}`,\n        'unexpected-context',\n        errorMessage,\n        () => {\n          /* noop */\n        }\n      );\n\n      const channels = await cc.getNonGlobalUserChannels();\n      if (channels.length < 1) {\n        assert.fail('No system channels available for app A');\n      }\n\n      await cc.joinChannel(channels[0]);\n      await cc.joinChannel(channels[1]);\n      await cc.openChannelApp(scTestId8, channels[0].id, JOIN_AND_BROADCAST, undefined, true, contextId);\n      await wait(constants.ShortWait); // give listeners time to receive context\n      cc.unsubscribeListeners([listener, listener2]);\n    });\n\n    const UCFilteredUsageLeave = '(UCFilteredUsageLeave) Should not receive context after leaving a user channel';\n    it(UCFilteredUsageLeave, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds fdc3.instrument and fdc3.contact context listener\\r\\n- App A joins channel 1\\r\\n- App A leaves current channel\\r\\n- App B joins channel 1\\r\\n- App B broadcasts both context types${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(UCFilteredUsageLeave);\n      const contextId = cc.getRandomId();\n\n      const listener = await cc.setupAndValidateListener(\n        null,\n        `fdc3.instrument.${contextId}`,\n        `fdc3.instrument.${contextId}`,\n        errorMessage,\n        () => {\n          assert.fail('fdc3.instrument context received');\n        }\n      );\n\n      const listener2 = await cc.setupAndValidateListener(\n        null,\n        `fdc3.contact.${contextId}`,\n        `fdc3.contact.${contextId}`,\n        errorMessage,\n        () => {\n          assert.fail('fdc3.contact context received');\n        }\n      );\n\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.joinChannel(channel);\n      await cc.leaveChannel();\n      await cc.openChannelApp(UCFilteredUsageLeave, channel.id, JOIN_AND_BROADCAST_TWICE, undefined, true, contextId);\n      await resolveExecutionCompleteListener;\n      await wait(constants.ShortWait); // give listeners time to receive context\n      cc.unsubscribeListeners([listener, listener2]);\n    });\n\n    const scTestId9 =\n      \"(UCFilteredUsageNoJoin) Should not receive context when A doesn't join a user channel before app B broadcasts the listened type to that channel\";\n    it(scTestId9, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A adds context listener of type fdc3.instrument\\r\\n- App A unsubscribes the listener\\r\\n- App B joins channel 1\\r\\n- App B broadcasts context of type fdc3.instrument${documentation}`;\n\n      const resolveExecutionCompleteListener = cc.initCompleteListener(scTestId9);\n      await cc.setupAndValidateListener(null, 'fdc3.instrument', 'unexpected-context', errorMessage, () => {\n        /* noop */\n      });\n      await cc.setupAndValidateListener(null, 'fdc3.contact', 'unexpected-context', errorMessage, () => {\n        /* noop */\n      });\n      const channel = await cc.getNonGlobalUserChannel();\n      await cc.openChannelApp(scTestId9, channel.id, JOIN_AND_BROADCAST);\n      await resolveExecutionCompleteListener;\n      await wait(constants.ShortWait);\n    });\n\n    const UCFilteredUsageJoin = '(UCFilteredUsageJoin) getCurrentChannel retrieves the channel that was joined';\n    it(UCFilteredUsageJoin, async () => {\n      const errorMessage = `\\r\\nSteps to reproduce:\\r\\n- App A retrieves user channels\\r\\n- App A joins the third channel\\r\\n- App A gets current channel${documentation}`;\n      const channels = await cc.getNonGlobalUserChannels();\n      if (channels.length < 1) {\n        assert.fail('No system channels available for app A');\n      }\n      await cc.joinChannel(channels[2]);\n      const currentChannel = await cc.getCurrentChannel();\n      expect(channels[2].id, errorMessage).to.be.equal(currentChannel?.id);\n    });\n  });\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/basic/fdc3.basic.ts",
    "content": "import { Context, DesktopAgent } from '@finos/fdc3';\n\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { ContextType, Intent } from '../support/intent-support';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\n\nimport { assert, expect } from 'chai';\nimport { handleFail } from '../../utils';\n\nconst getAgent2_2 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(GetAgentAPI) Method is callable', async () => {\n    const info = await fdc3.getInfo();\n    assert.isTrue(info.fdc3Version.startsWith('2.'), documentation);\n    const userChannels = await fdc3.getUserChannels();\n    assert.isTrue(userChannels.length > 0, documentation);\n  });\n};\n\nconst basicCL1 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(BasicCL1) Method is callable', async () => {\n    const contextType = 'fdc3.contact';\n    try {\n      const listener = await fdc3.addContextListener(contextType, (info: Context) => {\n        console.log(`Context listener of type ${contextType} triggered with result ${info}`);\n      });\n      assert.isTrue(listener && typeof listener === 'object', documentation);\n      expect(\n        typeof listener.unsubscribe,\n        'the listener did not contain an unsubscribe function' + documentation\n      ).to.be.equals('function');\n      if (listener !== undefined) {\n        listener.unsubscribe();\n      }\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicCL2 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(BasicCL2) Returns listener object', async () => {\n    try {\n      const listener = await fdc3.addContextListener(null, () => {});\n      assert.isTrue(listener && typeof listener === 'object', documentation);\n      expect(typeof listener.unsubscribe, documentation).to.be.equals('function');\n      if (listener !== undefined) {\n        listener.unsubscribe();\n      }\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicIL1 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(BasicIL1) Method is callable', async () => {\n    const intentName = 'ConformanceListener';\n    try {\n      const listener = await fdc3.addIntentListener(intentName, (info: Context) => {\n        console.log(`Intent listener for intent ${intentName} triggered with result ${info}`);\n      });\n      expect(listener).to.have.property('unsubscribe').that.is.a('function');\n      if (listener !== undefined) {\n        listener.unsubscribe();\n      }\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicGI1 = (fdc3: DesktopAgent, documentation: string) => {\n  console.log('coming here in');\n  it('(BasicGI1) Returns ImplementationMetadata object', async () => {\n    try {\n      const info = await fdc3.getInfo();\n      expect(info, documentation).to.have.property('fdc3Version');\n      expect(info, documentation).to.have.property('provider');\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicAC1 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(BasicAC1) Returns Channel object', async () => {\n    try {\n      const channel = await fdc3.getOrCreateChannel('FDC3Conformance');\n      expect(channel, documentation).to.have.property('id');\n      expect(channel, documentation).to.have.property('type');\n      expect(channel, documentation).to.have.property('broadcast');\n      expect(channel, documentation).to.have.property('getCurrentContext');\n      expect(channel, documentation).to.have.property('addContextListener');\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicUC1 = (fdc3: DesktopAgent, documentation: string) => {\n  it('(BasicUC1) Channel object is valid', async () => {\n    try {\n      const channels = await fdc3.getUserChannels();\n      expect(channels.length, documentation).to.be.greaterThan(0);\n      expect(typeof channels).to.be.equals('object', documentation);\n      for (let i = 0; i < channels.length; i++) {\n        expect(channels[0]).to.have.property('type');\n        expect(channels[0]).to.have.property('id');\n      }\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicJC1 = (fdc3: DesktopAgent, documentation: string) => {\n  it(\"(BasicJC1) getCurrentChannel should retrieve 'null' or a channel object depending upon whether the channel has been joined or not\", async () => {\n    const channels = await fdc3.getUserChannels();\n    if (channels.length > 0) {\n      try {\n        await fdc3.joinUserChannel(channels[0].id);\n        const currentChannel = await fdc3.getCurrentChannel();\n        if (typeof currentChannel !== 'object') {\n          assert.fail('getCurrentChannel did not retrieve a channel object');\n        }\n        expect(currentChannel?.id).to.eql(channels[0].id);\n        await fdc3.leaveCurrentChannel();\n        const currentChannelAfterLeave = await fdc3.getCurrentChannel();\n        assert.isNull(currentChannelAfterLeave);\n      } catch (ex) {\n        handleFail(documentation, ex);\n      }\n    } else {\n      assert.fail('No system channels available');\n    }\n  });\n};\n\nconst basicRI1 = (fdc3: DesktopAgent, documentation: string, intent: string, contextType: string) => {\n  const basicRI1 =\n    '(BasicRI1) application should be able to raise an intent by passing Intent name and gets a promise in return';\n  it(basicRI1, async () => {\n    try {\n      await fdc3.raiseIntent(intent, { type: contextType });\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\nconst basicRI2 = (fdc3: DesktopAgent, documentation: string, contextType: string) => {\n  const basicRI2 =\n    '(BasicRI2) application should be able to raise an intent for some item by passing context and gets a promise in return';\n  it(basicRI2, async () => {\n    const context = {\n      type: contextType,\n    };\n\n    try {\n      await fdc3.raiseIntentForContext(context);\n    } catch (ex) {\n      handleFail(documentation, ex);\n    }\n  });\n};\n\ndeclare let fdc3: DesktopAgent;\n\nconst documentation_CL = '\\r\\nDocumentation: ' + APIDocumentation.addContextListener + '\\r\\nCause';\nconst documentation_IL = '\\r\\nDocumentation: ' + APIDocumentation.addIntentListener + '\\r\\nCause';\nconst documentation_GI = '\\r\\nDocumentation: ' + APIDocumentation.getInfo + '\\r\\nCause';\nconst documentation_AC = '\\r\\nDocumentation: ' + APIDocumentation.getOrCreateChannel + '\\r\\nCause';\nconst documentation_UC = '\\r\\nDocumentation: ' + APIDocumentation.getUserChannels + '\\r\\nCause';\nconst documentation_JC = '\\r\\nDocumentation: ' + APIDocumentation.getCurrentChannel + '\\r\\nCause';\nconst documentation_RI = '\\r\\nDocumentation: ' + APIDocumentation.raiseIntentForContext + '\\r\\nCause';\nconst documentation_GA = '\\r\\nDocumentation: ' + APIDocumentation.getAgent + '\\r\\nCause';\n\nexport const fdc3BasicGetAgent = async () => describe('fdc3.basicGetAgent', () => getAgent2_2(fdc3, documentation_GA));\nexport const fdc3BasicCL1 = async () => describe('fdc3.basicCL1', () => basicCL1(fdc3, documentation_CL));\nexport const fdc3BasicCL2 = async () => describe('fdc3.basicCL2', () => basicCL2(fdc3, documentation_CL));\nexport const fdc3BasicIL1 = async () => describe('fdc3.basicIL1', () => basicIL1(fdc3, documentation_IL));\nexport const fdc3BasicGI1 = async () => describe('fdc3.basicGI1', () => basicGI1(fdc3, documentation_GI));\nexport const fdc3BasicAC1 = async () => describe('fdc3.basicAC1', () => basicAC1(fdc3, documentation_AC));\nexport const fdc3BasicUC1 = async () => describe('fdc3.basicUC1', () => basicUC1(fdc3, documentation_UC));\nexport const fdc3BasicJC1 = async () => describe('fdc3.basicJC1', () => basicJC1(fdc3, documentation_JC));\n\nexport const fdc3BasicRI1 = async () =>\n  describe('fdc3.basicRI1', () => {\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown test');\n    });\n    basicRI1(fdc3, documentation_RI, Intent.aTestingIntent, ContextType.testContextX);\n  });\n\nexport const fdc3BasicRI2 = async () =>\n  describe('fdc3.basicRI2', () => {\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown test');\n    });\n    basicRI2(fdc3, documentation_RI, ContextType.testContextZ);\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/fdc3-conformance-utils.ts",
    "content": "import { Channel, Context, DesktopAgent } from '@finos/fdc3';\nimport { AppControlContext, AppControlContextListener } from '../context-types';\nimport constants from '../constants';\nimport { wait } from '../utils';\n\ndeclare let fdc3: DesktopAgent;\n\nexport async function closeMockAppWindow(testId: string, count: number = 1) {\n  const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel);\n  const { listenerPromise: contextPromise } = await waitForContext('windowClosed', testId, appControlChannel, count);\n  await broadcastCloseWindow(testId);\n  await contextPromise;\n  await wait(constants.WindowCloseWaitTime); // wait for window to close\n}\n\nconst broadcastCloseWindow = async (currentTest: string) => {\n  const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel);\n  appControlChannel.broadcast({\n    type: 'closeWindow',\n    testId: currentTest,\n  } as AppControlContext);\n};\n\nexport const waitForContext = async (\n  contextType: string,\n  testId: string,\n  channel: Channel,\n  count = 1\n): Promise<AppControlContextListener> => {\n  let promiseResolve: (c: Context) => void;\n  let promiseReject: (x: unknown) => void;\n\n  const listenerPromise = new Promise<Context>((resolve, reject) => {\n    promiseResolve = resolve;\n    promiseReject = reject;\n  });\n\n  setTimeout(() => {\n    if (count > 0) {\n      promiseReject(new Error(\"App didn't return close context within 1 sec\"));\n    }\n  }, 1000);\n\n  return channel\n    .addContextListener(contextType, ctx => {\n      if (ctx['testId'] == testId) {\n        console.log(`Received ${contextType}`);\n        count--;\n        if (count == 0) {\n          promiseResolve(ctx);\n        } else {\n          console.log(`Waiting for ${count} more ${contextType}`);\n        }\n      } else {\n        console.log(`Wrong test id expected:  ${testId} got: ${ctx['testId']}`);\n      }\n    })\n    .then(() => {\n      return {\n        listenerPromise,\n      };\n    });\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/index.ts",
    "content": "export * from './testSuite';\nimport { getAgent } from '@finos/fdc3';\nimport { getPackMembers, getPackNames, executeTestsInBrowser, executeManualTestsInBrowser } from './testSuite';\nimport { ProgressReporter } from './progressReporter';\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nrequire('mocha/mocha.css');\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nrequire('source-map-support/browser-source-map-support.js');\n\nmocha.setup('bdd');\nmocha.reporter(ProgressReporter);\nconst testSuite = document.getElementById('testSuite')!;\n\n// populate drop-down\ngetPackNames().forEach(pn => {\n  const optGroup = document.createElement('optgroup');\n  optGroup.setAttribute('label', pn);\n  getPackMembers(pn).forEach(pm => {\n    const opt = document.createElement('option');\n    const text = document.createTextNode(pm);\n    opt.setAttribute('value', pm);\n    opt.appendChild(text);\n    optGroup.appendChild(opt);\n  });\n  testSuite.appendChild(optGroup);\n});\n\nfunction executeTests() {\n  toggleVersionSelector();\n  toggleBackButton();\n  const testSuiteMenu = document.getElementById('testSuite') as HTMLSelectElement;\n  const selectedSuite = testSuiteMenu.options[testSuiteMenu.selectedIndex].innerHTML;\n  const action = () => executeTestsInBrowser(selectedSuite);\n  if (window.fdc3) {\n    action();\n  } else {\n    getAgent().then(() => action());\n  }\n}\n\nfunction executeManualTests() {\n  toggleVersionSelector();\n  toggleBackButton();\n  const manualTests = document.getElementById('manualTests') as HTMLSelectElement;\n  const selectedManualTest = manualTests.options[manualTests.selectedIndex].innerHTML;\n  console.log('******** Selected manual test is', selectedManualTest);\n  const action = () => executeManualTestsInBrowser(selectedManualTest);\n  if (window.fdc3) {\n    action();\n  } else {\n    getAgent().then(() => action());\n  }\n}\n\nfunction returnToTestSelection() {\n  location.reload();\n}\n\nfunction toggleVersionSelector() {\n  const versionSelector = document.getElementById('version-selector')!;\n  const manualSelector = document.getElementById('manualTests-selector')!;\n  if (versionSelector.style.display === 'none') {\n    versionSelector.style.display = 'block';\n    manualSelector.style.display = 'block';\n  } else {\n    versionSelector.style.display = 'none';\n    manualSelector.style.display = 'none';\n  }\n}\n\nfunction toggleBackButton() {\n  const backButton = document.getElementById('back-button')!;\n  if (window.getComputedStyle(backButton).display === 'none') {\n    backButton.style.display = 'block';\n  } else {\n    backButton.style.display = 'none';\n  }\n}\n\ndocument.getElementById('runButton')!.addEventListener('click', executeTests);\ndocument.getElementById('back-button')!.addEventListener('click', returnToTestSelection);\ndocument.getElementById('manualTestsRunButton')!.addEventListener('click', executeManualTests);\n\ngetAgent(); // ensure the agent is ready before running tests\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/manual/fdc3.manual.ts",
    "content": "import { FDC3ChannelChangedEvent, getAgent } from '@finos/fdc3';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport { APIDocumentation } from '../support/apiDocuments';\nimport { ContextType, IntentApp, Intent, RaiseIntentControl } from '../support/intent-support';\nimport { handleFail, wait } from '../../utils';\nimport { expect } from 'chai';\n\nconst raiseIntentDocs = '\\r\\nDocumentation: ' + APIDocumentation.raiseIntent + '\\r\\nCause';\n\n/**\n * Details on the mock apps used in these tests can be found in /mock/README.md\n */\n\nexport const fdc3ResolveAmbiguousIntentTarget = async () =>\n  describe('ResolveAmbiguousIntentTarget', async () => {\n    const fdc3 = await getAgent();\n\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n    });\n    const ResolveAmbiguousIntentTarget =\n      \"(ResolveAmbiguousIntentTarget) Should be able to raise intent using Intent and Context and manually select an app out of 'E','F','G','H' and 'I'\";\n    it(ResolveAmbiguousIntentTarget, async () => {\n      try {\n        const context = {\n          type: ContextType.testContextY,\n        };\n        await fdc3.raiseIntent(Intent.sharedTestingIntent2, context);\n      } catch (ex) {\n        handleFail(raiseIntentDocs, ex);\n      }\n    });\n  });\n\nexport const fdc3ResolveAmbiguousContextTarget = async () =>\n  describe('ResolveAmbiguousContextTarget', async () => {\n    const fdc3 = await getAgent();\n\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n    });\n    const ResolveAmbiguousIntentTarget =\n      \"(ResolveAmbiguousContextTarget) Should be able to raise intent using ContextY and manually select an app out of 'E','F','G','H' and 'I'\";\n    it(ResolveAmbiguousIntentTarget, async () => {\n      try {\n        const context = {\n          type: ContextType.testContextY,\n        };\n        await fdc3.raiseIntentForContext(context);\n      } catch (ex) {\n        handleFail(raiseIntentDocs, ex);\n      }\n    });\n  });\n\nexport const fdc3ResolveAmbiguousIntentTargetMultiInstance = async () =>\n  describe('ResolveAmbiguousIntentTargetMultiInstance', async () => {\n    const fdc3 = await getAgent();\n    const control = new RaiseIntentControl(fdc3);\n\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n    });\n    const ResolveAmbiguousIntentTargetMultiInstance =\n      \"(ResolveAmbiguousIntentTargetMultiInstance) Open 2 instances of App E and AppF respectively and then should be able to raise intent using Intent and Context and manually select an app out of 'E','F','G','H' and 'I'\";\n    it(ResolveAmbiguousIntentTargetMultiInstance, async () => {\n      try {\n        const context = {\n          type: ContextType.testContextY,\n        };\n        await control.openIntentApp(IntentApp.IntentAppE);\n        await control.openIntentApp(IntentApp.IntentAppE);\n        await control.openIntentApp(IntentApp.IntentAppF);\n        await control.openIntentApp(IntentApp.IntentAppF);\n        await wait(100);\n\n        await fdc3.raiseIntent(Intent.sharedTestingIntent2, context);\n      } catch (ex) {\n        handleFail(raiseIntentDocs, ex);\n      }\n    });\n  });\n\nexport const fdc3ResolveAmbiguousContextTargetMultiInstance = async () =>\n  describe('ResolveAmbiguousContextTargetMultiInstance', async () => {\n    const fdc3 = await getAgent();\n    const control = new RaiseIntentControl(fdc3);\n\n    after(async function after() {\n      await closeMockAppWindow(this.currentTest?.title ?? 'Unknown Test');\n    });\n    const ResolveAmbiguousContextTargetMultiInstance =\n      \"(ResolveAmbiguousContextTargetMultiInstance) Open 2 instances of App E and AppF respectively and then should be able to raise intent using Context and manually select an app out of 'E','F','G','H' and 'I'\";\n    it(ResolveAmbiguousContextTargetMultiInstance, async () => {\n      try {\n        const context = {\n          type: ContextType.testContextY,\n        };\n        await control.openIntentApp(IntentApp.IntentAppE);\n        await control.openIntentApp(IntentApp.IntentAppE);\n        await control.openIntentApp(IntentApp.IntentAppF);\n        await control.openIntentApp(IntentApp.IntentAppF);\n        await wait(100);\n\n        await fdc3.raiseIntentForContext(context);\n      } catch (ex) {\n        handleFail(raiseIntentDocs, ex);\n      }\n    });\n  });\n\nexport const fdc3ChannelChangedEvent = async () =>\n  describe('ChannelChangedEvent', () => {\n    it('(ChannelChangedEvent) Should receive an event when the user changes channel.  This is a manual test, please change the channel a few times in your browser to get this to pass.', async () => {\n      const channels: (string | null)[] = [];\n      try {\n        const agent = await getAgent();\n        agent.addEventListener('userChannelChanged', event => {\n          const changedEvent: FDC3ChannelChangedEvent = event as FDC3ChannelChangedEvent;\n          const currentChannel = changedEvent.details.currentChannelId;\n          console.log('User channel changed', event, currentChannel);\n          channels.push(currentChannel);\n        });\n\n        await wait(8000);\n        const uniqueChannels = new Set(channels);\n        expect(uniqueChannels.size).to.be.greaterThan(0);\n      } catch (ex) {\n        handleFail(`Didn't get any channel change events: ${JSON.stringify(channels)}`, ex);\n      }\n    });\n  });\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/progressReporter.ts",
    "content": "/**\n * Custom Mocha reporter that shows an amber in-progress indicator when each test\n * starts, then updates the indicator to a green tick or red cross when the test completes.\n */\nexport class ProgressReporter extends Mocha.reporters.Base {\n  private testElements = new Map<string, HTMLElement>();\n  private suiteStack: HTMLElement[];\n  private canvas: HTMLCanvasElement;\n  private passCount: HTMLElement;\n  private failCount: HTMLElement;\n  private durationCount: HTMLElement;\n  private startTime: number;\n  private durationTimer: ReturnType<typeof setInterval>;\n\n  constructor(runner: Mocha.Runner, options?: Mocha.MochaOptions) {\n    super(runner, options);\n\n    const root = document.getElementById('mocha')!;\n    root.replaceChildren();\n\n    const statsEl = document.createElement('ul');\n    statsEl.id = 'mocha-stats';\n    root.appendChild(statsEl);\n\n    const report = document.createElement('ul');\n    report.id = 'mocha-report';\n    root.appendChild(report);\n\n    // Progress ring canvas\n    const progressLi = document.createElement('li');\n    progressLi.className = 'progress-ring';\n    this.canvas = document.createElement('canvas');\n    this.canvas.width = 40;\n    this.canvas.height = 40;\n    progressLi.appendChild(this.canvas);\n    statsEl.appendChild(progressLi);\n\n    const passLi = document.createElement('li');\n    passLi.className = 'passes';\n    this.passCount = this.buildStatItem(passLi, 'passes: ', '0');\n    statsEl.appendChild(passLi);\n\n    const failLi = document.createElement('li');\n    failLi.className = 'failures';\n    this.failCount = this.buildStatItem(failLi, 'failures: ', '0');\n    statsEl.appendChild(failLi);\n\n    const durationLi = document.createElement('li');\n    durationLi.className = 'duration';\n    this.durationCount = this.buildStatItem(durationLi, 'duration: ', '0', 's');\n    statsEl.appendChild(durationLi);\n\n    this.suiteStack = [report];\n    this.startTime = Date.now();\n\n    this.durationTimer = setInterval(() => this.updateDuration(), 100);\n\n    runner.on('suite', suite => this.onSuite(suite));\n    runner.on('suite end', suite => this.onSuiteEnd(suite));\n    runner.on('test', test => this.onTest(test));\n    runner.on('pass', test => this.onPass(test));\n    runner.on('fail', (test, err) => this.onFail(test, err));\n    runner.on('end', () => this.onEnd());\n  }\n\n  private onSuite(suite: Mocha.Suite) {\n    if (suite.root) return;\n    const li = document.createElement('li');\n    li.className = 'suite';\n    const h1 = document.createElement('h1');\n    const a = document.createElement('a');\n    a.textContent = suite.title;\n    h1.appendChild(a);\n    li.appendChild(h1);\n    const ul = document.createElement('ul');\n    li.appendChild(ul);\n    this.suiteStack[this.suiteStack.length - 1].appendChild(li);\n    this.suiteStack.push(ul);\n  }\n\n  private onSuiteEnd(suite: Mocha.Suite) {\n    if (suite.root) return;\n    if (this.suiteStack.length > 1) this.suiteStack.pop();\n  }\n\n  private onTest(test: Mocha.Test) {\n    const li = document.createElement('li');\n    li.className = 'test running';\n    const h2 = document.createElement('h2');\n    h2.textContent = test.title;\n    li.appendChild(h2);\n    this.suiteStack[this.suiteStack.length - 1].appendChild(li);\n    this.testElements.set(test.fullTitle(), li);\n    li.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n  }\n\n  private onPass(test: Mocha.Test) {\n    const li = this.testElements.get(test.fullTitle());\n    if (li) {\n      li.className = `test pass ${this.getSpeedClass(test)}`;\n      this.addDuration(li, test);\n    }\n    this.updateStats();\n  }\n\n  private onFail(test: Mocha.Test, err: Error) {\n    const li = this.testElements.get(test.fullTitle());\n    if (li) {\n      li.className = 'test fail';\n      this.addDuration(li, test);\n      const pre = document.createElement('pre');\n      pre.className = 'error';\n      pre.textContent = err.message;\n      li.appendChild(pre);\n    }\n    this.updateStats();\n  }\n\n  private onEnd() {\n    clearInterval(this.durationTimer);\n    this.updateDuration();\n  }\n\n  private getSpeedClass(test: Mocha.Test): string {\n    const slow = test.slow ? test.slow() : 75;\n    const duration = test.duration ?? 0;\n    if (duration > slow) return 'slow';\n    if (duration > slow / 2) return 'medium';\n    return 'fast';\n  }\n\n  private addDuration(li: HTMLElement, test: Mocha.Test) {\n    if (test.duration !== undefined) {\n      const h2 = li.querySelector('h2')!;\n      const span = document.createElement('span');\n      span.className = 'duration';\n      span.textContent = ` ${test.duration}ms`;\n      h2.appendChild(span);\n    }\n  }\n\n  private buildStatItem(parent: HTMLElement, label: string, initialValue: string, suffix?: string): HTMLElement {\n    const a = document.createElement('a');\n    a.href = 'javascript:void(0);';\n    a.textContent = label;\n    const em = document.createElement('em');\n    em.textContent = initialValue;\n    a.appendChild(em);\n    if (suffix) {\n      a.appendChild(document.createTextNode(suffix));\n    }\n    parent.appendChild(a);\n    return em;\n  }\n\n  private updateDuration() {\n    const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(2);\n    this.durationCount.textContent = elapsed;\n  }\n\n  private updateStats() {\n    const { passes, failures } = this.stats;\n    this.passCount.textContent = String(passes);\n    this.failCount.textContent = String(failures);\n\n    // Draw progress ring\n    const total = this.runner.total;\n    const completed = passes + failures;\n    const percent = total > 0 ? completed / total : 0;\n    const ctx = this.canvas.getContext('2d')!;\n    const x = this.canvas.width / 2;\n    const y = this.canvas.height / 2;\n    const rad = Math.min(x, y) - 1;\n\n    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n    // Background circle\n    ctx.beginPath();\n    ctx.arc(x, y, rad, 0, Math.PI * 2, false);\n    ctx.strokeStyle = '#9f9f9f';\n    ctx.lineWidth = 2;\n    ctx.stroke();\n\n    // Progress arc\n    ctx.beginPath();\n    ctx.arc(x, y, rad - 1, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2 * percent, false);\n    ctx.strokeStyle = '#4fbc5f';\n    ctx.lineWidth = 3;\n    ctx.stroke();\n\n    // Percentage text\n    ctx.fillStyle = '#888';\n    ctx.font = '11px \"Helvetica Neue\", Helvetica, Arial, sans-serif';\n    ctx.textAlign = 'center';\n    ctx.textBaseline = 'middle';\n    ctx.fillText(`${Math.round(percent * 100)}%`, x, y);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/apiDocuments.ts",
    "content": "/**\n * Links to API documentation\n */\n\nexport const APIDocumentation = {\n  getAgent: 'https://fdc3.finos.org/docs/api/ref/GetAgent',\n  desktopAgent: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent',\n  addContextListener: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#addcontextlistener',\n  addIntentListener: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#addintentlistener',\n  broadcast: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#broadcast',\n  findIntent: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#findintent',\n  findIntentsByContext: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#findintentsbycontext',\n  getCurrentChannel: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#getcurrentchannel',\n  getInfo: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#getinfo',\n  getOrCreateChannel: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#getorcreatechannel',\n  getUserChannels: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#getuserchannels',\n  joinChannel: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#joinchannel',\n  leaveCurrentChannel: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#leavecurrentchannel',\n  open: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#open',\n  raiseIntent: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#raiseintent',\n  raiseIntentForContext: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#raiseintentforcontext',\n  appMetadata: 'https://fdc3.finos.org/docs/api/ref/Metadata#appmetadata',\n  findInstances: 'https://fdc3.finos.org/docs/api/ref/DesktopAgent#findinstances',\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/channel-control.ts",
    "content": "import { Context, Channel, Listener } from '@finos/fdc3';\n\n/**\n * This interface wraps channel functionality\n */\nexport interface ChannelControl {\n  // channels\n  getNonGlobalUserChannels(): Promise<Channel[]>;\n  leaveChannel(): Promise<void>;\n  getNonGlobalUserChannel(): Promise<Channel>;\n  joinChannel(channel: Channel): Promise<void>;\n  createRandomTestChannel(): Promise<Channel>;\n  getCurrentChannel(): Promise<Channel | null>;\n\n  // test control\n  unsubscribeListeners(listeners: Listener[]): void;\n  openChannelApp(\n    testId: string,\n    channelId: string,\n    commands: string[],\n    historyItems?: number,\n    notify?: boolean,\n    contextId?: string\n  ): Promise<void>;\n  closeMockApp(testId: string): Promise<void>;\n\n  // listening\n  initCompleteListener(testId: string): Promise<Context>;\n\n  setupAndValidateListener(\n    channel: Channel | null,\n    listenContextType: string | null,\n    expectedContextType: string | null,\n    errorMessage: string,\n    onComplete: (ctx: Context) => void\n  ): Promise<Listener>;\n\n  setupContextChecker(\n    channel: Channel,\n    requestedContextType: string | null,\n    expectedContextType: string,\n    errorMessage: string,\n    onComplete: (ctx: Context) => void\n  ): Promise<void>;\n\n  // helpers\n  getRandomId(): string;\n}\n\nexport type ChannelsAppContext = Context & {\n  commands: string[];\n  config: {\n    testId: string;\n    notifyAppAOnCompletion: boolean;\n    historyItems: number;\n    channelId: string;\n    contextId?: string;\n  };\n};\n\nexport type ChannelsAppConfig = {\n  testId: string;\n  notifyAppAOnCompletion?: boolean;\n  historyItems?: number;\n  channelId: string;\n  contextId?: string;\n};\n\nexport const commands = {\n  joinRetrievedUserChannel: 'joinRetrievedUserChannel',\n  retrieveTestAppChannel: 'retrieveTestAppChannel',\n  broadcastInstrumentContext: 'broadcastInstrumentContext',\n  broadcastContactContext: 'broadcastContactContext',\n};\n\nexport const APP_CHANNEL_AND_BROADCAST = [commands.retrieveTestAppChannel, commands.broadcastInstrumentContext];\n\nexport const APP_CHANNEL_AND_BROADCAST_TWICE = [\n  commands.retrieveTestAppChannel,\n  commands.broadcastInstrumentContext,\n  commands.broadcastContactContext,\n];\n\nexport const JOIN_AND_BROADCAST = [commands.joinRetrievedUserChannel, commands.broadcastInstrumentContext];\n\nexport const JOIN_AND_BROADCAST_TWICE = [\n  commands.joinRetrievedUserChannel,\n  commands.broadcastInstrumentContext,\n  commands.broadcastContactContext,\n];\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/channels-support.ts",
    "content": "import { assert, expect } from 'chai';\nimport { Channel, Context, Listener, DesktopAgent } from '@finos/fdc3';\nimport constants from '../../constants';\nimport { ChannelControl, ChannelsAppConfig, ChannelsAppContext } from '../support/channel-control';\nimport { closeMockAppWindow, waitForContext } from '../fdc3-conformance-utils';\n\nexport class ChannelControlImpl implements ChannelControl {\n  private readonly testAppChannelName = 'test-channel';\n  private readonly fdc3: DesktopAgent;\n\n  constructor(fdc3: DesktopAgent) {\n    this.fdc3 = fdc3;\n  }\n\n  getNonGlobalUserChannels = async () => {\n    const channels = await this.fdc3.getUserChannels();\n    if (channels.find(channel => channel.id.indexOf('global') >= 0)) {\n      assert.fail('Global channel received ');\n    }\n    return channels.filter(channel => channel.id.indexOf('global') === -1);\n  };\n\n  getNonGlobalUserChannel = async (): Promise<Channel> => {\n    const channels = await this.getNonGlobalUserChannels();\n    if (channels.length > 0) {\n      return channels[0];\n    } else {\n      assert.fail('No system channels available for app A');\n    }\n  };\n\n  leaveChannel = async () => {\n    return await this.fdc3.leaveCurrentChannel();\n  };\n\n  joinChannel = async (channel: Channel) => {\n    return this.fdc3.joinUserChannel(channel.id);\n  };\n\n  createRandomTestChannel = async () => {\n    const channelName = `${this.testAppChannelName}.${this.getRandomId()}`;\n    return await this.fdc3.getOrCreateChannel(channelName);\n  };\n\n  getCurrentChannel = async (): Promise<Channel | null> => {\n    return await this.fdc3.getCurrentChannel();\n  };\n\n  unsubscribeListeners = async (listeners: Listener[]) => {\n    listeners.map(listener => {\n      listener.unsubscribe();\n    });\n  };\n\n  initCompleteListener = async (testId: string) => {\n    const { listenerPromise } = await waitForContext(\n      'executionComplete',\n      testId,\n      await this.fdc3.getOrCreateChannel(constants.ControlChannel)\n    );\n    return listenerPromise;\n  };\n\n  openChannelApp = async (\n    testId: string,\n    channelId: string,\n    commands: string[],\n    historyItems?: number,\n    notify: boolean = true,\n    contextId?: string\n  ) => {\n    const channelsAppConfig: ChannelsAppConfig = {\n      testId: testId,\n      channelId: channelId,\n      notifyAppAOnCompletion: notify,\n      contextId: contextId,\n    };\n\n    if (historyItems) {\n      channelsAppConfig.historyItems = historyItems;\n    }\n\n    //Open ChannelsApp then execute commands in order\n    await this.fdc3.open({ appId: 'ChannelsAppId' }, buildChannelsAppContext(commands, channelsAppConfig));\n  };\n\n  async closeMockApp(testId: string) {\n    await closeMockAppWindow(testId);\n  }\n\n  setupAndValidateListener = async (\n    channel: Channel | null,\n    listenContextType: string | null,\n    expectedContextType: string | null,\n    errorMessage: string,\n    onComplete: (ctx: Context) => void\n  ): Promise<Listener> => {\n    let listener;\n    if (channel) {\n      listener = await channel.addContextListener(listenContextType, context => {\n        if (expectedContextType != null) {\n          expect(context.type).to.be.equals(expectedContextType, errorMessage);\n        }\n        onComplete(context);\n      });\n    } else {\n      listener = await this.fdc3.addContextListener(expectedContextType, context => {\n        if (expectedContextType != null) {\n          expect(context.type).to.be.equals(expectedContextType, errorMessage);\n        }\n        onComplete(context);\n      });\n    }\n\n    validateListenerObject(listener);\n    return listener;\n  };\n\n  setupContextChecker = async (\n    channel: Channel,\n    requestedContextType: string | null,\n    expectedContextType: string,\n    errorMessage: string,\n    onComplete: (ctx: Context) => void\n  ): Promise<void> => {\n    //Retrieve current context from channel\n    const context =\n      requestedContextType === null\n        ? await channel.getCurrentContext()\n        : await channel.getCurrentContext(requestedContextType);\n    assert.isNotNull(context, 'await channel.getCurrentContext() returned null');\n    expect(context?.type, 'retrieved context was not of the expected type').to.be.equals(\n      expectedContextType,\n      errorMessage\n    );\n    if (context) {\n      onComplete(context);\n    }\n  };\n\n  getRandomId(): string {\n    const uint32 = window.crypto.getRandomValues(new Uint32Array(1))[0];\n\n    return uint32.toString(16);\n  }\n}\n\nfunction validateListenerObject(listenerObject: Listener) {\n  assert.isTrue(typeof listenerObject === 'object', 'No listener object found');\n  expect(typeof listenerObject.unsubscribe).to.be.equals('function', 'Listener does not contain an unsubscribe method');\n}\n\nfunction buildChannelsAppContext(mockAppCommands: string[], config: ChannelsAppConfig): ChannelsAppContext {\n  return {\n    type: 'channelsAppContext',\n    commands: mockAppCommands,\n    config: {\n      testId: config.testId,\n      notifyAppAOnCompletion: config.notifyAppAOnCompletion ?? false,\n      historyItems: config.historyItems ?? 1,\n      channelId: config.channelId,\n      contextId: config.contextId,\n    },\n  };\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/intent-support.ts",
    "content": "import { assert, expect } from 'chai';\nimport {\n  AppIdentifier,\n  Channel,\n  IntentResolution,\n  IntentResult,\n  Listener,\n  PrivateChannel,\n  Context,\n  DesktopAgent,\n  getOrCreateChannel,\n} from '@finos/fdc3';\nimport { APIDocumentation } from './apiDocuments';\nimport constants from '../../constants';\nimport { appIdMatches, handleFail, wait, wrapPromise } from '../../utils';\nimport { AppControlContext, IntentUtilityContext } from '../../context-types';\n\nconst raiseIntentDocs = '\\r\\nDocumentation: ' + APIDocumentation.raiseIntent + '\\r\\nCause';\n\nexport class RaiseIntentControl {\n  private readonly fdc3: DesktopAgent;\n\n  constructor(fdc3: DesktopAgent) {\n    this.fdc3 = fdc3;\n  }\n\n  async receiveContext(contextType: string, waitTime?: number, count: number = 1): Promise<AppControlContext> {\n    const appControlChannel = await this.fdc3.getOrCreateChannel(constants.ControlChannel);\n    // eslint-disable-next-line no-async-promise-executor\n    return new Promise<Context>(async (resolve, reject) => {\n      const listener = await appControlChannel.addContextListener(contextType, (context: AppControlContext) => {\n        count--;\n        console.log(`Received ${contextType} waiting for ${count} more`);\n        if (count == 0) {\n          resolve(context);\n          listener.unsubscribe();\n        }\n      });\n\n      //if no context received reject promise\n      await wait(waitTime ?? constants.WaitTime);\n      if (count > 0) {\n        reject(\n          new Error(\n            'No context received. Listener expected to receive context of type ' + contextType + ' from mock app'\n          )\n        );\n      }\n    });\n  }\n\n  async openIntentApp(appId: string): Promise<AppIdentifier> {\n    try {\n      return await this.fdc3.open({ appId: appId });\n    } catch (ex) {\n      handleFail('Error while attempting to open the mock app', ex);\n    }\n  }\n\n  async createAppChannel(channelId: string): Promise<Channel> {\n    return await this.fdc3.getOrCreateChannel(channelId);\n  }\n\n  async createPrivateChannel(): Promise<PrivateChannel> {\n    return await this.fdc3.createPrivateChannel();\n  }\n\n  validatePrivateChannel(privChan: PrivateChannel): void {\n    expect(privChan).to.have.property('id');\n  }\n\n  async raiseIntent(\n    intent: string,\n    contextType: string,\n    appIdentifier?: AppIdentifier,\n    delayBeforeReturn: number = 0,\n    contextId?: { [key: string]: string }\n  ): Promise<IntentResolution> {\n    const context: IntentUtilityContext = {\n      type: contextType,\n      delayBeforeReturn: delayBeforeReturn,\n    };\n\n    if (contextId) {\n      context.id = contextId;\n    }\n\n    try {\n      if (appIdentifier) {\n        return await this.fdc3.raiseIntent(intent, context, appIdentifier);\n      } else {\n        return await this.fdc3.raiseIntent(intent, context);\n      }\n    } catch (ex) {\n      throw handleFail('', ex);\n    }\n  }\n\n  async findInstances(appId: string): Promise<AppIdentifier[]> {\n    try {\n      return await this.fdc3.findInstances({ appId: appId });\n    } catch (ex) {\n      handleFail(`Error while attempting to find instances`, ex);\n    }\n  }\n\n  getIntentResult(intentResolution: IntentResolution): Promise<IntentResult> {\n    //ensure getIntentResult immediately returns a promise that can be awaited\n    const timeout = this.failIfResponseTimesOut();\n    const intentResult = intentResolution.getResult();\n    if (typeof intentResult.then !== 'function') {\n      assert.fail(`intentResolution.getResult() did not return a Promise: ${JSON.stringify(intentResult, null, 2)}`);\n    }\n    clearTimeout(timeout);\n    return intentResult;\n  }\n\n  failIfResponseTimesOut() {\n    const timeout = window.setTimeout(() => {\n      assert.fail(\n        'When running getIntentResult() the promise should be returned immediately unless it is being awaited'\n      );\n    }, 500);\n\n    return timeout;\n  }\n\n  async privateChannelBroadcast(privateChannel: PrivateChannel, contextType: string): Promise<void> {\n    await privateChannel.broadcast({ type: contextType });\n  }\n\n  validateIntentResult(\n    intentResult: IntentResult,\n    expectedIntentResultType: IntentResultType,\n    expectedContextType?: string\n  ) {\n    switch (expectedIntentResultType) {\n      case IntentResultType.Context: {\n        if (expectedContextType) {\n          expect(\n            intentResult,\n            `The promise received by Test from resolution.getResult() should resolve to a ${expectedContextType} instance`\n          ).to.have.property('type');\n          expect(\n            intentResult?.type,\n            `The promise received by Test from resolution.getResult() should resolve to a ${expectedContextType} instance. Instead resolved to ${intentResult?.type}`\n          ).to.be.equal(expectedContextType);\n          break;\n        }\n        break;\n      }\n      case IntentResultType.Void: {\n        assert.isUndefined(\n          intentResult,\n          'The promise received by Test from resolution.getResult() should resolve to void'\n        );\n        break;\n      }\n      case IntentResultType.Channel: {\n        expect(intentResult).to.have.property('id');\n        expect(intentResult).to.have.property('type');\n        expect(intentResult?.type).to.be.equal('app');\n        expect(intentResult?.id).to.be.equal('test-channel');\n        break;\n      }\n      case IntentResultType.PrivateChannel: {\n        expect(intentResult).to.have.property('onAddContextListener');\n        expect(intentResult).to.have.property('onUnsubscribe');\n        expect(intentResult).to.have.property('onDisconnect');\n        expect(intentResult).to.have.property('disconnect');\n        expect(intentResult).to.have.property('id');\n        expect(intentResult).to.have.property('type');\n        expect(intentResult?.type).to.be.equal('private');\n      }\n    }\n  }\n\n  validateInstances(\n    instances: AppIdentifier[],\n    expectedInstanceCount: number,\n    expectedInstanceId?: string,\n    returnedInstanceId?: string\n  ): void {\n    expect(instances.length).to.be.equal(expectedInstanceCount);\n    expect(instances[0].instanceId).to.be.equal(expectedInstanceId);\n    if (returnedInstanceId) {\n      expect(expectedInstanceId).to.be.equal(returnedInstanceId);\n    }\n  }\n\n  validateIntentResolution = (appId: string, intentResolution: IntentResolution) => {\n    if (typeof intentResolution.source === 'object') {\n      expect(intentResolution.source as AppIdentifier).to.have.property('appId');\n      expect(intentResolution.source as AppIdentifier).to.have.property('instanceId');\n      expect(typeof intentResolution.source.instanceId).to.be.equal('string');\n      expect(intentResolution.source.instanceId).to.not.be.equal('');\n      expect(appIdMatches(intentResolution.source.appId, appId), raiseIntentDocs).to.be.true;\n    } else assert.fail('Invalid intent resolution object');\n  };\n\n  async listenForError() {\n    const appControlChannel = await getOrCreateChannel('app-control');\n    return appControlChannel.addContextListener('error', (context: AppControlContext) => {\n      assert.fail(context.errorMessage);\n    });\n  }\n\n  async receiveContextStreamFromMockApp(\n    privChannel: PrivateChannel,\n    streamedNumberStart: number,\n    streamedNumberEnd: number\n  ): Promise<Listener> {\n    const wrapper = wrapPromise();\n\n    //receive multiple contexts in succession from intent-k\n    const listener = privChannel.addContextListener(ContextType.testContextZ, (context: IntentUtilityContext) => {\n      expect(context.number, 'Unexpected context stream number received.').to.be.equal(streamedNumberStart);\n      expect(context.type).to.be.equal(ContextType.testContextZ);\n\n      if (streamedNumberStart === streamedNumberEnd) {\n        wrapper.resolve();\n        clearTimeout(timeout);\n      }\n\n      streamedNumberStart += 1;\n    });\n\n    const timeout = window.setTimeout(() => {\n      wrapper.reject(\n        'Timeout: did not receive all 5 streamed contexts back from the mock app. onAddContextListener may not have been triggered'\n      );\n    }, constants.WaitTime);\n\n    await wrapper.promise;\n    return listener;\n  }\n\n  unsubscribeListener(listener: Listener): void {\n    listener.unsubscribe();\n  }\n\n  disconnectPrivateChannel(privateChannel: PrivateChannel): void {\n    privateChannel.disconnect();\n  }\n}\n\nexport enum IntentResultType {\n  Channel = 'Channel',\n  PrivateChannel = 'PrivateChannel',\n  Context = 'Context',\n  Void = 'Void',\n}\n\nexport enum IntentApp {\n  IntentAppA = 'IntentAppAId',\n  IntentAppB = 'IntentAppBId',\n  IntentAppC = 'IntentAppCId',\n  IntentAppD = 'IntentAppDId',\n  IntentAppE = 'IntentAppEId',\n  IntentAppF = 'IntentAppFId',\n  IntentAppG = 'IntentAppGId',\n  IntentAppH = 'IntentAppHId',\n  IntentAppI = 'IntentAppIId',\n  IntentAppJ = 'IntentAppJId',\n  IntentAppK = 'IntentAppKId',\n  IntentAppL = 'IntentAppLId',\n}\n\nexport enum ContextType {\n  testContextX = 'testContextX',\n  testContextY = 'testContextY',\n  testContextZ = 'testContextZ',\n  testContextL = 'testContextL',\n  nonExistentContext = 'nonExistentContext',\n  privateChannelDetails = 'privateChannelDetails',\n}\n\nexport enum ControlContextType {\n  CONTEXT_RECEIVED = 'context-received',\n  ERROR = 'error',\n  A_TESTING_INTENT_LISTENER_TRIGGERED = 'aTestingIntent-listener-triggered',\n  INTENT_APP_A_OPENED = 'intent-app-a-opened',\n  SHARED_TESTING_INTENT1_LISTENER_TRIGGERED = 'sharedTestingIntent1-listener-triggered',\n  SHARED_TESTING_INTENT_2_RESULT_SENT = 'sharedTestingIntent2-result-sent',\n  ON_UNSUBSCRIBE_TRIGGERED = 'onUnsubscribeTriggered',\n  ON_DISCONNECT_TRIGGERED = 'onDisconnectTriggered',\n  CONTEXT_LISTENER_TRIGGERED = 'context-listener-triggered',\n  INTENT_LISTENER_TRIGGERED = 'intent-listener-triggered',\n}\n\nexport enum Intent {\n  aTestingIntent = 'aTestingIntent',\n  bTestingIntent = 'bTestingIntent',\n  cTestingIntent = 'cTestingIntent',\n  kTestingIntent = 'kTestingIntent',\n  lTestingIntent = 'LTestingIntent',\n  sharedTestingIntent1 = 'sharedTestingIntent1',\n  sharedTestingIntent2 = 'sharedTestingIntent2',\n  privateChannelIsPrivate = 'privateChannelIsPrivate',\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/metadata-support.ts",
    "content": "import { expect } from 'chai';\nimport {\n  IntentResolution,\n  AppIdentifier,\n  AppMetadata,\n  Channel,\n  Context,\n  ContextMetadata,\n  DesktopAgent,\n  ImplementationMetadata,\n} from '@finos/fdc3';\nimport constants from '../../constants';\nimport { APIDocumentation } from './apiDocuments';\n\nconst getMetadataDocs = '\\r\\nDocumentation: ' + APIDocumentation.appMetadata + '\\r\\nCause: ';\nconst getInfoDocs = '\\r\\nDocumentation: ' + APIDocumentation.getInfo + '\\r\\nCause';\ndeclare let fdc3: DesktopAgent;\nconst validAppMetaDataProperties = [\n  'appId',\n  'instanceId',\n  'name',\n  'version',\n  'instanceMetadata',\n  'title',\n  'tooltip',\n  'description',\n  'icons',\n  'screenshots',\n  'resultType',\n];\nexport class MetadataValidator {\n  validateAppMetadata(metadata: AppMetadata) {\n    expect(metadata, `The AppMetadata object does not contain an appId property${getMetadataDocs}`).to.have.property(\n      'appId'\n    );\n    const properties = Object.keys(metadata);\n    for (const property of properties) {\n      expect(\n        validAppMetaDataProperties,\n        `The AppMetadata object contains an invalid property ${getMetadataDocs}`\n      ).includes(property);\n    }\n  }\n\n  validateImplementationMetadata(implMetadata: ImplementationMetadata) {\n    expect(implMetadata, `ImplementationMetadata did not have property fdc3Version${getInfoDocs}`).to.have.property(\n      'fdc3Version'\n    );\n    expect(parseFloat(implMetadata.fdc3Version)).to.be.greaterThanOrEqual(2);\n    expect(implMetadata, `ImplementationMetadata did not have property provider${getInfoDocs}`).to.have.property(\n      'provider'\n    );\n    expect(implMetadata.provider).to.not.be.equal('');\n    expect(\n      implMetadata.optionalFeatures,\n      `ImplementationMetadata.optionalFeatures did not have property OriginatingAppMetadata${getInfoDocs}`\n    ).to.have.property('OriginatingAppMetadata');\n    expect(\n      implMetadata.optionalFeatures,\n      `ImplementationMetadata.optionalFeatures did not have property UserChannelMembershipAPIs${getInfoDocs}`\n    ).to.have.property('UserChannelMembershipAPIs');\n    expect(\n      typeof implMetadata.optionalFeatures.OriginatingAppMetadata,\n      `ImplementationMetadata.optionalFeatures.OriginatingAppMetadata should be of type boolean`\n    ).to.be.equal('boolean');\n    expect(\n      typeof implMetadata.optionalFeatures.UserChannelMembershipAPIs,\n      'ImplementationMetadata.optionalFeatures.UserChannelMembershipAPIs should be of type boolean'\n    ).to.be.equal('boolean');\n  }\n\n  validateAppIdentifier(appIdentifier: AppIdentifier | undefined) {\n    expect(appIdentifier, `AppIdentifier is undefined${getInfoDocs} `).to.not.be.equal(undefined);\n    expect(appIdentifier, `AppIdentifier did not have property appId${getInfoDocs} `).to.have.property('appId');\n    expect(typeof appIdentifier!.appId).to.be.equal('string');\n    expect(appIdentifier, `AppIdentifier did not have property instanceId${getInfoDocs} `).to.have.property(\n      'instanceId'\n    );\n    expect(typeof appIdentifier!.instanceId).to.be.equal('string');\n  }\n}\n\nexport class MetadataFdc3Api {\n  async openMetadataApp(contextType?: string): Promise<AppIdentifier> {\n    if (contextType) {\n      return await fdc3.open(\n        {\n          appId: 'MetadataAppId',\n        },\n        { type: contextType }\n      );\n    } else {\n      return await fdc3.open({\n        appId: 'MetadataAppId',\n      });\n    }\n  }\n\n  async getAppInstances(): Promise<AppIdentifier[]> {\n    return await fdc3.findInstances({ appId: 'MetadataAppId' });\n  }\n\n  async getAppMetadata(appIdentifier?: AppIdentifier): Promise<AppMetadata> {\n    if (!appIdentifier) {\n      appIdentifier = {\n        appId: 'MetadataAppId',\n      };\n    }\n\n    return await fdc3.getAppMetadata(appIdentifier);\n  }\n\n  async retrieveAppControlChannel(): Promise<Channel> {\n    return await fdc3.getOrCreateChannel(constants.ControlChannel);\n  }\n\n  async raiseIntent(intent: string, contextType: string, appIdentifier: AppIdentifier): Promise<IntentResolution> {\n    return await fdc3.raiseIntent(intent, { type: contextType }, appIdentifier);\n  }\n\n  async getInfo(): Promise<ImplementationMetadata> {\n    return await fdc3.getInfo();\n  }\n}\n\nexport interface MetadataContext extends Context {\n  implMetadata?: ImplementationMetadata;\n  contextMetadata?: ContextMetadata;\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/open-control.ts",
    "content": "import { AppIdentifier, Context } from '@finos/fdc3';\n\nexport interface OpenControl {\n  //test control\n  openMockApp(targetApp: AppIdentifier, context?: Context): void;\n  closeMockApp(testId: string): Promise<void>;\n\n  // helper method\n  createTargetAppIdentifier(appId?: string): AppIdentifier;\n\n  //listening\n  contextReceiver(contextType: string, expectNotToReceiveContext?: boolean): Promise<Context>;\n  addListenerAndFailIfReceived(): Promise<void>;\n\n  //validation\n  confirmAppNotFoundErrorReceived(exception: unknown): void;\n  validateReceivedContext(contextReceiver: Context, expectedContextType: string): Promise<void>;\n  expectAppTimeoutErrorOnOpen(appId: AppIdentifier): Promise<void>;\n}\n\nexport const openApp = {\n  a: {\n    name: 'IntentAppA',\n    id: 'IntentAppAId',\n  },\n  b: {\n    name: 'MockApp',\n    id: 'MockAppId',\n  },\n  c: {\n    name: 'IntentAppC',\n    id: 'IntentAppCId',\n  },\n  d: {\n    id: 'OpenAppAId',\n  },\n  e: {\n    id: 'OpenAppBId',\n  },\n  f: {\n    name: 'IntentAppB',\n    id: 'IntentAppBId',\n  },\n};\n\nexport type OpenCommonConfig = {\n  target: string;\n  targetMultiple: string;\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/support/open-support.ts",
    "content": "import { assert, expect } from 'chai';\nimport { AppIdentifier, Context, DesktopAgent, Listener, OpenError } from '@finos/fdc3';\nimport constants from '../../constants';\nimport { ContextSender } from '../../mock/general';\nimport { failAfterTimeout } from '../../utils';\nimport { AppControlContext } from '../../context-types';\nimport { OpenControl } from './open-control';\nimport { APIDocumentation } from './apiDocuments';\nimport { closeMockAppWindow } from '../fdc3-conformance-utils';\nimport { ControlContextType } from './intent-support';\n\nconst openDocs = '\\r\\nDocumentation: ' + APIDocumentation.open + '\\r\\nCause:';\n\nexport class OpenControlImpl implements OpenControl {\n  private readonly fdc3: DesktopAgent;\n\n  constructor(fdc3: DesktopAgent) {\n    this.fdc3 = fdc3;\n  }\n\n  contextReceiver = async (contextType: string): Promise<Context> => {\n    const appControlChannel = await this.fdc3.getOrCreateChannel(constants.ControlChannel);\n\n    let listener: Listener | undefined;\n\n    const messageReceived = new Promise<Context>((resolve, reject) => {\n      appControlChannel\n        .addContextListener(contextType, (context: AppControlContext) => {\n          if (context.errorMessage) {\n            reject(new Error(context.errorMessage));\n          } else {\n            resolve(context);\n          }\n        })\n        .then(l => {\n          listener = l;\n        })\n        .catch(reject);\n    });\n\n    try {\n      const result = await Promise.race([messageReceived, failAfterTimeout(constants.NoListenerTimeout)]);\n      if (result) {\n        return result;\n      } else {\n        throw new Error('No context received from app B');\n      }\n    } finally {\n      if (listener) listener.unsubscribe();\n    }\n  };\n\n  openMockApp = async (targetApp: AppIdentifier, context?: Context) => {\n    let instanceIdentifier: AppIdentifier;\n    if (context) {\n      instanceIdentifier = await this.fdc3.open(targetApp, context);\n    } else {\n      instanceIdentifier = await this.fdc3.open(targetApp);\n    }\n    return instanceIdentifier;\n  };\n\n  //Close mock app using the interface implementation so that common tests can switch freely between different closeMockAppWindow implementations\n  async closeMockApp(testId: string) {\n    await closeMockAppWindow(testId);\n  }\n\n  createTargetAppIdentifier(appId: string) {\n    return { appId };\n  }\n\n  addListenerAndFailIfReceived = async () => {\n    const appControlChannel = await this.fdc3.getOrCreateChannel(constants.ControlChannel);\n    await appControlChannel.addContextListener(ControlContextType.CONTEXT_RECEIVED, (context: AppControlContext) => {\n      assert.fail(context.errorMessage);\n    });\n  };\n\n  confirmAppNotFoundErrorReceived = (exception: unknown) => {\n    expect(exception).to.have.property('message', OpenError.AppNotFound, openDocs);\n  };\n\n  validateReceivedContext = async (context: ContextSender, expectedContextType: string) => {\n    expect(context.context?.type).to.eq(expectedContextType, openDocs);\n  };\n\n  expectAppTimeoutErrorOnOpen = async (targetApp: AppIdentifier) => {\n    try {\n      //wait for the open promise to be rejected\n      Promise.race([\n        this.fdc3.open(targetApp, { type: 'fdc3.contextDoesNotExist' }),\n        failAfterTimeout(constants.NoListenerTimeout),\n      ]);\n    } catch (ex) {\n      expect(ex).to.have.property('message', OpenError.AppTimeout, openDocs);\n    }\n  };\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/test/testSuite.ts",
    "content": "import mocha from 'mocha';\nimport constants from '../constants';\nimport fdc3FindIntent from './advanced/fdc3.findIntent';\nimport fdc3FindIntentsByContext from './advanced/fdc3.findIntentsByContext';\nimport fdc3GetInfo from './advanced/fdc3.getInfo';\nimport fdc3getAppMetadata from './advanced/fdc3.getAppMetadata';\nimport fdc3FindInstances from './advanced/fdc3.findInstances';\nimport fdc3Open from './advanced/fdc3.open';\nimport fdc3RaiseIntent from './advanced/fdc3.raiseIntent';\nimport fdc3RaiseIntent_Result from './advanced/fdc3.raiseIntent-Result';\nimport fdc3RaiseIntent_NoAppsFound from './advanced/fdc3.raiseIntent-NoAppsFound';\nimport fdc3AppChannels from './advanced/fdc3.app-channels';\nimport fdc3UserChannels from './advanced/fdc3.user-channels';\nimport {\n  fdc3BasicGetAgent,\n  fdc3BasicCL1,\n  fdc3BasicCL2,\n  fdc3BasicIL1,\n  fdc3BasicGI1,\n  fdc3BasicAC1,\n  fdc3BasicUC1,\n  fdc3BasicJC1,\n  fdc3BasicRI1,\n  fdc3BasicRI2,\n} from './basic/fdc3.basic';\nimport {\n  fdc3ResolveAmbiguousIntentTarget,\n  fdc3ResolveAmbiguousContextTarget,\n  fdc3ResolveAmbiguousIntentTargetMultiInstance,\n  fdc3ResolveAmbiguousContextTargetMultiInstance,\n  fdc3ChannelChangedEvent,\n} from './manual/fdc3.manual';\n\ntype testSet = { [key: string]: (() => Promise<Mocha.Suite>)[] };\n\nconst basicSuite: testSet = {\n  'fdc3.basicGetAgent': [fdc3BasicGetAgent],\n  'fdc3.basicCL1': [fdc3BasicCL1],\n  'fdc3.basicCL2': [fdc3BasicCL2],\n  'fdc3.basicIL1': [fdc3BasicIL1],\n  'fdc3.basicGI1': [fdc3BasicGI1],\n  'fdc3.basicAC1': [fdc3BasicAC1],\n  'fdc3.basicUC1': [fdc3BasicUC1],\n  'fdc3.basicJC1': [fdc3BasicJC1],\n  'fdc3.basicRI1': [fdc3BasicRI1],\n  'fdc3.basicRI2': [fdc3BasicRI2],\n};\n\nconst advancedSuite: testSet = {\n  'fdc3.open': [fdc3Open],\n  'fdc3.getInfo': [fdc3GetInfo],\n  'fdc3.getAppMetadata': [fdc3getAppMetadata],\n  'fdc3.appChannels': [fdc3AppChannels],\n  'fdc3.userChannels': [fdc3UserChannels],\n  'fdc3.findInstances': [fdc3FindInstances],\n  'fdc3.findIntent': [fdc3FindIntent],\n  'fdc3.findIntentsByContext': [fdc3FindIntentsByContext],\n  'fdc3.raiseIntent': [fdc3RaiseIntent],\n  'fdc3.raiseIntent (result)': [fdc3RaiseIntent_Result],\n  'fdc3.raiseIntent (throws error)': [fdc3RaiseIntent_NoAppsFound],\n};\n\nconst ambiguousTests: testSet = {\n  'fdc3.ResolveAmbiguousIntentTarget': [fdc3ResolveAmbiguousIntentTarget],\n  'fdc3.ResolveAmbiguousContextTarget': [fdc3ResolveAmbiguousContextTarget],\n  'fdc3.ResolveAmbiguousIntentTargetMultiInstance': [fdc3ResolveAmbiguousIntentTargetMultiInstance],\n  'fdc3.ResolveAmbiguousContextTargetMultiInstance': [fdc3ResolveAmbiguousContextTargetMultiInstance],\n  'fdc3.ChannelChangedEvent': [fdc3ChannelChangedEvent],\n};\n\nfunction stripSuites(ts: testSet[]): (() => Promise<Mocha.Suite>)[] {\n  const out: (() => Promise<Mocha.Suite>)[] = [];\n  ts.map(item => {\n    const sets = Object.values(item);\n    sets.forEach(set => set.forEach(test => out.push(test)));\n  });\n  return out;\n}\n\nexport const allTests: testSet = {\n  All: stripSuites([basicSuite, advancedSuite]),\n  ...basicSuite,\n  ...advancedSuite,\n};\n\nexport const allManualTests: testSet = {\n  ...ambiguousTests,\n};\n\nexport const packs: { [index: string]: string[] } = {\n  All: ['All'],\n  'Individual Basic': Object.keys(basicSuite),\n  'Individual Advanced': Object.keys(advancedSuite),\n};\n\nexport function getPackNames(): string[] {\n  return Object.keys(packs);\n}\n\nexport function getPackMembers(packName: string): string[] {\n  return packs[packName];\n}\n\n/**\n * Intended for running tests in container with results shown\n * in HTML page\n */\nexport const executeTestsInBrowser = async (pack: string) => {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  (mocha as any).timeout(constants.TestTimeout);\n  const suite = allTests[pack];\n  for (let index = 0; index < suite.length; index++) {\n    await suite[index]();\n  }\n  mocha.run();\n};\n\n/**\n * Intended for running Manual tests in container with results shown\n * in HTML page\n */\nexport const executeManualTestsInBrowser = async (pack: string) => {\n  console.log('Pack', pack);\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  (mocha as any).timeout(constants.TestTimeout);\n  const suite = allManualTests[pack];\n  console.log('************ found suite ************', suite);\n  for (let index = 0; index < suite.length; index++) {\n    await suite[index]();\n  }\n  mocha.run();\n};\n"
  },
  {
    "path": "toolbox/fdc3-conformance/src/utils.ts",
    "content": "import { assert } from 'chai';\nimport constants from './constants';\n\nexport function failAfterTimeout(timeoutMs: number = constants.WaitTime): Promise<void> {\n  return new Promise<void>((_, reject) => {\n    setTimeout(() => {\n      reject(new Error(`Test timed out after ${timeoutMs} ms`));\n    }, timeoutMs);\n  });\n}\n\nexport async function wait(timeoutMs?: number): Promise<void> {\n  return new Promise<void>(resolve => {\n    setTimeout(() => {\n      resolve();\n    }, timeoutMs);\n  });\n}\n\nexport function wrapPromise(): {\n  promise: Promise<void>;\n  resolve: () => void;\n  reject: (reason?: unknown) => void;\n} {\n  let wrapperResolve: (() => void) | undefined;\n  let wrapperReject: ((reason?: unknown) => void) | undefined;\n\n  const promise = new Promise<void>((resolve, reject) => {\n    wrapperResolve = resolve;\n    wrapperReject = reject;\n  });\n\n  return {\n    promise,\n    resolve: wrapperResolve!,\n    reject: wrapperReject!,\n  };\n}\n\nexport function handleFail(documentation: string, ex: unknown): never {\n  const message = ex instanceof Error ? ex.message : String(ex);\n  assert.fail(documentation + message);\n}\n\n/**\n * Checks whether a received appId matches an expected unqualified appId.\n * Accepts either an exact match (e.g. 'MockAppId') or a fully qualified\n * appId with the current hostname (e.g. 'MockAppId@localhost').\n */\nexport function appIdMatches(received: string, expected: string): boolean {\n  if (received === expected) {\n    return true;\n  }\n\n  return received.split('@')[0] === expected.split('@')[0];\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/app/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <title>FDC3 Conformance Tests</title>\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <button title=\"return to selection\" type=\"button\" id=\"back-button\">\n    <svg xmlns=\"http://www.w3.org/2000/svg\" \n    xmlns:xlink=\"http://www.w3.org/1999/xlink\" \n    version=\"1.1\" \n    id=\"mdi-arrow-left-circle-outline\" \n    viewBox=\"0 0 24 24\" \n    width=\"30\" \n    height=\"30\"\n    fill=\"currentColor\">\n    <path d=\"M18,11V13H10L13.5,16.5L12.08,17.92L6.16,12L12.08,6.08L13.5,7.5L10,11H18M2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12M4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12Z\"/></svg>\n</button>\n  <div id=\"mocha\"></div>\n  <div class=\"center\" id=\"version-selector\">\n    <label for=\"testSuite\" style=\"margin-right: 23;\">Test suite:</label>\n    <select id=\"testSuite\" style=\"width: 250px;\"></select>\n    <input id=\"runButton\" value=\"Run\" type=\"button\" />\n  </div>\n  <div id=\"manualTests-selector\">\n  <div class=\"center\" >\n    <label for=\"manualTests\">Manual Tests:</label>\n    <select id=\"manualTests\" class=\"manualTests\">\n      <option value=\"test1\">fdc3.ResolveAmbiguousIntentTarget</option>\n      <option value=\"test2\">fdc3.ResolveAmbiguousContextTarget</option>\n      <option value=\"test3\">fdc3.ResolveAmbiguousIntentTargetMultiInstance</option>\n      <option value=\"test4\">fdc3.ResolveAmbiguousContextTargetMultiInstance</option>\n      <option value=\"test5\">fdc3.ChannelChangedEvent</option>\n    </select>\n    <input id=\"manualTestsRunButton\" value=\"Run\" type=\"button\" />\n  </div>\n  <p class=\"manualTestsInfo\"><span class=\"bold\">Manual Tests:</span>  Each of these tests will invoke the intent resolver of the Desktop Agent.  In order for the test to pass you will need to manually choose an application to resolve the intent.</p>\n  <p class=\"manualTestsInfo\">FDC3 Desktop Agent MUST provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForContext that return multiple options).\n\n    This is often accomplished by providing a user interface allowing the user to select the desired target application or intent and application.\n    \n    i.e. It should not fail to raise the intent or resolve it to multiple applications.</p>\n</div>\n  <p id=\"context\"></p>\n  <script src=\"../../lib/fdc3-compliance.js\"></script>\n  <script>\n    // no idea why but this doesn't seem to work when added in the above script.\n    sourceMapSupport.install();\n  </script>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/basic/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Basic Mock app</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  \n  <script src=\"../../lib/basic.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/channels/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Channels Mock App</p>\n  <p>This app is only used by the conformance framework for test purposes</p>\n  <p></p>\n  \n  <script src=\"../../lib/channel.js\"></script>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/general/index.html",
    "content": "<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n  </head>\n\n  <body>\n    <p>Conformance Framework Mock App</p>\n    <p>This app is only used by the conformance framework for test purposes.</p>\n    \n    <script src=\"../../lib/general.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-a/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App A</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-a.js\"></script>\n  \n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-b/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App B</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-b.js\"></script>\n  \n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-c/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App C</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  \n  <script src=\"../../lib/intent-c.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-d/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App D</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  \n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-e/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App E</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-e.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-f/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App F</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-f.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-g/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App G</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-g.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-h/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App H</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-h.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-i/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App I</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-i.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-j/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App J</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-j.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/intent-k/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Mock Intent App K</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  <script src=\"../../lib/intent-k.js\"></script>\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/metadata/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n</head>\n\n<body>\n  <p>Conformance Framework Metadata App</p>\n  <p>This app is only used by the conformance framework for intent test purposes.</p>\n  \n  <script src=\"../../lib/metadata.js\"></script>\n \n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/open-a/index.html",
    "content": "<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n  </head>\n\n  <body>\n    <p>Conformance Framework Open App A</p>\n    <p>This app is only used by the conformance framework for test purposes.</p>\n    \n    <script src=\"../../lib/open-a.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/apps/open-b/index.html",
    "content": "<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"stylesheet\" href=\"../../lib/index.css\" />\n  </head>\n\n  <body>\n    <p>Conformance Framework Open App B</p>\n    <p>This app is only used by the conformance framework for test purposes.</p>\n    <script src=\"../../lib/open-b.js\"></script>\n    \n  </body>\n</html>"
  },
  {
    "path": "toolbox/fdc3-conformance/static/directories/website-conformance.json",
    "content": "{\n\t\"applications\": [\n\t\t{\n\t\t\t\"appId\": \"Conformance1\",\n\t\t\t\"name\": \"Conformance1\",\n\t\t\t\"title\": \"FDC3 Conformance Framework\",\n\t\t\t\"description\": \"FDC3 Conformance testing framework - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/app/index.html\"\n\t\t\t},\n\t\t\t\"screenshots\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/screenshots/Conformance1.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\"\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"left\": \"0\",\n\t\t\t\t\t\t\"width\": 800,\n\t\t\t\t\t\t\"height\": 900\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"ConformanceListener\": {\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"fdc3.nothing\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"ChannelsAppId\",\n\t\t\t\"name\": \"ChannelsApp\",\n\t\t\t\"title\": \"Channels App\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/channels/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppAId\",\n\t\t\t\"name\": \"IntentAppA\",\n\t\t\t\"title\": \"Intent App A\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-a/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"aTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"A Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\",\n\t\t\t\t\t\t\t\t\"testContextZ\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sharedTestingIntent1\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 1\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppBId\",\n\t\t\t\"name\": \"IntentAppB\",\n\t\t\t\"title\": \"Intent App B\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-b/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent1\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 1\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\",\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextY\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppCId\",\n\t\t\t\"name\": \"IntentAppC\",\n\t\t\t\"title\": \"Intent App C\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-c/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"cTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"C Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppDId\",\n\t\t\t\"name\": \"IntentAppD\",\n\t\t\t\"title\": \"Intent App D\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-d/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppEId\",\n\t\t\t\"name\": \"IntentAppE\",\n\t\t\t\"title\": \"Intent App E\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-e/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppFId\",\n\t\t\t\"name\": \"IntentAppF\",\n\t\t\t\"title\": \"Intent App F\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-f/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel<testContextZ>\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppGId\",\n\t\t\t\"name\": \"IntentAppG\",\n\t\t\t\"title\": \"Intent App G\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-g/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppHId\",\n\t\t\t\"name\": \"IntentAppH\",\n\t\t\t\"title\": \"Intent App H\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-h/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppIId\",\n\t\t\t\"name\": \"IntentAppI\",\n\t\t\t\"title\": \"Intent App I\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-i/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppJId\",\n\t\t\t\"name\": \"IntentAppJ\",\n\t\t\t\"title\": \"Intent App J\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-j/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"privateChannelIsPrivate\": {\n\t\t\t\t\t\t\t\"displayName\": \"J Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"privateChannelDetails\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"privateChannelIsPrivateResult\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppKId\",\n\t\t\t\"name\": \"IntentAppK\",\n\t\t\t\"title\": \"Intent App K\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/intent-k/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"kTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"K Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel<testContextZ>\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"OpenAppAId\",\n\t\t\t\"name\": \"OpenAppA\",\n\t\t\t\"title\": \"Open App A\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/open-a/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"OpenAppBId\",\n\t\t\t\"name\": \"OpenAppB\",\n\t\t\t\"title\": \"Open App B\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/open-b/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"MockAppId\",\n\t\t\t\"name\": \"MockApp\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/general/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"MetadataAppId\",\n\t\t\t\"name\": \"MetadataApp\",\n\t\t\t\"title\": \"App Title\",\n\t\t\t\"description\": \"Part of the FDC3 Conformance Tests\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/apps/metadata/index.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"intents\": {\n\t\t\t\t\t\t\t\"listensFor\": {}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"placeholder\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-conformance/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"message\": \"OK\"\n}"
  },
  {
    "path": "toolbox/fdc3-conformance/static/lib/index.css",
    "content": "html {\n  font-size: 15px;\n  height: 100%;\n}\n\nbody {\n  background-color: #f7f7f7;\n  font-size: 14px;\n  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;\n  height: 100%;\n}\n\nbody {\n  height: 100%;\n}\n\n.center {\n  margin: auto;\n  width: 50%;\n}\n\n#back-button {\n  position: relative;\n  top: 0px;\n  left: 0px;\n  display: none;\n  cursor: pointer;\n  border-radius: 100%;\n  background: transparent;\n  border: none !important;\n}\n\n.manualTests {\n  width: 250px;\n}\n\n.manualTestsInfo {\n  padding-left: 100;\n  padding-right: 50;\n}\n\n.bold {\n  font-weight: bold;\n}\n\n#mocha-stats .duration em {\n  min-width: 4em;\n  display: inline-block;\n  text-align: right;\n}\n\n#mocha .test.running::before {\n  content: '●';\n  font-size: 12px;\n  display: block;\n  float: left;\n  margin-right: 5px;\n  color: #daa520;\n}\n\n#mocha li.suite {\n  padding: 0px 0px 25px 0px;\n}\n"
  },
  {
    "path": "toolbox/fdc3-conformance/terms-conditions/branding.md",
    "content": "## FDC3 Branding\n\n- [Branding Guide (pdf)](2022_FDC3_CompliantBadges.pdf)\n- [FDC3 Certified Badges In Various Formats (zip)](FDC3-Compliant-Badges.zip)"
  },
  {
    "path": "toolbox/fdc3-conformance/terms-conditions/participation-form.md",
    "content": "## Certified FDC3 Desktop Agent Conformance Program\n### Participation Form\n\nComplete this form for each Participant (company or other entity) that desires to participate in the Certified FDC3 Desktop Agent Conformance Program and to use the Certified FDC3 Marks or Participant FDC3 Combinations. FDC3 and the Certified FDC3 Marks are trademarks of The Linux Foundation. Capitalized terms used herein and not otherwise defined shall have the same meanings set forth in the Program Terms.\n\nBy signing below and submitting this form to The Linux Foundation (by [DocuSign](https://na3.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=514e8bf9-adcc-4113-898c-071acb40790a&env=na3&acct=f30e10ec-fea1-4dd8-a262-384a61edabb5&v=2) or emailing the [PDF](participation-form.pdf) to [help@finos.org](mailto:help@finos.org)):\n\n1.  The Participant agrees to the Terms and Conditions of the Certified FDC3 Conformance Program (the \"**Program Terms**\") described below.\n2.  The Participant confirms that the products and services identified below as Qualifying Offerings have passed all of the self-tests described in the Certification Guide, and are Qualifying Offerings under the Program Terms.\n3.  The Participant confirms that it has submitted to FINOS the results of the self-tests prior to its first public use of the Certified FDC3 Marks associated with the corresponding version of FDC3.\n4.  The Participant confirms that it will either (a) maintain conformance of the Qualifying Offerings with later versions of FDC3, or (b) cease use of the Certified FDC3 Marks and Participant FDC3 Combinations at the end of the applicable conformance time period described in the Program Terms.\n5. The Participant confirms that it has listed below all Participant FDC3 Combinations that it intends to use with the Qualifying Offerings.\n6.  The Participant confirms that it will promptly submit an updated Participant Form to The Linux Foundation prior to (a) using the Certified FDC3 Marks with Qualifying Offerings not listed here, or (b) using Participant FDC3 Combinations not listed here.\n7.  I confirm that I am authorized to make the above statements and to submit this form on behalf of the Participant.\n\n### Certified FDC3 Desktop Agent Conformance Program – Terms and Conditions\n\n\n#### Last updated: November 4, 2022\n\nThis document sets forth the terms and conditions that apply to the Conformance Program and use of the Certified FDC3 Marks.\n\nIn this document, these terms have the following meanings:\n\n*  \"**Certified FDC3 Marks**\" means the mark \"Certified FDC3\", \"FDC3 Certified\", \"FDC3 1.2 Certified\", \"FDC3 2.0 Certified\", \"FDC3 1.2 Certified Desktop Agent\" , \"FDC3 2.0 Certified Desktop Agent\" and variations and different version numbers thereof;\n*  \"**FDC3 Word Mark**\" means the trademark \"FDC3\";\n*  \"**Participant FDC3 Combination**\" means a combination that includes both the Participant’s mark(s) and the FDC3 Word Mark as elements (for example, \"XYZ FDC3\" or \"XYZ FDC3 Desktop Agent\");\n*  \"**Conformance Program**\" means the program described in this document;\n*  \"**Participant**\" means a company or other entity that is permitted to use one or more of the Certified FDC3 Marks in association with their goods and services, pursuant to the Conformance Program; and\n*  \"**Qualifying Offering(s)**\" means a Participant’s goods or services that have passed all of the self-tests described in the Certification Guide, where the self-test results have been submitted to and accepted by FINOS as described below.\n\n#### Related Documents\n\nTogether with these terms and conditions, the following documents are part of the Conformance Program, each as updated from time to time:\n\n*  \"**Certification Guide**\": the conformance testing instructions and requirements for the Conformance Program, available at <https://github.com/FINOS/FDC3/blob/main/toolbox/fdc3-conformance/instructions.md>;\n*  \"**Branding Guide**\": the Certified FDC3 Brand Guidelines, available at <https://github.com/FINOS/FDC3/blob/main/toolbox/fdc3-conformance/terms-conditions/branding.md>;\n*  \"**LF Trademark Usage Guidelines**\": The Linux Foundation Trademark Usage Guidelines, available at <https://www.linuxfoundation.org/trademark-usage>; and\n*  \"**Participation Form**\": the Certified FDC3 Participation Form, available at <https://github.com/FINOS/FDC3/blob/main/toolbox/fdc3-conformance/terms-conditions/participation-form.md>>.\n\n#### Introduction\n\nThe Certified FDC3 Marks and the FDC3 Word Mark are trademarks of The Linux Foundation. The Linux Foundation has established the Conformance Program to achieve two objectives: 1) The Linux Foundation needs to ensure that the Certified FDC3 Marks and the FDC3 Word Mark remain reliable indicators of the qualities that they have been created to preserve, and 2) The Linux Foundation needs to ensure that community members are able to accurately describe their Qualifying Offerings.\n\nTo achieve these objectives, The Linux Foundation requires that third parties who use the Certified FDC3 Marks or Participant FDC3 Combinations in association with their goods and services may do so only as Participants pursuant to the Conformance Program described in this document. By participating in the Conformance Program and by using the Certified FDC3 Marks or Participant FDC3 Combinations, a Participant acknowledges that third parties will be relying on the accuracy of its self-testing results and on its compliance with the terms of the Conformance Program.\n\n#### Participant Requirements\n\nIn order to be a Participant in the Conformance Program and to use the Certified FDC3 Marks or Participant FDC3 Combinations, a Participant must do the following:\n\n1. determine those of its goods and services with which it intends to use with the Certified FDC3 Marks and Participant FDC3 Combinations;\n2. confirm through self-testing that those goods and services are Qualifying Offerings, as described herein;\n3. submit to The Linux Foundation a signed Participation Form (by email to [help@finos.org](mailto:help@Ffinos.org) or other method made available by The Linux Foundation), designating the applicable Qualifying Offerings and Participant FDC3 Combinations and accepting the terms and conditions of the Conformance Program;\n4. submit to FINOS the successfully-passing self-testing results for the Qualifying Offerings, and have the results accepted by FINOS;\n5. pay fees (if any) required for its participation in the Conformance Program; and\n6. abide by the terms and conditions of the Conformance Program, including subsequent re-testing as described herein, throughout the period of the Participant’s use of the Certified FDC3 Marks and Participant FDC3 Combinations.\n\nMembers of FINOS and non-profit organizations will not be charged fees to participate in the Conformance Program. Other potential Participants should [contact](mailto:help@Ffinos.org) FINOS for more information about participation fees.\n\n#### Qualifying Offerings and Self-Testing\n\n_Eligible Versions_. A Qualifying Offering may be initially self-certified for (1) the then-current minor (x.y) official release of FDC3, and (2) the two immediately-preceding minor (x.y-1 and x.y-2) official releases of FDC3; provided, in each case, that FINOS has made available a testing evaluation program for that version of FDC3.\n\nExample: Following the release of FDC3 v2.4, a new Qualifying Offering may be initially self-certified for FDC3 v2.3, v2.2 or v2.1, but not for v2.0.\n\n_Self-Testing Process_. The Certified FDC3 Marks and Participant FDC3 Combinations are intended to be used with Participants’ goods and services that are Qualifying Offerings. The Certification Guide contains details about the self-testing process and the specific tests that must be passed for a Participant’s offering to be a Qualifying Offering. A Participant confirms that its goods and services are Qualifying Offerings by demonstrating that its offerings have successfully passed all of the self-tests set forth in the Certification Guide. FINOS will make available a testing evaluation program that Participants will use to determine whether the self-tests are passed or failed.\n\n_Submission of Self-Testing Results_. After passing the designated self-tests, a Participant must submit to FINOS (in the manner described in the Certification Guide) a copy of the self-testing results generated by the testing evaluation program no more than 90 days prior to its first public use of the Certified FDC3 Marks or Participant FDC3 Combinations. These results will be made available to the public on a FINOS website or public repository if Participant makes public use of the Certified FDC3 Marks or Participant FDC3 Combinations. However, if the Participant decides not to proceed with any such public use following submission of self-testing results to FINOS, then upon Participant’s written request to FINOS the test results will not be publicly disclosed.\n\n_Acceptance of Self-Testing Results_. The Certified FDC3 Marks and Participant FDC3 Combinations may only be used with Qualifying Offerings whose self-tests have been both submitted to and accepted by FINOS (in the manner described in the Certification Guide).\n\n_Profiles_. The Certification Guide may also specify, for certain versions of FDC3, one or more \"Profiles\" consisting of groups of different or additional functionality. These Profiles will be associated with additional sets of self-tests. If a Participant’s Qualifying Offering also passes the set of self-tests associated with a Profile, then the Participant may additionally use with the Qualifying Offering any Certified FDC3 Marks designated for that Profile.\n\n_End User Reproducibility_. One objective of the Conformance Program is that the self-tests set forth in the Certification Guide should be verifiable by end users of each Qualifying Offering. A Participant may not prohibit or prevent end users of its Qualifying Offerings from running the corresponding self-tests on a Qualifying Offering, in order to reproduce the submitted results and verify their accuracy. If The Linux Foundation determines or is informed that (1) end users of a Qualifying Offering are prevented from running the tests, or (2) that end users’ results from running the tests demonstrate that a Qualifying Offering does not successfully pass the tests, then upon written notice from The Linux Foundation the Participant must address any non-conformance concerns raised by The Linux Foundation; successfully pass the corresponding self-tests; and submit to FINOS a copy of the new self-testing results generated by the testing evaluation program within 30 days following such notice. Otherwise, the Participant will be subject to the requirements to remove the Certified FDC3 Marks and Participant FDC3 Combinations set forth herein.\n\n_Changes to Qualifying Offerings_. The self-testing process and permission to use the Certified FDC3 Marks and Participant FDC3 Combinations are intended for a specific version of a Qualifying Offering. If a Participant subsequently modifies a Qualifying Offering, and The Linux Foundation determines or is informed that the Qualifying Offering no longer conforms to the compatibility tests set forth in the Certification Guide or to users’ expectations for Qualifying Offerings, then upon written notice from The Linux Foundation the Participant must again successfully pass the corresponding self-tests and submit to FINOS a copy of the new self-testing results generated by the testing evaluation program within 30 days following such notice. \n\n_Removal of Certified FDC3 Marks and Participant FDC3 Combinations at End of Participation_. After the termination of participation in the Conformance Program, a Participant may no longer use the Certified FDC3 Marks or Participant FDC3 Combinations in new materials, and must remove the Certified FDC3 Marks and Participant FDC3 Combinations from existing marketing materials and websites within 30 days.\n\n#### Use of the Certified FDC3 Marks and Participant FDC3 Combinations\n\nUse of the Certified FDC3 Marks and Participant FDC3 Combinations is only permitted for Participants who have satisfied the requirements of the Conformance Program; and is only permitted in connection with its Qualifying Offerings. No other rights to use the Certified FDC3 Marks or the FDC3 Word Mark are permitted hereunder, except to the extent permitted under \"fair use\" or other applicable law.\n\nAll use of the Certified FDC3 Marks and Participant FDC3 Combinations is subject to the LF Trademark Usage Guidelines, which are incorporated herein.\n\nAdditionally, the following specific rules also apply to use of the Certified FDC3 Marks and Participant FDC3 Combinations:\n\n*  **Do** follow the requirements set forth in the Branding Guide when using the Certified FDC3 Marks.\n\n*  **Do** specify the version of FDC3 for which a Qualifying Offering has been self-tested, in a location near the Participant’s use of the Certified FDC3 Marks.\n\n*  **Do** include appropriate notices of The Linux Foundation’s ownership of the Certified FDC3 Marks and the FDC3 Word Mark.\n\n*  **Do not** use the Certified FDC3 Marks or Participant FDC3 Combinations except as permitted pursuant to the Conformance Program’s terms. For example, do not use the Certified FDC3 Marks or Participant FDC3 Combinations with a service offering that is not itself a Qualifying Offering, or with a formerly Qualifying Offering whose period of use has expired.\n\n*  **Do not** be misleading about the nature or scope of certification or conformance. **Do not** state or imply that the Participant’s participation in the Conformance Program constitutes The Linux Foundation’s or FINOS’s endorsement of a Participant or its goods or services. For example, do not say that a Participant or a Qualifying Offering has been \"certified by FINOS\" or \"certified by The Linux Foundation,\" or that \"The Linux Foundation has certified Product XYZ.\"\n\n*  **Do not** state or imply that there are different degrees of certification or conformance. For example, do not say that a Qualifying Offering is \"more certified\" than another, or that it was \"certified before\" another Participant. However, this does not prohibit use of Certified FDC3 Marks designated for Profiles that a Qualifying Offering has passed, as described above.\n\n#### Additional Terms for Use of Participant FDC3 Combinations\n\nIn addition to the rules set forth above and in the LF Trademark Usage Guidelines, the following specific rules also apply to use of Participant FDC3 Combinations:\n\n*  **Do** use the \"circle R\" symbol adjacent to the end of the FDC3 Word Mark within the first prominent appearance of the Participant FDC3 Combination, for example: XYZ FDC3® Engine.\n\n*  **Do** include the following attribution statement in a conspicuous location near the first prominent appearance of the Participant FDC3 Combination: FDC3® is a registered trademark of The Linux Foundation in the United States and other countries, and is used pursuant to a license from The Linux Foundation.\n\n*  **Do** use the Participant FDC3 Combination only in plain text form, in a similar font to the surrounding text (e.g., in the same font and style used for other header or body text on a web page).\n\n*  **Do not** use the Participant FDC3 Combination in a stylized form, or incorporate the Participant FDC3 Combination or FDC3 Word Mark into a custom logo.\n\nDuring and after the term of Participant’s participation in the Conformance Program, Participant will not, anywhere in the world, (1) register or attempt to register a mark that contains or consists of the FDC3 Word Mark or Participant FDC3 Combination; or (2) challenge, oppose, petition to cancel or otherwise attack or limit the FDC3 Word Mark (whether its validity, enforceability, scope of coverage or otherwise) or The Linux Foundation’s exclusive ownership thereof. Performing either of the preceding actions shall constitute a material breach of the terms of the Conformance Program, resulting in termination of Participant’s participation in the Conformance Program without further notice and without opportunity to cure.\n\nParticipant will promptly cooperate with The Linux Foundation, and comply with its requests and instructions, regarding use of the Participant FDC3 Combination. The Linux Foundation shall have a reasonable right to request copies of and to inspect products and advertising distributed by Participant as an aid to enforcing the FDC3 Word Mark and its rights hereunder, as a part of policing the FDC3 Word Mark. Participant will promptly cease any use of the Participant FDC3 Combination that The Linux Foundation determines may negatively impact the validity, enforceability or scope of coverage of the FDC3 Word Mark.\n\nParticipant will not otherwise combine the FDC3 Word Mark with its own marks, other than Participant FDC3 Combinations used in full compliance with the terms of the Conformance Program.\n\n#### Participant Marks\n\nEach Participant hereby grants to The Linux Foundation a royalty-free, worldwide license to use and display the names and logos of Participant and its Qualifying Offerings (the \"Participant Marks\") in connection with The Linux Foundation’s operation of the Conformance Program and its marketing and promotion of Participant’s participation in the Conformance Program. Each Participant represents and warrants that it possesses all rights necessary to make this license grant. The Linux Foundation will comply with any reasonable requirements regarding use of the Participant Marks about which the Participant notifies The Linux Foundation, and will correct any identified misuse within a reasonable time following Participant’s notification. Nothing in this section shall require The Linux Foundation to make any use of the Participant Marks. As between The Linux Foundation and Participant, any goodwill associated with the foregoing use of the Participant Marks shall inure to the benefit of the Participant.\n\n#### Term and Termination\n\n_Term_. The term of a Participant’s participation in the Conformance Program shall begin upon the Participant’s submission (by email to [help@finos.org](mailto:help@finos.org) or other method made available by The Linux Foundation), and The Linux Foundation’s receipt and acceptance, of a fully-completed Participation Form signed by the Participant.\n\n_Termination_. Either The Linux Foundation or the Participant may terminate Participant’s participation in the Conformance Program upon written notice to the other. Additionally, Participant’s participation in the Conformance Program shall automatically terminate (unless otherwise agreed by The Linux Foundation in writing) upon the occurrence of the Participant’s breach of the terms of the Conformance Program, if such breach is incurable or, if curable, is not cured within 15 days thereafter\n.\n\n_Effect of Termination; Survival_. Upon the termination of Participant’s participation in the Conformance Program, the Participant may no longer use the Certified FDC3 Marks or Participant FDC3 Combinations and must remove them from existing marketing materials and websites. The sections of this agreement entitled \"Participant Marks,\" \"Disclaimer of Warranties,\" \"Limitation of Liability,\" \"Indemnification\" and \"Miscellaneous\" shall survive any such termination.\n\n#### Disclaimer of Warranties\n\nTHE LINUX FOUNDATION MAKES NO EXPRESS OR IMPLIED WARRANTIES WITH RESPECT TO THE CONFORMANCE PROGRAM, THE CERTIFIED FDC3 MARKS OR PARTICIPANT FDC3 COMBINATIONS, EITHER TO PARTICIPANT OR TO ANY THIRD PARTY, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OR NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHTS. THE DISCLAIMERS AND INDEMNITIES SET FORTH IN THE LF TRADEMARK USAGE GUIDELINES ARE ALSO DEEMED TO BE INCORPORATED HEREIN. A PARTICIPANT’S PARTICIPATION IN THE CONFORMANCE PROGRAM DOES NOT CONSTITUTE ANY FORM OF ENDORSEMENT BY THE LINUX FOUNDATION OF ANY PARTICIPANT OR ITS QUALIFYING OFFERINGS, AND THE LINUX FOUNDATION MAKES NO EXPRESS OR IMPLIED WARRANTIES WITH RESPECT THERETO. THE CONFORMANCE PROGRAM IS OFFERED \"AS-IS\", \"AS-AVAILABLE\" AND \"WITH ALL FAULTS.\"\n\n#### Limitation of Liability\n\nTO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE LINUX FOUNDATION SHALL NOT BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY OR PUNITIVE DAMAGES, ARISING OUT OF OR RELATING TO THE CONFORMANCE PROGRAM OR ANY PARTICIPANT’S PARTICIPATION THEREIN. IF ANY DAMAGES ARE NOT EXCLUDED UNDER APPLICABLE LAW PURSUANT TO THE PRECEDING SENTENCE, THEN IN NO EVENT SHALL THE LINUX FOUNDATION’S LIABILITY FOR ANY SUCH DAMAGES EXCEED THE FEES PAID TO THE LINUX FOUNDATION BY THE PARTICIPANT SOLELY FOR PARTICIPATION IN THE CONFORMANCE PROGRAM. THE FOREGOING LIMITATIONS OF LIABILITY ARE AN ESSENTIAL BASIS OF THE LINUX FOUNDATION’S DECISION TO OFFER THE CONFORMANCE PROGRAM AND THE PARTICIPANT’S PARTICIPATION THEREIN, AND SHALL APPLY REGARDLESS OF THE LEGAL THEORY UPON WHICH DAMAGES MAY BE CLAIMED; REGARDLESS OF WHETHER A PARTY KNEW OR SHOULD HAVE KNOWN OF THE POSSIBILITY OF SUCH DAMAGES; AND REGARDLESS OF WHETHER THE FOREGOING LIMITATIONS OF LIABILITY CAUSE ANY REMEDY TO FAIL IN ITS ESSENTIAL PURPOSE.\n\n#### Indemnification\n\nBy electing to participate in the Conformance Program or to make any use of the Certified FDC3 Marks or Participant FDC3 Combinations, each Participant agrees to indemnify, defend and hold harmless The Linux Foundation, together with its affiliates and its and their respective employees, officers and directors (collectively, the \"Indemnified Parties\") from and against any and all losses, liabilities, damages and penalties, and all related costs and expenses (including reasonable attorneys' fees) arising from (1) the Participant’s breach of the terms of the Conformance Program, (2) any third party claims that may arise in any manner by reason of Participant’s use of the Certified FDC3 Marks or the Participant FDC3 Combination with the Participant’s Qualifying Offerings or the Participant’s other goods and services, and (3) any third-party claim relating to the Participant’s Qualifying Offerings or the Participant’s other goods and services, including without limitation any product liability claim.\n\n#### Entire Agreement; Modifications\n\nThese Terms and Conditions, together with the other documents referenced herein, constitute the entire agreement between any Participant and The Linux Foundation regarding Participant’s participation in the Conformance Program. These Terms and Conditions and the other documents referenced herein may be modified from time to time by The Linux Foundation, and updated versions will be placed on the FINOS website. Participant’s continued participation in the Conformance Program or continued use of the Certified FDC3 Marks or Participant FDC3 Combinations constitutes Participant’s acceptance of all such modifications.\n\n#### Miscellaneous\n\nAll notices to be sent to The Linux Foundation hereunder should be sent to [help@finos.org](mailto:help@finos.org), unless otherwise specified herein. The Conformance Program Terms and Conditions are governed by the law of the State of California, without regards to its choice of law provisions, and any action arising hereunder shall be brought in the state or federal courts located in California. The Participant and The Linux Foundation agree that the Conformance Program does not create a partnership or joint venture between them or any other P\n\n### Participant Information\n\n\nCompany / entity name:\n\n\\___________________________________________________\n\nContact address:\n\n\\___________________________________________________\n\n\\___________________________________________________\n\n\\___________________________________________________\n\n\\___________________________________________________\n\nContact telephone:\n\n\\___________________________________________________\n\nContact email:\n\n\\___________________________________________________\n\n\nSelect one:\n\n - [ ] Participant is a member of FINOS.\n - [ ] Participant is a non-profit organization.\n - [ ] Neither of the above. **Please contact FINOS to discuss fees for participation in the Conformance Program.**\n\n#### Qualifying Offerings\n\nName, brief description and URLs for more information:\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\n#### Participant FDC3 Combinations\n\nList all Participant FDC3 Combinations to be used with the Qualifying Offerings, if any:\n\n(for example, \"XYZ FDC3\" or \"XYZ FDC3 Platform\")\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\\_____________________________________________________\n\n\n#### Conformance Details\n\nInitial Version of FDC3 for Conformance (e.g., v2.0): _______\n\nConformance Date: __________________\n\n\n### Signed on behalf of Participant by:\n\n```\nSignature: __________________________________\n\nName:      __________________________________\n\nTitle:     __________________________________\n\nDate:      __________________________________\n```\n"
  },
  {
    "path": "toolbox/fdc3-conformance/tsconfig.json",
    "content": "{\n    \"extends\": \"../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"rootDir\": \"src\",\n        \"moduleResolution\": \"node\",\n        \"module\": \"ESNext\",\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src\"\n    ],\n    \"references\": [\n        {\n            \"path\": \"../../packages/fdc3\"\n        }\n    ]\n}"
  },
  {
    "path": "toolbox/fdc3-conformance/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n    browser: {\n      enabled: true,\n      provider: 'preview',\n      instances: [\n        {\n          browser: 'chromium',\n          setupFile: './chromium-setup.js',\n        },\n      ],\n    },\n  },\n});\n"
  },
  {
    "path": "toolbox/fdc3-conformance/webpack.config.js",
    "content": "/* eslint-disable */\nconst path = require('path');\nconst webpack = require('webpack');\n\nconst isProduction = process.env.NODE_ENV == 'production';\n\nconst config = {\n  entry: {\n    'fdc3-compliance': './src/test/index.ts',\n    channel: './src/mock/channel.ts',\n    general: './src/mock/general.ts',\n    metadata: './src/mock/metadata.ts',\n    'intent-a': './src/mock/intent-a.ts',\n    'intent-b': './src/mock/intent-b.ts',\n    'intent-c': './src/mock/intent-c.ts',\n    'intent-d': './src/mock/intent-d.ts',\n    'intent-e': './src/mock/intent-e.ts',\n    'intent-f': './src/mock/intent-f.ts',\n    'intent-g': './src/mock/intent-g.ts',\n    'intent-h': './src/mock/intent-h.ts',\n    'intent-i': './src/mock/intent-i.ts',\n    'intent-j': './src/mock/intent-j.ts',\n    'intent-k': './src/mock/intent-k.ts',\n    basic: './src/mock/basic.ts',\n    'open-a': './src/mock/open-a.ts',\n  },\n  devtool: 'source-map',\n  output: {\n    filename: '[name].js',\n    //globalObject: 'this',\n    path: path.resolve(__dirname, './dist/lib'),\n  },\n  plugins: [\n    new webpack.ProvidePlugin({\n      process: 'process/browser.js',\n      Buffer: ['buffer', 'Buffer'],\n    }),\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.(ts|tsx)$/i,\n        loader: 'ts-loader',\n        exclude: [path.resolve(__dirname, '/node_modules/')],\n      },\n      {\n        test: /\\.css$/,\n        use: ['style-loader', 'css-loader'],\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.tsx', '.ts', '.js'],\n    fallback: {\n      util: require.resolve('util/'),\n      stream: require.resolve('stream-browserify/'),\n      buffer: require.resolve('buffer/'),\n      window: false,\n    },\n  },\n};\n\nmodule.exports = () => {\n  if (isProduction) {\n    config.mode = 'production';\n  } else {\n    config.mode = 'development';\n  }\n  return config;\n};\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.0/index.html",
    "content": "<html>\n  <!-- \n  \n  /**\n   * SPDX-License-Identifier: Apache-2.0\n   * Copyright FINOS FDC3 contributors - see NOTICE file\n   */\n  \n   -->\n<head>\n\t<title>FDC3 Explained</title>\n\t<link rel=\"stylesheet\" href=\"./styles.css\">\n\t<script type=\"module\" src=\"./main.js\" defer></script>\n</head>\n\n<body>\n\n\t<table border=\"1\">\n\t\t<tr>\n\t\t\t<td colspan=\"3\" style=\"text-align:center;\">Back to <a href=\"..\">main page</a>.</td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"header\">FDC3 Provider:</td>\n\t\t\t<td><span id=\"providerDetails\">FDC3 Not Available</span></td>\n    </tr>\n\n\t\t<tr>\n\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"header\">App Directory:</td>\n\t\t\t<td><span id=\"directoryDetails\">No Application Directory Connected</span></td>\n\t\t\t<td><input type=\"button\" value=\"Connect\" disabled></td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"header\">Available Apps:</td>\n\t\t\t<td><textarea disabled></textarea></td>\n\t\t\t<td><input type=\"button\" value=\"Fetch\" disabled></td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"header\">Broadcast Context:</td>\n\t\t\t<td>\n        <textarea id=\"broadcastText\" disabled>{\n  \"type\":\"fdc3.instrument\",\n  \"id\": {\n    \"ISIN\":\"US0378331005\",\n    \"SEDOL\":\"2046251\",\n    \"ticker\":\"AAPL\"\n  },\n  \"name\":\"Apple Inc.\"\n}</textarea>\n      </td>\n\t\t\t<td>\n        <input type=\"button\"\n               value=\"Send\"\n               id=\"broadcastButton\"\n               disabled>\n      </td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"header\" rowspan=\"3\">Get Context:</td>\n      <td><textarea disabled>Not implemented</textarea></td>\n\t\t\t<td>\n        <input type=\"button\" value=\"Subscribe\" disabled />\n        <br />\n        <input type=\"button\" value=\"Unsbscribe\" disabled />\n      </td>\n\t\t</tr>\n\t</table>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.0/main.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n// enable application when FDC3 is available\ndocument.addEventListener('DOMContentLoaded', () => {\n  fdc3Init(enablePage);\n});\n\n// check if FDC3 is available\nfunction fdc3Init(callback) {\n  let fdc3Tries = 10;\n\n  const onFDC3Ready = () => {\n    if (window.fdc3) {\n      callback.call(this);\n    } else {\n      if (fdc3Tries > 0) {\n        fdc3Tries--;\n        window.setTimeout(onFDC3Ready, 100);\n      }\n    }\n  };\n\n  onFDC3Ready();\n}\n\nconst providerDetails = document.getElementById('providerDetails');\nconst broadcastButton = document.getElementById('broadcastButton');\nconst broadcastText = document.getElementById('broadcastText');\n\nfunction enablePage() {\n  console.log('FDC3 is available');\n\n  // NOTE: conceptually replaced with fdc3.getInfo\n  if (window.FSBL) {\n    window.FSBL.getFSBLInfo().then(info => updateProviderDetails('Available - Finsemble ' + info.FSBLVersion));\n  } else if (window.fin) {\n    updateProviderDetails('Available - OpenFin ' + fin.desktop.getVersion());\n  } else {\n    updateProviderDetails('Available - Unknown');\n  }\n\n  broadcastButton.disabled = false;\n  broadcastText.disabled = false;\n}\n\nfunction updateProviderDetails(details) {\n  providerDetails.innerText = details;\n}\n\nfunction broadcastFDC3Context() {\n  var context = JSON.parse(broadcastText.value);\n  fdc3.broadcast(context);\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.0/styles.css",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\ntextarea {\n  width: 400px;\n  height: 150px;\n}\n\nselect {\n  width: 150px;\n  height: 24px;\n}\n\n.ctxInput {\n  width: 241px;\n  height: 24px;\n}\n\n.urlInput {\n  width: 400px;\n  height: 24px;\n}\n\n.header {\n  width: 200px;\n  height: 40px;\n  font-weight: 700;\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.1/index.html",
    "content": "<html>\n  <!-- \n  \n  /**\n   * SPDX-License-Identifier: Apache-2.0\n   * Copyright FINOS FDC3 contributors - see NOTICE file\n   */\n  \n   -->\n<head>\n\t<title>FDC3 Explained</title>\n  <meta charset=\"UTF-8\">\n\t<link rel=\"stylesheet\" href=\"./styles.css\">\n\t<script type=\"module\" src=\"./main.js\" defer></script>\n</head>\n\n<body>\n\t<div class=\"main\">\n\t\t<table border=\"1\">\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\" style=\"text-align:center;\">Back to <a href=\"..\">main page</a>.</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">FDC3 Supported </td>\n\t\t\t\t<td><span id=\"fdc3-support\">Checking...</span></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">FDC3 Provider:</td>\n\t\t\t\t<td><span id=\"providerDetails\">None</span></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">App Directory:</td>\n\t\t\t\t<td><span id=\"directoryDetails\">Not supported yet!</span></td>\n\t\t\t\t<td><input type=\"button\" value=\"Connect\" class=\"not-supported\" disabled></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Available Apps:</td>\n\t\t\t\t<td><textarea disabled></textarea></td>\n\t\t\t\t<td><input type=\"button\" value=\"Fetch\" disabled></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Available Channels:</td>\n\t\t\t\t<td>\n\t\t\t\t\tSystem Channels:\n\t\t\t\t\t<ul id=\"system-channel-list\"></ul>\n\t\t\t\t\tApp Channels:\n\t\t\t\t\t<ul id=\"app-channel-list\"></ul>\n\t\t\t\t</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Add App Channel:</td>\n\t\t\t\t<td><input id=\"app-channel\"></input></td>\n\t\t\t\t<td><Button type=\"button\" id=\"add-app-channel__btn\" disabled>Add</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Join Channel:</td>\n\t\t\t\t<td>Channel: <select class=\"fdc3-channels\" id=\"join-channel\"></select>\n\t\t\t\t\t<Button type=\"button\" id=\"join-channel__btn\" disabled>Join</Button>\n\t\t\t\t</td>\n\t\t\t\t<td><Button type=\"button\" id=\"leave-channel__btn\" disabled>Leave</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"2\">Broadcast Context:</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>\n          <textarea id=\"txtBroadcastData\">{\n  \"type\":\"fdc3.instrument\",\n  \"id\": {\n    \"ISIN\":\"US0378331005\",\n    \"SEDOL\":\"2046251\",\n    \"ticker\":\"AAPL\"\n  },\n  \"name\":\"Apple Inc.\"\n}</textarea>\n        </td>\n        <td rowspan=\"2\">\n          <Button type=\"button\" id=\"broadcast__btn\" disabled>Send</Button>\n        </td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"3\">Context received:</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>Context Type: <input type=\"text\" id=\"context-type\"></td>\n\t\t\t\t<td><Button type=\"button\" id=\"get_context__btn\" disabled>Get context</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td><textarea id=\"context-result\" disabled></textarea></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"3\">Raise Intent:</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>Intent: <input type=\"text\" id=\"intent\" value=\"ViewChart\"></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td><textarea id=\"intent-context\">{\n  \"type\":\"fdc3.instrument\",\n  \"id\": {\n    \"ISIN\":\"US0378331005\",\n    \"SEDOL\":\"2046251\",\n    \"ticker\":\"AAPL\"\n  },\n  \"name\":\"Apple Inc.\"\n}</textarea>\n        </td>\n\t\t\t\t<td>\n          <Button id=\"raise-intent__btn\" disabled>Raise Intent </Button>\n        </td>\n\t\t\t</tr>\n\n\t\t</table>\n\t</div>\n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.1/main.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  fdc3OnReady(main, displayFDC3Support);\n});\n\nfunction fdc3OnReady(success, error) {\n  let fdc3Tries = 10;\n\n  const checkFDC3Ready = () => {\n    if (window.fdc3) {\n      success.call(this);\n    } else {\n      if (fdc3Tries > 0) {\n        fdc3Tries--;\n        window.setTimeout(checkFDC3Ready, 100);\n      } else {\n        error.call(this);\n      }\n    }\n  };\n  checkFDC3Ready();\n}\n\n// use this to keep track of context listener - one per system channel\nlet contextListener = null;\nlet appChannels = [];\n\nfunction main() {\n  try {\n    console.log('FDC3 is ready and DOM has rendered');\n    displayFDC3Support();\n    getPlatform();\n    populateHTML();\n    setUpEventListeners();\n    getContext();\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nfunction displayFDC3Support() {\n  try {\n    const supportedElement = document.getElementById('fdc3-support');\n    if (window.fdc3) {\n      supportedElement.innerHTML = 'Yes ✅';\n    } else {\n      supportedElement.innerHTML = 'No ❌';\n    }\n  } catch (error) {\n    console.error(\"Can't find FDC3 support\", error);\n  }\n}\n\nfunction getPlatform() {\n  // TODO: add G42 and FDC3 Desktop Agent to vendors\n  // NOTE: conceptually replaced with fdc3.getInfo\n  if (window.FSBL) {\n    window.FSBL.getFSBLInfo().then(info => updateProviderDetails('Available - Finsemble ' + info.FSBLVersion));\n  } else if (window.fin) {\n    updateProviderDetails('Available - OpenFin ' + fin.desktop.getVersion());\n  } else {\n    updateProviderDetails('Available - Unknown');\n  }\n}\n\nfunction updateProviderDetails(details) {\n  const providerDetails = document.getElementById('providerDetails');\n  providerDetails.innerText = details;\n}\n\nasync function populateHTML() {\n  try {\n    //populate available channels list with system channels\n    const channelList = document.getElementById('system-channel-list');\n\n    const populateChannelsList = id => {\n      let node = document.createElement('li');\n      let textNode = document.createTextNode(id);\n      node.appendChild(textNode);\n      channelList.appendChild(node);\n    };\n\n    const systemChannels = await fdc3.getSystemChannels();\n\n    // for all of the system channels populate dropdowns & lists\n    systemChannels.forEach(({ displayMetadata, id, type }) => {\n      populateChannelsList(id);\n      populateChannelsDropDown(id);\n    });\n\n    // as FDC3 is supported we can enable the buttons again except those that are not yet supported features\n    document.querySelectorAll('button').forEach(button => {\n      if (!button.className.includes('not-supported')) {\n        button.disabled = false;\n      }\n    });\n  } catch (error) {\n    console.error('unable to populate the html for the page ', error);\n  }\n}\n\nfunction setUpEventListeners() {\n  document.getElementById('add-app-channel__btn').addEventListener('click', addAppChannel);\n\n  document.getElementById('join-channel__btn').addEventListener('click', joinChannel);\n\n  document.getElementById('leave-channel__btn').addEventListener('click', () => {\n    fdc3.leaveCurrentChannel();\n  });\n\n  document.getElementById('broadcast__btn').addEventListener('click', broadcastFDC3Context);\n\n  document.getElementById('raise-intent__btn').addEventListener('click', raiseIntent);\n\n  document.getElementById('get_context__btn').addEventListener('click', event => {\n    let contextType = document.getElementById('context-type').value;\n    getContext(contextType);\n  });\n}\n\n/**\n *Populate the channel dropdown elements\n */\nfunction populateChannelsDropDown(newOptionText) {\n  try {\n    let dropdownElement = document.querySelector('.fdc3-channels');\n\n    if (newOptionText) {\n      dropdownElement.add(new Option(newOptionText));\n    } else {\n      throw new Error('No option provided');\n    }\n  } catch (error) {\n    console.error('could not add a new channel to the channel dropdown list', error);\n  }\n}\n\nfunction joinChannel() {\n  try {\n    let dropdownElement = document.getElementById('join-channel');\n    let channelName = dropdownElement.options[dropdownElement.selectedIndex].text;\n    fdc3.joinChannel(channelName);\n  } catch (error) {\n    console.error(\"Can't join channel\", error);\n  }\n}\n\nasync function broadcastFDC3Context() {\n  try {\n    let contextData = document.getElementById('txtBroadcastData').value;\n    fdc3.broadcast(JSON.parse(contextData));\n  } catch (error) {\n    console.error('could not broadcast', error);\n  }\n}\n\nasync function getContext(contextType) {\n  try {\n    let contextResultBox = document.getElementById('context-result');\n    if (contextListener) contextListener.unsubscribe();\n\n    // if context type is passed in then only listen on that specific context\n    if (contextType) {\n      contextListener = fdc3.addContextListener(\n        contextType,\n        context => (contextResultBox.value = JSON.stringify(context, null, 2))\n      );\n    } else {\n      contextListener = fdc3.addContextListener(context => (contextResultBox.value = JSON.stringify(context, null, 2)));\n    }\n  } catch (error) {\n    console.error('Unable to add a context listener', error);\n  }\n}\n\nasync function addAppChannel() {\n  try {\n    let appChannelName = document.getElementById('app-channel').value;\n\n    if (!appChannelName) throw new Error('no channel name set');\n\n    let appChannelExists = appChannels.find(appChannel => appChannel.id === appChannelName);\n\n    if (!appChannelExists) {\n      let newAppChannel = await fdc3.getOrCreateChannel(appChannelName);\n      appChannels.push(newAppChannel);\n\n      // add to the list of available app channels\n      let node = document.createElement('li');\n      let textNode = document.createTextNode(appChannelName);\n      node.appendChild(textNode);\n      document.getElementById('app-channel-list').appendChild(node);\n\n      //populate the channel list dropdown with new appChannel\n      populateChannelsDropDown(newAppChannel.id);\n    } else {\n      throw new Error('app channel already exists');\n    }\n  } catch (error) {\n    console.error('could not add an app channel', error);\n  }\n}\n\nasync function raiseIntent() {\n  try {\n    // get the channel\n    let intent = document.getElementById('intent').value;\n    let context = JSON.parse(document.getElementById('intent-context').value);\n\n    // TODO: add the target param\n    await fdc3.raiseIntent(intent, context);\n  } catch (err) {\n    console.error('intent did not resolve', err);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.1/styles.css",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap');\n\nbody {\n  font-family: 'Noto Sans JP', sans-serif;\n  margin: 0;\n  padding: 0;\n  background-color: white;\n}\n\n.main {\n  margin: 10px 0;\n  padding: 0;\n  display: flex;\n  place-content: center;\n}\ntable {\n  border: 0;\n}\ntr {\n  border: 0;\n}\ntd {\n  border: 0;\n}\ntextarea {\n  width: 400px;\n  height: 150px;\n}\n\nselect {\n  width: 238px;\n  height: 24px;\n}\n\n.ctxInput {\n  width: 241px;\n  height: 24px;\n}\n\n.urlInput {\n  width: 400px;\n  height: 24px;\n}\n\n.header {\n  width: 200px;\n  height: 40px;\n  font-weight: 700;\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.2/index.html",
    "content": "<html>\n\n<head>\n\t<title>\n\t\tFDC3 Explained\n\t</title>\n\n\n<meta charset=\"UTF-8\">\n\t<link rel=\"stylesheet\" href=\"./styles.css\" />\n\t<script type=\"module\" src=\"./main.js\" defer></script>\n\n</head>\n\n<body class=\"body\">\n\t<div class=\"main\">\n\t\t<a href=\"../\"><img id=\"logo\" src=\"../logo.svg\"></a>\n\t\t<table border=\"1\">\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">FDC3 Supported </td>\n\t\t\t\t<td><span id=\"fdc3-support\">Checking...</span></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">FDC3 Provider:</td>\n\t\t\t\t<td><span id=\"providerDetails\">None</span></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">FDC3 Version:</td>\n\t\t\t\t<td><span id=\"fdc3Details\">None</span></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">App Directory:</td>\n\t\t\t\t<td><span id=\"directoryDetails\">Not supported yet!</span></td>\n\t\t\t\t<td><Button class=\"not-supported\" type=\"button\" disabled>Connect</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Available Apps:</td>\n\t\t\t\t<td><textarea disabled></textarea></td>\n\t\t\t\t<td><Button class=\"not-supported\" type=\"button\" disabled>Fetch</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Available Channels:</td>\n\t\t\t\t<td>\n\t\t\t\t\tSystem Channels:\n\t\t\t\t\t<ul id=\"system-channel-list\"></ul>\n\t\t\t\t\tApp Channels:\n\t\t\t\t\t<ul id=\"app-channel-list\"></ul>\n\t\t\t\t</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Add App Channel:</td>\n\t\t\t\t<td><input id=\"app-channel\"></input></td>\n\t\t\t\t<td><Button type=\"button\" id=\"add-app-channel__btn\" disabled>Add</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\">Join Channel:</td>\n\t\t\t\t<td>Channel: <select class=\"fdc3-channels\" id=\"join-channel\"></select>\n\t\t\t\t\t<Button type=\"button\" id=\"join-channel__btn\" disabled>Join</Button>\n\t\t\t\t</td>\n\t\t\t\t<td><Button type=\"button\" id=\"leave-channel__btn\" disabled>Leave</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\"><hr/></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"2\">Broadcast Context:</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>\n          <textarea id=\"txtBroadcastData\">{\n  \"type\":\"fdc3.instrument\",\n  \"id\": {\n    \"ISIN\":\"US0378331005\",\n    \"SEDOL\":\"2046251\",\n    \"ticker\":\"AAPL\"\n  },\n  \"name\":\"Apple Inc.\"\n}</textarea>\n        </td>\n        <td rowspan=\"2\"><Button type=\"button\" id=\"broadcast__btn\" disabled>Send</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"3\">Context received:</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>Context Type: <input type=\"text\" id=\"context-type\"></td>\n\t\t\t\t<td><Button type=\"button\" id=\"get_context__btn\" disabled>Get context</Button></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<pre id=\"context-result\"><i>Context result will appear here.</i></pre>\n\t\t\t\t\t</div>\n\t\t\t\t</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td colspan=\"3\">\n\t\t\t\t\t<hr/>\n\t\t\t\t</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td class=\"header\" rowspan=\"3\">Raise Intent:</td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>Intent: <input type=\"text\" id=\"intent\" value=\"ViewChart\"></td>\n\t\t\t</tr>\n\n\t\t\t<tr>\n\t\t\t\t<td>\n          <textarea id=\"intent-context\">{\n  \"type\":\"fdc3.instrument\",\n  \"id\": {\n    \"ISIN\":\"US0378331005\",\n    \"SEDOL\":\"2046251\",\n    \"ticker\":\"AAPL\"\n  },\n  \"name\":\"Apple Inc.\"\n}</textarea>\n        </td>\n\t\t\t\t<td><Button id=\"raise-intent__btn\" disabled>Raise Intent </Button></td>\n\t\t\t</tr>\n\n\t\t</table>\n\t</div>\n</body>\n\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.2/main.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n// check for FDC3 support\nfunction fdc3OnReady(success, error) {\n  window.setTimeout(error, 1000);\n  if (window.fdc3) {\n    success();\n  } else {\n    window.addEventListener('fdc3Ready', success);\n  }\n}\n\n// Wait for the document to load\nfunction documentLoaded(cb) {\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', cb);\n  } else {\n    cb();\n  }\n}\n\n// use this to keep track of context listener - one per system channel\nlet contextListener = null;\nlet appChannels = [];\n\n//  document and FDC3 have loaded start the main function\ndocumentLoaded(() => {\n  fdc3OnReady(main, displayFDC3Support);\n});\n\nfunction main() {\n  try {\n    console.log('FDC3 is ready and DOM has rendered');\n    displayFDC3Support();\n    getPlatform();\n    populateHTML();\n    setUpEventListeners();\n    getContext();\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nfunction displayFDC3Support() {\n  try {\n    const supportedElement = document.getElementById('fdc3-support');\n    if (window.fdc3) {\n      supportedElement.innerHTML = 'Yes ✅';\n    } else {\n      supportedElement.innerHTML = 'No ❌';\n    }\n  } catch (error) {\n    console.error(\"Can't find FDC3 support\", error);\n  }\n}\n\nfunction getPlatform() {\n  const fdc3Info = window.fdc3.getInfo();\n  console.log('FDC3 info', fdc3Info);\n\n  //providerDetails.innerHTML = `${fdc3Info.provider} ${fdc3Info.providerVersion}`;\n  updateProviderDetails(`${fdc3Info.provider} ${fdc3Info.providerVersion}`);\n  updateFDC3Version(`${fdc3Info.fdc3Version}`);\n}\n\nfunction updateProviderDetails(details) {\n  const providerDetails = document.getElementById('providerDetails');\n  providerDetails.innerText = details;\n}\n\nfunction updateFDC3Version(details) {\n  const fdc3Details = document.getElementById('fdc3Details');\n  fdc3Details.innerText = details;\n}\n\nasync function populateHTML() {\n  try {\n    //populate available channels list with system channels\n    let channelList = document.getElementById('system-channel-list');\n\n    const populateChannelsList = id => {\n      let node = document.createElement('li');\n      let textNode = document.createTextNode(id);\n      node.appendChild(textNode);\n      channelList.appendChild(node);\n    };\n\n    const systemChannels = await fdc3.getSystemChannels();\n\n    // for all of the system channels populate dropdowns & lists\n    systemChannels.forEach(({ displayMetadata, id, type }) => {\n      //use the id field as this is what is needed to join the channel\n      populateChannelsList(id);\n      populateChannelsDropDown(id);\n    });\n\n    // as FDC3 is supported we can enable the buttons again except those that are not yet supported features\n    document.querySelectorAll('button').forEach(button => {\n      if (!button.className.includes('not-supported')) {\n        button.disabled = false;\n      }\n    });\n  } catch (error) {\n    console.error('unable to populate the html for the page ', error);\n  }\n}\n\nfunction setUpEventListeners() {\n  document.getElementById('add-app-channel__btn').addEventListener('click', addAppChannel);\n\n  document.getElementById('join-channel__btn').addEventListener('click', joinChannel);\n\n  document.getElementById('leave-channel__btn').addEventListener('click', () => {\n    fdc3.leaveCurrentChannel();\n  });\n\n  document.getElementById('broadcast__btn').addEventListener('click', broadcastFDC3Context);\n\n  document.getElementById('raise-intent__btn').addEventListener('click', raiseIntent);\n\n  document.getElementById('get_context__btn').addEventListener('click', event => {\n    let contextType = document.getElementById('context-type').value;\n    getContext(contextType);\n  });\n}\n\n/**\n *Populate the channel dropdown elements\n */\nfunction populateChannelsDropDown(newOptionText) {\n  try {\n    let dropdownElement = document.querySelector('.fdc3-channels');\n\n    if (newOptionText) {\n      dropdownElement.add(new Option(newOptionText));\n    } else {\n      throw new Error('No option provided');\n    }\n  } catch (error) {\n    console.error('could not add a new channel to the channel dropdown list', error);\n  }\n}\n\nfunction joinChannel() {\n  try {\n    let dropdownElement = document.getElementById('join-channel');\n    let channelName = dropdownElement.options[dropdownElement.selectedIndex].text;\n    fdc3.joinChannel(channelName);\n  } catch (error) {\n    console.error(\"Can't join channel\", error);\n  }\n}\n\nasync function broadcastFDC3Context() {\n  try {\n    let contextData = document.getElementById('txtBroadcastData').value;\n    fdc3.broadcast(JSON.parse(contextData));\n  } catch (error) {\n    console.error('could not broadcast', error);\n  }\n}\n\nasync function getContext(contextType) {\n  try {\n    if (contextListener) contextListener.unsubscribe();\n\n    // if context type is passed in then only listen on that specific context\n    if (contextType) {\n      contextListener = fdc3.addContextListener(contextType, context =>\n        displayContext(JSON.stringify(context, null, 2))\n      );\n    } else {\n      contextListener = fdc3.addContextListener(context => displayContext(JSON.stringify(context, null, 2)));\n    }\n  } catch (error) {\n    console.error('Unable to add a context listener', error);\n  }\n}\n\nfunction displayContext(text) {\n  let contextResultBox = document.getElementById('context-result');\n  contextResultBox.innerText = text;\n}\n\nasync function addAppChannel() {\n  try {\n    let appChannelName = document.getElementById('app-channel').value;\n\n    if (!appChannelName) throw new Error('no channel name set');\n\n    let appChannelExists = appChannels.find(appChannel => appChannel.id === appChannelName);\n\n    if (!appChannelExists) {\n      let newAppChannel = await fdc3.getOrCreateChannel(appChannelName);\n      appChannels.push(newAppChannel);\n\n      // add to the list of available app channels\n      let node = document.createElement('li');\n      let textNode = document.createTextNode(appChannelName);\n      node.appendChild(textNode);\n      document.getElementById('app-channel-list').appendChild(node);\n\n      //populate the channel list dropdown with new appChannel\n      populateChannelsDropDown(newAppChannel.id);\n    } else {\n      throw new Error('app channel already exists');\n    }\n  } catch (error) {\n    console.error('could not add an app channel', error);\n  }\n}\n\nasync function raiseIntent() {\n  try {\n    // get the channel\n    let intent = document.getElementById('intent').value;\n    let context = JSON.parse(document.getElementById('intent-context').value);\n\n    // TODO: add the target param\n    await fdc3.raiseIntent(intent, context);\n  } catch (err) {\n    console.error('intent did not resolve', err);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/1.2/styles.css",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap');\n\n.body {\n  font-family: 'Noto Sans JP', sans-serif;\n  margin: 0;\n  padding: 0;\n  background-color: #284b63;\n  color: white;\n}\n\n.main {\n  margin: 10px 0;\n  padding: 0;\n  display: flex;\n  flex-wrap: wrap;\n  place-content: center;\n  flex-direction: column;\n}\n#logo {\n  height: 200px;\n  margin-left: 20px;\n}\nbutton {\n  min-width: 45px;\n  height: 22px;\n  background: rgb(210 236 255);\n  border: 2px solid rgb(0 0 0 / 0%);\n  border-radius: 5px;\n  box-shadow: #03a9f433 2px 3px 0px 0px;\n  cursor: pointer;\n}\nbutton:active {\n  outline: transparent;\n  box-shadow:\n    inset #3c3c3c70 2px 3px 3px 0px,\n    #03a9f433 1px 2px 0px 0px;\n  transform: translateY(2px);\n  transition: ease-out 0.1s;\n}\nbutton:focus {\n  outline: transparent;\n}\ninput {\n  background: #e8f7ff;\n  box-shadow:\n    inset -2px -2px 2px 0px rgb(255 255 255 / 12%),\n    inset 2px 3px 6px 2px rgb(0 0 0 / 19%);\n  border-radius: 6px;\n  border: 2px solid transparent;\n}\ninput:focus {\n  transition-property: border;\n  transition-duration: 0.8s;\n  border: 2px solid #368cc7;\n  outline: 0;\n}\ntextarea {\n  background: #e8f7ff;\n  box-shadow:\n    inset -3px -5px 5px 1px rgb(255 255 255 / 12%),\n    inset 2px 3px 6px 2px rgb(0 0 0 / 19%);\n  border-radius: 6px;\n  border: 2px solid transparent;\n}\ntextarea:focus {\n  transition-property: border;\n  transition-duration: 0.8s;\n  border: 2px solid #368cc7;\n  outline: 0;\n}\ntable {\n  border: 0;\n  margin: 0 auto;\n  max-width: 1000px;\n  display: flex;\n}\ntr {\n  border: 0;\n}\ntd {\n  border: 0;\n}\ntextarea {\n  width: 400px;\n  height: 150px;\n}\n\nselect {\n  width: 238px;\n  height: 24px;\n  width: 238px;\n  height: 24px;\n  border-radius: 6px;\n  background: #e8f7ff;\n  border: 2px solid rgb(0 0 0 / 0%);\n  box-shadow: #03a9f433 2px 3px 0px 0px;\n}\n\n.ctxInput {\n  width: 241px;\n  height: 24px;\n}\n\n.urlInput {\n  width: 400px;\n  height: 24px;\n}\n\n.header {\n  width: 200px;\n  height: 40px;\n  font-weight: 700;\n}\n\n#context-result {\n  border: 1px solid white;\n  padding: 17px;\n  color: #9fffa2;\n  font-family: monospace;\n}\n"
  },
  {
    "path": "toolbox/fdc3-explained/README.md",
    "content": "# <a href='http://fdc3.finos.org/toolbox/fdc3-explained'><img src='logo.png' alt='FDC3 Explained Logo' /></a>\n\nFDC3 Explained was originally created by Johan Sandersson, an original maintainer of FDC3, and contributed to the project. It shows how easy it is to create very simple HTML and JavaScript that can use the FDC3 APIs to facilitate interoperability.\n\nIt is also a useful tool for detecing whether FDC3 is enabled, by running the website inside an FDC3-supporting desktop agent, and for performing basic FDC3 operations to help test interoperability workflows.\n\n## Website\n\nFDC3 Explained can be accessed at the following URL: https://fdc3.finos.org/toolbox/fdc3-explained.\n\nNote that it will only detect and allow use of FDC3 when running in the context of an FDC3 desktop agent.\n\n## Build\n\nThe NPM script `copy-explained` in the `website` folder copies the relevant files to the FDC3 website build for deployment.\n\nIt is automatically executed during deployments to https://fdc3.finos.org.\n\n## Note\n\nFDC3 Explained does not aim to be an exhaustive reference implementation for each version of the FDC3 Standard, it is merely a convenient testing utility.\n"
  },
  {
    "path": "toolbox/fdc3-explained/index.html",
    "content": "<html>\n  <!-- \n  \n  /**\n   * SPDX-License-Identifier: Apache-2.0\n   * Copyright FINOS FDC3 contributors - see NOTICE file\n   */\n  \n   -->\n  <head>\n    <title>\n      FDC3 Explained\n    </title>\n\n    <style>\n      body {\n        font-family: \"Noto Sans JP\", sans-serif;\n        margin: 0;\n        padding: 0;\n        background-color: #284b63;\n        color: white;\n      }\n\n      a  {\n        color: white;\n        text-decoration: none;\n      }\n\n      .main {\n        margin: 10px 0;\n        padding: 0;\n        display: flex;\n        flex-wrap: wrap;\n        place-content: center;\n        flex-direction: column;\n      }\n\n      .linkbox {\n        width: 25%;\n        padding: 5px;\n        text-align: center;\n        font-weight: 700;\n      }\n\n      .retired {\n        background-color: red;\n      }\n\n      .acceptable {\n        background-color: orange;\n      }\n\n      .optimal {\n        background-color: green;\n      }\n\n      #logo {\n        height: 200px;\n      }\n    </style>\n\n    <meta charset=\"UTF-8\" />\n  </head>\n\n  <body>\n    <div class=\"main\">\n      <table border=\"0\" style=\"width: 500px;\">\n        <tr>\n          <td colspan=\"4\"><img id=\"logo\" src=\"logo.svg\" /></td>\n        </tr>\n        <tr>\n          <td colspan=\"4\" style=\"padding: 30px 0px 30px 0px;\">\n            FDC3 Explained is a community project and reference implementation\n            of various FDC3 functionality. The key goal is to provide a tool for\n            application and container developers to verify their implementations\n            and act as basic but fully functional participant when testing and\n            demonstrating desktop interoperability.\n          </td>\n        </tr>\n        <tr>\n          <td class=\"linkbox acceptable\">\n            <a href=\"1.0/\"\">1.0</a>\n          </td>\n          <td class=\"linkbox acceptable\">\n            <a href=\"1.1/\"\">1.1</a>\n          </td>\n          <td class=\"linkbox optimal\">\n            <a href=\"1.2/\"\">1.2</a>\n          </td>\n        </tr>\n      </table>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/README.md",
    "content": "# FDC3 Demo Desktop Agent\n\nThis repository contains a [FDC3 2.0 Conformant](../../fdc3-conformance/README.md) Desktop Agent reference implementation, built on top of the [FDC3 Web Implementation](../fdc3-web-impl/README.md).\n\n## Running The Demo\n\nFrom the root of the repository, run:\n\n```bash\n\nnpm install\nnpm run dev\n\n```\n\nIf all goes well, you should see the following message in the console:\n\n```\nServer is listening on port 4000. Head to http://localhost:4000/static/da/index.html\n```\n\nAnd the web page will load in Chrome looking like this:\n\n![Demo Running In Chrome](./images/demo.png)\n\n## Features\n\nThe demo Desktop Agent provides the following features:\n\n### 1. Browser-Based Desktop Agent\n\n![Console](./images/console.png)\n\nAll FDC3 state is maintained in-browser with the exception of some very simple routing (expressed in `src/server/main.ts`) that links the various connections together.  Therefore, refreshing the Desktop Agent's window will reset the state of the Desktop Agent.\n\nThis means that you can view FDC3 communications within the Demo Desktop Agent's browser window, as shown in the above screenshot.\n\n### 2. Tabs or Frames\n\n![Tabs or Frames](./images/tab1.png)\n\n`demo` supports launching of FDC3 Apps as either tabs or frames.  You can choose the approach with the drop-down on the demo page.\n\n### 3.  Both Parent Post-Message and Iframe Communication Approaches\n\n![IFrame or Parent Post Message](./images/tab2.png)\n\nFDC3 WCP supports both communication from the App to the Desktop Agent via direct parent window postMessage and via postMessage to an iframe.  `demo` supports both approaches and you can choose the approach with the middle drop-down on the demo page.\n\n### 4. Intent Resolver / Channel Selector UI\n\n![Choosing The UI](./images/tab3.png)\n\nFDC3 WCP supports the ability for Desktop Agents to specify UI for resolving intents or selecting channels, and FDC3 also provides a default implementation which Desktop Agent implementers can use if they want.  `demo` allows the user to choose between `demo`'s own Channel Selector and Intent Resolver or the Default Web FDC3 ones (running either on localhost or on the fdc3.finos.org website).  This is done with the right-most drop-down on the launch page.  \n\n#### Channel Selectors\n\n|Mode           | Default Web FDC3 UI | Demo UI |\n|---------------|---------------------|---------|\n|Collapsed      |![Default Collapsed](./images/channel-selector/default-collapsed.png)|![Demo Collapsed](./images/channel-selector/demo-collapsed.png)| \n|Expanded       |![Default Expanded](./images/channel-selector/default-expanded.png)|![Demo Expanded](./images/channel-selector/demo-expanded.png)|\n\n**Note:** The Demo UI Channel Selector also supports **dragging** when in expanded mode.  You can reposition it on the screen by dragging on the six circles on the right of the title bar.\n\n#### Intent Resolvers\n\nHere are screenshots of the two different UIs provided for intent resolution:\n\n![Default](./images/intent-resolver/default.png)  ![Demo Implementation](./images/intent-resolver/demo-implementation.png)\n\n### 5. App Directory Loaded From URL\n\n![AppD Configuration](./images/appd.png)\n\nThe Demo Desktop Agent doesn't provide UI for selecting the app directory, however it is trivial to change this by modifying the `dummy-desktop-agent.ts` file.  You are able to specify as many different app directories to load as you want.  Note, `appd.json` and `local-conformance-2_0.v2.json` are provided in the `static/da` directory for you.\n\nThe `appd.json` file is a simple JSON file that specifies some demo apps (see below).  The `local-conformance-2_0.v2.json` file is for running 2.0 conformance tests.\n\n## Demo Applications\n\nAs shown in the screenshot above, there are 7 demo applications provided by Demo.   These attempt to exercise the functionality of FDC3 in a simple way.  They are:\n\n- **Broadcaster**: When you hit \"Press Me To Broadcast\", it joins User Channel 1 and then begins periodically broadcasting simple messages, until it gets to 50 messages and stops.  \n\n- **Receiver**: This also joins User Channel 1, and logs the contents of any messages it receives.  Tip: Try changing the user channel using the channel selector in either of these two apps to see what happens.\n\n- **Receiver and Broadcaster**: A single App combining the functionality of the two above.  It will broadcast messages and log them.\n\n- **FDC3 Workbench**:  The venerable [FDC3 Workbench](../../fdc3-workbench/README.md), which provides a simple UI for exercising all of the interoperability features of FDC3.  Tip: try running a few of these and testing sending messages via channels between the instances.\n\n- **View News Intent Listener**: One of two apps that listens for the `ViewNews` intent, logs the context it receives on screen and responds with an `fdc3.test` context.  Tip: This is useful for testing out intent resolution. Try going into the FDC3 Workbench and raising a `ViewNews` intent with an `fdc3.instrument` context and you'll see an intent resolver pop up.  \n\n- **View News and View Quote Intent Listener**: Similar to the above, but also responds to the `ViewQuote` intent.  tip: As this is the only app responding to `ViewQuote`, you will not see an intent resolver when you raise `ViewQuote` with an `fdc3.instrument`.\n\n- **Intent Result**: On launch, raises a `ViewQuote` intent with an `fdc3.instrument` context.  This is useful for testing out intent resolution without having to bother with the FDC3 Workbench.\n\n- **Intent Result 2**: On launch, raises a `ViewNews` intent with an `fdc3.instrument` context.    Tip: Try changing the intent resolver in the UI to the default one and see what happens.\n\n- **FDC3 Conformance 2.0**: This app is used to run the FDC3 2.0 conformance tests.  If you start with `npm run dev` from the root directory, the conformance tests will be started and running on their own port.   See [/toolbox/fdc3-conformance/README.md#running-the-conformance-tests](../../fdc3-conformance/README.md#running-the-conformance-tests#running-the-conformance-tests) for more details.  \n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/package.json",
    "content": "{\n  \"name\": \"@finos/demo\",\n  \"private\": true,\n  \"version\": \"2.2.2\",\n  \"license\": \"Apache-2.0\",\n  \"scripts\": {\n    \"dev\": \"tsx src/server/main.ts\",\n    \"lint\": \"eslint src/\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.19.0\",\n    \"@types/color\": \"^4.2.0\",\n    \"@types/express\": \"^4.17.21\",\n    \"@types/node\": \"^20.16.11\",\n    \"color\": \"^4.2.3\",\n    \"eslint\": \"^9.32.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"globals\": \"^15.14.0\",\n    \"nodemon\": \"^3.1.7\",\n    \"rimraf\": \"^6.0.1\",\n    \"typescript-eslint\": \"^8.17.0\",\n    \"vite\": \"^6.4.2\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3\": \"2.2.2\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"@types/ws\": \"^8.5.12\",\n    \"express\": \"^4.21.1\",\n    \"socket.io\": \"^4.8.0\",\n    \"socket.io-client\": \"^4.8.0\",\n    \"tsx\": \"^4.19.1\",\n    \"typescript\": \"^5.6.3\",\n    \"uuid\": \"^9.0.1\",\n    \"vite-express\": \"^0.15.0\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app1.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\nfunction createContext(i: number) {\n  return {\n    type: 'demo.counter',\n    count: i,\n  };\n}\n\n/**\n * Calling this function should get the fdc3 DesktopAgent and then\n * broadcast 50 context elements to the default channel.\n *\n * Can be called any number of times.\n */\nasync function startBroadcasting() {\n  console.log('starting...');\n  const fdc3 = await getAgent();\n  console.log('got api...');\n  const cc = await fdc3.getCurrentChannel();\n\n  if (cc == null) {\n    const channels = await fdc3.getUserChannels();\n    await fdc3.joinUserChannel(channels[0].id);\n  }\n  for (let index = 0; index < 50; index++) {\n    setTimeout(() => fdc3.broadcast(createContext(index)), index * 1000);\n  }\n}\n\nwindow.addEventListener('load', () => {\n  const broadcast = document.getElementById('broadcast');\n  broadcast?.addEventListener('click', () => startBroadcasting());\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app2.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\n/**\n * This demonstrates using the API via a promise\n */\ngetAgent().then(async fdc3 => {\n  console.log('in promise');\n  const log = document.getElementById('log');\n  const msg = document.createElement('p');\n  const info = await fdc3.getInfo();\n  msg.textContent = 'FDC3 Loaded: ' + JSON.stringify(info);\n  log?.appendChild(msg);\n\n  const cc = await fdc3.getCurrentChannel();\n  if (cc == null) {\n    const channels = await fdc3.getUserChannels();\n    await fdc3.joinUserChannel(channels[0].id);\n  }\n\n  fdc3.addContextListener(null, context => {\n    const msg = document.createElement('p');\n    msg.textContent = 'Received: ' + JSON.stringify(context);\n    log?.appendChild(msg);\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app3.ts",
    "content": "import './app1.js';\nimport './app2.js';\n\n/**\n * This demonstrates getting two separate APIs in the same app, and using them for\n * intra-app comms.\n */\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app4.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\n/**\n * This demonstrates using the API via a promise\n */\ngetAgent().then(async fdc3 => {\n  console.log('in promise');\n\n  fdc3.addIntentListener('ViewNews', async context => {\n    const msg = document.createElement('p');\n    msg.textContent = 'Received News!: ' + JSON.stringify(context);\n    const log = document.getElementById('log');\n    log?.appendChild(msg);\n\n    return {\n      type: 'fdc3.test',\n      id: {\n        from: 'app4',\n        intent: 'ViewNews',\n      },\n    };\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app5.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\n/**\n * This demonstrates using the API via a promise\n */\ngetAgent().then(async fdc3 => {\n  console.log('in promise');\n\n  fdc3.addIntentListener('ViewNews', async context => {\n    const msg = document.createElement('p');\n    msg.textContent = 'Received News!: ' + JSON.stringify(context);\n    const log = document.getElementById('log');\n    log?.appendChild(msg);\n    return {\n      type: 'fdc3.test',\n      id: {\n        from: 'app5',\n        intent: 'ViewNews',\n      },\n    };\n  });\n\n  fdc3.addIntentListener('ViewQuote', async context => {\n    const msg = document.createElement('p');\n    msg.textContent = 'Received Quote!: ' + JSON.stringify(context);\n    const log = document.getElementById('log');\n    log?.appendChild(msg);\n    return {\n      type: 'fdc3.test',\n      id: {\n        from: 'app5',\n        intent: 'ViewQuote',\n      },\n    };\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app6.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\n/**\n * This demonstrates using the API via a promise\n */\ngetAgent().then(async fdc3 => {\n  console.log('in promise');\n  const log = document.getElementById('log');\n  const reso = await fdc3.raiseIntent('ViewQuote', {\n    type: 'fdc3.instrument',\n    id: {\n      isin: 'Abc123',\n    },\n  });\n\n  log!.textContent = `Got resolution: ${JSON.stringify(reso)}`;\n  const result = await reso.getResult();\n  log!.textContent += `Got result: ${JSON.stringify(result)}`;\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/apps/app7.ts",
    "content": "import { getAgent } from '@finos/fdc3-get-agent';\n\n/**\n * This demonstrates using the API via a promise\n */\ngetAgent().then(async fdc3 => {\n  console.log('in promise');\n  const log = document.getElementById('log');\n  const reso = await fdc3.raiseIntent('ViewNews', {\n    type: 'fdc3.instrument',\n    id: {\n      isin: 'Abc123',\n    },\n  });\n\n  if (log) {\n    log.textContent = `Got resolution: ${JSON.stringify(reso)}`;\n    const result = await reso.getResult();\n    log.textContent += `Got result: ${JSON.stringify(result)}`;\n  } else {\n    console.error(\"Unable to load resolution as the log element didn't exist!\");\n  }\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/da/DemoServerContext.ts",
    "content": "import {\n  AppRegistration,\n  Directory,\n  DirectoryApp,\n  FDC3Server,\n  InstanceID,\n  ServerContext,\n  State,\n} from '@finos/fdc3-web-impl';\nimport { Socket } from 'socket.io-client';\nimport { v4 as uuid } from 'uuid';\nimport { FDC3_DA_EVENT } from '../../message-types.js';\nimport { AppIdentifier, AppIntent, OpenError } from '@finos/fdc3';\n\nenum Opener {\n  Tab,\n  Frame,\n}\n\ntype RunningAppRegistration = AppRegistration & {\n  window: Window;\n  url: string;\n  messagePort?: MessagePort;\n};\n\ntype LaunchingAppRegistration = AppRegistration & {\n  windowPromise: Promise<Window | null>;\n  url: string;\n};\n\ntype DemoAppRegistration = RunningAppRegistration | LaunchingAppRegistration;\n\n//Type guard used to check if application launch details have a URL\nfunction isWebAppLaunchDetails(details: object): details is { url: string } {\n  return (details as { url: string }).url !== undefined;\n}\n\n//Type guard used to check if application is still launching (we are waiting on the window reference)\nfunction isLaunchingAppRegistration(\n  details: RunningAppRegistration | LaunchingAppRegistration\n): details is LaunchingAppRegistration {\n  return !!(details as LaunchingAppRegistration).windowPromise;\n}\n\n//Type guard used to check if application has been launched (and we have received the window reference)\nfunction isRunningAppRegistration(\n  details: RunningAppRegistration | LaunchingAppRegistration\n): details is RunningAppRegistration {\n  return !!(details as RunningAppRegistration).window;\n}\n\nexport class DemoServerContext implements ServerContext<DemoAppRegistration> {\n  private readonly socket: Socket;\n  private readonly directory: Directory;\n  private connections: (RunningAppRegistration | LaunchingAppRegistration)[] = [];\n  private server: FDC3Server | null = null;\n\n  constructor(socket: Socket, directory: Directory) {\n    this.socket = socket;\n    this.directory = directory;\n  }\n\n  setFDC3Server(server: FDC3Server): void {\n    this.server = server;\n  }\n\n  async narrowIntents(_raiser: AppIdentifier, appIntents: AppIntent[] /*, _context: Context*/): Promise<AppIntent[]> {\n    return appIntents;\n  }\n\n  /**\n   * Sets the appId, url, state and either the window or a Promise<Window> for a given connection UUID.\n   */\n  setInstanceDetails(uuid: InstanceID, meta: RunningAppRegistration | LaunchingAppRegistration): void {\n    //remove any existing records with this uuid\n    this.connections = this.connections.filter(ca => ca.instanceId !== uuid);\n\n    const instanceDetails = {\n      ...meta,\n      instanceId: uuid,\n    };\n    this.connections.push(instanceDetails);\n\n    if (isLaunchingAppRegistration(meta)) {\n      //If the window wasn't fully realized yet, monitor the window promise so that it\n      //  sets window when resolved.\n      meta.windowPromise.then((window: Window | null) => {\n        if (window) {\n          const launchedMeta: RunningAppRegistration = {\n            window: window,\n            url: meta.url,\n            appId: meta.appId,\n            instanceId: meta.instanceId,\n            state: meta.state,\n          };\n          //will replace any existing record\n          this.setInstanceDetails(uuid, launchedMeta);\n        } else {\n          //delete this record as launch failed\n          this.connections = this.connections.filter(ca => ca.instanceId !== uuid);\n          console.error(\n            'We did not receive a window reference after launching app: ',\n            meta.url,\n            '\\nn.b. this may occur if a popup blocker prevented launch or the Cross-Origin-Opener-Policy opener policy is set'\n          );\n        }\n      });\n    }\n  }\n\n  async getInstanceForWindow(window: Window): Promise<RunningAppRegistration | undefined> {\n    const registration = this.connections.filter(isRunningAppRegistration).find(i => i.window == window);\n    if (registration) {\n      return registration;\n    }\n\n    //check for as yet unrealized windows and then wait on those...\n    const launchingApps = this.connections.filter(isLaunchingAppRegistration);\n\n    if (launchingApps.length == 0) {\n      console.warn('Could not locate an app registration for a window and there are no window launches in progress!');\n      return;\n    } else {\n      //we need to wait on all currently launching windows as it could be any one of those\n      return new Promise<RunningAppRegistration | undefined>(resolve => {\n        const toMonitor = launchingApps.length;\n        let doneCount = 0;\n        launchingApps.forEach(launchingApp => {\n          launchingApp.windowPromise.then(realizedWindow => {\n            doneCount++;\n            if (realizedWindow == window) {\n              //note that this record will separately be converting itself into a RunningAppRegistration\n              resolve({\n                window: realizedWindow,\n                url: launchingApp.url,\n                appId: launchingApp.appId,\n                instanceId: launchingApp.instanceId,\n                state: launchingApp.state,\n              });\n            } else if (doneCount >= toMonitor) {\n              //we did not find it :-(\n              resolve(undefined);\n            }\n          });\n        });\n      });\n    }\n  }\n\n  getInstanceDetails(uuid: InstanceID): DemoAppRegistration | undefined {\n    return this.connections.find(i => i.instanceId == uuid);\n  }\n\n  getOpener(): Opener {\n    const cb = document.getElementById('opener') as HTMLInputElement;\n    const val = cb.value;\n    const out: Opener = Opener[val as keyof typeof Opener]; //Works with --noImplicitAny\n    return out;\n  }\n\n  createUUID(): string {\n    return uuid();\n  }\n\n  /**\n   * Post an outgoing message to a particular app\n   */\n  async post(message: object, to: InstanceID): Promise<void> {\n    //figure out if we're using a MessagePort or the socket to communicate with the app\n    const registration = this.getInstanceDetails(to);\n    if (registration && isRunningAppRegistration(registration)) {\n      if (registration.messagePort) {\n        registration.messagePort.postMessage(message);\n      } else {\n        this.socket.emit(FDC3_DA_EVENT, message, to);\n      }\n    } else if (!registration) {\n      console.error(\"Can't message unknown app instance: \", to);\n    } else {\n      console.error(\"Can't message app that is not yet connected: \", to);\n    }\n  }\n\n  openFrame(url: string): Promise<Window | null> {\n    const iframe = document.createElement('iframe');\n    iframe.setAttribute('src', url);\n    iframe.style.width = '640px';\n    iframe.style.height = '480px';\n    document.body.appendChild(iframe);\n\n    //wait for load event, after which contentWindow should not be null\n    const loadPromise = new Promise<Window | null>(resolve => {\n      iframe.onload = () => resolve(iframe.contentWindow);\n    });\n    return loadPromise;\n  }\n\n  openTab(url: string): Promise<Window | null> {\n    //n.b. There are cases where the window reference returned is null\n    // That can happen if the Cross-Origin-Opener-Policy opener policy is set (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy)\n    // or a browser pop-up blocker gets in the way...\n    return Promise.resolve(window.open(url, '_blank'));\n  }\n\n  async openUrl(url: string): Promise<Window | null> {\n    const opener = this.getOpener();\n    switch (opener) {\n      case Opener.Tab:\n        return this.openTab(url);\n      case Opener.Frame:\n        return this.openFrame(url);\n    }\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  async open(appId: string, _source?: AppIdentifier): Promise<InstanceID> {\n    const details: DirectoryApp[] = this.directory.retrieveAppsById(appId) as DirectoryApp[];\n    if (details.length > 0) {\n      const launchDetails = details[0].details;\n      if (isWebAppLaunchDetails(launchDetails)) {\n        const url = launchDetails.url ?? undefined;\n\n        //We do not await the window or frame opening here as that can cause a race condition\n        //  where the app loads and attempts to connect before we call `this.setInstanceDetails`.\n        //const window = await this.openUrl(url);\n        const windowPromise = this.openUrl(url);\n        const instanceId: InstanceID = this.createUUID();\n        const metadata: LaunchingAppRegistration = {\n          appId,\n          instanceId,\n          windowPromise,\n          url,\n          state: State.Pending,\n        };\n\n        this.setInstanceDetails(instanceId, metadata);\n        return instanceId;\n      } else {\n        console.error('Unable to launch app without a URL, app: ', details[0]);\n        throw new Error(OpenError.ErrorOnLaunch);\n      }\n    }\n\n    throw new Error(OpenError.AppNotFound);\n  }\n\n  async getConnectedApps(): Promise<AppRegistration[]> {\n    return (await this.getAllApps()).filter(ca => ca.state == State.Connected);\n  }\n\n  async isAppConnected(app: InstanceID): Promise<boolean> {\n    const found = this.connections.find(a => a.instanceId == app && a.state == State.Connected);\n    return found != null;\n  }\n\n  async setAppState(app: InstanceID, newState: State): Promise<void> {\n    const found = this.connections.find(a => a.instanceId == app);\n\n    //if this is a new termination (which might be due to a heartbeat) then notify the server\n    //  if we were already terminated, don't bother as the server will notify us back and\n    //  create a loop\n    if (found) {\n      const currentState = found.state;\n      if (currentState !== State.Terminated && newState === State.Terminated) {\n        this.server?.cleanup(app);\n      }\n      found.state = newState;\n    }\n  }\n\n  async getAllApps(): Promise<AppRegistration[]> {\n    return this.connections.map(x => {\n      return {\n        appId: x.appId,\n        instanceId: x.instanceId,\n        state: x.state,\n      };\n    });\n  }\n\n  log(message: string): void {\n    console.log(message);\n  }\n\n  provider(): string {\n    return 'FDC3-Web-Demo';\n  }\n\n  providerVersion(): string {\n    return '2.2.2';\n  }\n\n  fdc3Version(): string {\n    return '2.2';\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/da/FDC3_2_1_JSONDirectory.ts",
    "content": "import { BasicDirectory, DirectoryApp } from '@finos/fdc3-web-impl';\n\nasync function loadRemotely(u: string) {\n  const response = await fetch(u);\n  return await response.json();\n}\n\nasync function load(url: string): Promise<DirectoryApp[]> {\n  if (url.startsWith('http')) {\n    return await loadRemotely(url).then(convertToDirectoryList);\n  } else {\n    return await loadRemotely(window.location.origin + url).then(convertToDirectoryList);\n  }\n}\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst convertToDirectoryList = (data: any): DirectoryApp[] => {\n  return data.applications as DirectoryApp[];\n};\n\nexport class FDC3_2_1_JSONDirectory extends BasicDirectory {\n  constructor() {\n    super([]);\n  }\n\n  async load(url: string) {\n    const aa = this.allApps;\n    const apps = await load(url);\n\n    apps.forEach((app: DirectoryApp) => {\n      const existing = aa.find(a => a.appId == app.appId);\n      if (!existing) {\n        aa.push(app);\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/da/dummy-desktop-agent.ts",
    "content": "import { io } from 'socket.io-client';\nimport { v4 as uuid } from 'uuid';\nimport { APP_GOODBYE, DA_HELLO, FDC3_APP_EVENT } from '../../message-types.js';\nimport { DemoServerContext } from './DemoServerContext.js';\nimport { FDC3_2_1_JSONDirectory } from './FDC3_2_1_JSONDirectory.js';\nimport {\n  AppRegistration,\n  ChannelState,\n  ChannelType,\n  DefaultFDC3Server,\n  DirectoryApp,\n  ServerContext,\n} from '@finos/fdc3-web-impl';\nimport { UI, UI_URLS } from './util.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { WebConnectionProtocol3Handshake } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype WebConnectionProtocol2LoadURL = BrowserTypes.WebConnectionProtocol2LoadURL;\n\nfunction createAppStartButton(app: DirectoryApp, sc: ServerContext<AppRegistration>): HTMLDivElement {\n  const div: HTMLDivElement = document.createElement('div');\n  div.classList.add('app');\n  const h3 = document.createElement('h3');\n  h3.textContent = app.title;\n  div.appendChild(h3);\n  const button = document.createElement('button');\n  button.textContent = 'Start';\n  button.onclick = () => sc.open(app.appId);\n  div.appendChild(button);\n  const p = document.createElement('p');\n  p.textContent = app.description ?? '';\n  div.appendChild(p);\n  return div;\n}\n\nenum Approach {\n  IFRAME,\n  PARENT_POST_MESSAGE,\n}\n\nfunction getApproach(): Approach {\n  const cb = document.getElementById('approach') as HTMLInputElement;\n  const val = cb.value;\n  const out: Approach = Approach[val as keyof typeof Approach]; //Works with --noImplicitAny\n  return out;\n}\n\nfunction getUIKey(): UI {\n  const cb = document.getElementById('ui') as HTMLInputElement;\n  const val = cb.value;\n  const out: UI = UI[val as keyof typeof UI]; //Works with --noImplicitAny\n  return out;\n}\n\nwindow.addEventListener('load', () => {\n  const desktopAgentUUID = uuid();\n\n  const socket = io();\n\n  socket.on('connect', async () => {\n    socket.emit(DA_HELLO, desktopAgentUUID);\n\n    const directory = new FDC3_2_1_JSONDirectory();\n    await directory.load('/static/da/appd.json');\n    await directory.load('/static/da/local-conformance.v2.json');\n    const sc = new DemoServerContext(socket, directory);\n\n    const channelDetails: ChannelState[] = [\n      {\n        id: 'fdc3.channel.1',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 1',\n          color: 'red',\n          glyph: '1',\n        },\n      },\n      {\n        id: 'fdc3.channel.2',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 2',\n          color: 'orange',\n          glyph: '2',\n        },\n      },\n      {\n        id: 'fdc3.channel.3',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 3',\n          color: 'yellow',\n          glyph: '3',\n        },\n      },\n      {\n        id: 'fdc3.channel.4',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 4',\n          color: 'green',\n          glyph: '4',\n        },\n      },\n      {\n        id: 'fdc3.channel.5',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 5',\n          color: 'cyan',\n          glyph: '5',\n        },\n      },\n      {\n        id: 'fdc3.channel.6',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 6',\n          color: 'blue',\n          glyph: '6',\n        },\n      },\n      {\n        id: 'fdc3.channel.7',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 7',\n          color: 'magenta',\n          glyph: '7',\n        },\n      },\n      {\n        id: 'fdc3.channel.8',\n        type: ChannelType.user,\n        context: [],\n        displayMetadata: {\n          name: 'Channel 8',\n          color: 'purple',\n          glyph: '8',\n        },\n      },\n    ];\n    const fdc3Server = new DefaultFDC3Server(sc, directory, channelDetails, true, 20000, 15000);\n\n    socket.on(FDC3_APP_EVENT, (msg, from) => {\n      fdc3Server.receive(msg, from);\n    });\n\n    socket.on(APP_GOODBYE, (id: string) => {\n      fdc3Server.cleanup(id);\n    });\n\n    // let's create buttons for some apps\n    const appList = document.getElementById('app-list') as HTMLOListElement;\n    directory.retrieveAllApps().forEach((app: DirectoryApp) => {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      const mani = app?.hostManifests?.demo as any;\n      const show = mani?.visible ?? true;\n      if (show) {\n        appList.appendChild(createAppStartButton(app, sc));\n      }\n    });\n\n    // set up Desktop Agent Proxy interface here\n    // disabling rule for checks on origin of messages - this could be improved by validating for origins we know we are working with\n    // nosemgrep: javascript.browser.security.insufficient-postmessage-origin-validation.insufficient-postmessage-origin-validation\n    window.addEventListener('message', async e => {\n      const event = e as MessageEvent;\n      const data = event.data;\n      const source = event.source as Window;\n      const origin = event.origin;\n\n      console.log('Received window.postMessage: ' + JSON.stringify(event.data));\n      if (data.type == 'WCP1Hello') {\n        const instance = await sc.getInstanceForWindow(source);\n        if (instance) {\n          console.log('Identified instance for source window: ' + JSON.stringify(instance.instanceId));\n\n          if (getApproach() == Approach.IFRAME) {\n            // Let getAgent/the app know to load an adaptor into an iframe via WCP2LoadUrl\n            const message: WebConnectionProtocol2LoadURL = {\n              type: 'WCP2LoadUrl',\n              meta: {\n                connectionAttemptUuid: data.meta.connectionAttemptUuid,\n                timestamp: new Date(),\n              },\n              payload: {\n                iframeUrl:\n                  window.location.origin +\n                  `/static/da/embed.html?&desktopAgentId=${desktopAgentUUID}&instanceId=${instance.instanceId}&UI=${getUIKey()}`,\n              },\n            };\n\n            console.log('Responding with message: ', JSON.stringify(message));\n\n            // no message port is included as communication will be setup with the iframe\n            source.postMessage(message, origin);\n          } else {\n            //setup a MessageChannel and handling for incoming messages on it\n            const channel = new MessageChannel();\n            channel.port2.onmessage = message => {\n              console.log(\n                `message received on message port for app ${instance.instanceId}, message: ${JSON.stringify(message.data)}`\n              );\n              const msg = message.data as\n                | BrowserTypes.AppRequestMessage\n                | BrowserTypes.WebConnectionProtocol4ValidateAppIdentity\n                | BrowserTypes.WebConnectionProtocol6Goodbye;\n\n              if (msg.type == 'WCP6Goodbye') {\n                // handle disconnect messages\n                fdc3Server.cleanup(instance.instanceId);\n              } else {\n                // handle DACP messages and WCP4ValidateAppIdentity\n                fdc3Server.receive(msg, instance.instanceId);\n              }\n            };\n\n            //update the server Context with the MessagePort\n            await sc.setInstanceDetails(instance.instanceId, { ...instance, messagePort: channel.port2 });\n\n            //get details of channel selector and intent resolver\n            const ui = UI_URLS[getUIKey()];\n\n            //prepare the handshake message\n            const message: WebConnectionProtocol3Handshake = {\n              type: 'WCP3Handshake',\n              meta: {\n                connectionAttemptUuid: data.meta.connectionAttemptUuid,\n                timestamp: new Date(),\n              },\n              payload: {\n                fdc3Version: '2.2',\n                ...ui,\n              },\n            };\n            console.log('Responding with message: ', JSON.stringify(message));\n\n            //send the handshake message and include the message port for further comms\n            source.postMessage(message, origin, [channel.port1]);\n          }\n        } else {\n          // Log unknown windows but don't let them connect\n          let sourceName;\n          try {\n            sourceName = source.name;\n          } catch (e: unknown) {\n            sourceName = `{a cross-origin window: ${(e as Error).message ?? e}}`;\n          }\n          console.error(`Couldn't locate an instance for window: ${sourceName}`);\n        }\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/da/embed.ts",
    "content": "import { io } from 'socket.io-client';\nimport { link, UI, UI_URLS } from './util.js';\nimport { APP_HELLO } from '../../message-types.js';\nimport { isWebConnectionProtocol1Hello } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nconst appWindow = window.parent;\n\nfunction getQueryVariable(variable: string): string {\n  const query = window.location.search.substring(1);\n  const vars = query.split('&');\n  for (let i = 0; i < vars.length; i++) {\n    const pair = vars[i].split('=');\n    if (pair[0] == variable) {\n      return pair[1];\n    }\n  }\n\n  return '';\n}\n\nfunction getSource(): string {\n  return getQueryVariable('instanceId');\n}\n\nfunction getDesktopAgentId(): string {\n  return getQueryVariable('desktopAgentId');\n}\n\nfunction getUIKey(): UI {\n  const ui = getQueryVariable('UI');\n  return parseInt(ui) as UI;\n}\n\nconst helloListener = (e: MessageEvent) => {\n  const messageData = e.data;\n  const eventSource = e.source;\n  let eventSourceName;\n  try {\n    eventSourceName = (eventSource as Window)?.name;\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  } catch (e: unknown) {\n    eventSourceName = `{a cross-origin window} `;\n  }\n  if (!eventSourceName) {\n    eventSourceName = '{no window name set} ';\n  }\n\n  if (isWebConnectionProtocol1Hello(messageData)) {\n    console.debug(\n      'Communication iframe adaptor received hello message from: ',\n      eventSourceName,\n      eventSource == appWindow ? '(parent window): ' : '(NOT parent win): ',\n      messageData\n    );\n\n    window.removeEventListener('message', helloListener);\n\n    const socket = io();\n    const channel = new MessageChannel();\n    const source = getSource();\n    const desktopAgentUUID = getDesktopAgentId();\n\n    socket.on('connect', () => {\n      link(socket, channel, source);\n\n      socket.emit(APP_HELLO, desktopAgentUUID, source);\n\n      const ui = UI_URLS[getUIKey()];\n\n      // send the other end of the channel to the app\n      // nosemgrep\n      appWindow.postMessage(\n        {\n          type: 'WCP3Handshake',\n          meta: {\n            connectionAttemptUuid: messageData.meta.connectionAttemptUuid,\n            timestamp: new Date(),\n          },\n          payload: {\n            fdc3Version: '2.2',\n            ...ui,\n          },\n        },\n        '*',\n        [channel.port1]\n      );\n    });\n  }\n};\n\nwindow.addEventListener('message', helloListener);\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/da/util.ts",
    "content": "import { InstanceID } from '@finos/fdc3-web-impl';\nimport { Socket } from 'socket.io-client';\nimport { FDC3_APP_EVENT, FDC3_DA_EVENT } from '../../message-types.js';\n\nexport enum UI {\n  DEFAULT,\n  DEMO,\n  LOCAL,\n}\n\nexport const UI_URLS = {\n  [UI.DEMO]: {\n    intentResolverUrl: window.location.origin + '/static/da/intent-resolver.html',\n    channelSelectorUrl: window.location.origin + '/static/da/channel-selector.html',\n  },\n  [UI.DEFAULT]: {\n    intentResolverUrl: 'https://fdc3.finos.org/toolbox/fdc3-reference-ui/intent_resolver.html',\n    channelSelectorUrl: 'https://fdc3.finos.org/toolbox/fdc3-reference-ui/channel_selector.html',\n  },\n  [UI.LOCAL]: {\n    intentResolverUrl: 'http://localhost:4002/intent_resolver.html',\n    channelSelectorUrl: 'http://localhost:4002/channel_selector.html',\n  },\n};\n\nexport function link(socket: Socket, channel: MessageChannel, source: InstanceID) {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  socket.on(FDC3_DA_EVENT, (data: any) => {\n    channel.port2.postMessage(data);\n  });\n\n  channel.port2.onmessage = function (event) {\n    socket.emit(FDC3_APP_EVENT, event.data, source);\n  };\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/ui/channel-selector.ts",
    "content": "import { selectHighestContrast } from './contrast.js';\nimport { dragElement } from './drag.js';\nimport {\n  Channel,\n  Fdc3UserInterfaceChannelSelected,\n  Fdc3UserInterfaceHello,\n  Fdc3UserInterfaceRestyle,\n  isFdc3UserInterfaceChannels,\n  isFdc3UserInterfaceHandshake,\n  UpdatedCSS,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nlet channels: Channel[] = [];\nlet channelId: string | null = null;\n\nexport const DEFAULT_COLLAPSED_CSS: UpdatedCSS = {\n  width: '50px',\n  height: '50px',\n  position: 'fixed',\n  zIndex: '1000',\n};\n\nconst DEFAULT_EXPANDED_CSS: UpdatedCSS = {\n  left: '0',\n  right: '0',\n  top: '0',\n  bottom: '0',\n  position: 'fixed',\n  zIndex: '1000',\n};\n\nexport type Position = {\n  left: string;\n  top: string;\n  bottom: string;\n  right: string;\n};\n\nconst position: Position = {\n  right: '10px',\n  bottom: '10px',\n  left: '',\n  top: '',\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst debug = (...params: any[]) => {\n  console.debug('Demo Channel Selector: ', ...params);\n};\n\nwindow.addEventListener('load', () => {\n  const parent = window.parent;\n  const logo = document.getElementById('logo')!;\n  const close = document.getElementById('close')!;\n  const drag = document.getElementById('drag')!;\n  const selector = document.getElementById('selector')!;\n  const list = document.getElementById('channel-list')!;\n\n  const mc = new MessageChannel();\n  const myPort = mc.port1;\n  myPort.start();\n\n  // ISSUE: 1302\n  const helloMessage: Fdc3UserInterfaceHello = {\n    type: 'Fdc3UserInterfaceHello',\n    payload: {\n      initialCSS: {\n        ...DEFAULT_COLLAPSED_CSS,\n        ...position,\n      },\n      implementationDetails: 'Demo Channel Selector v1.0',\n    },\n  };\n  // nosemgrep\n  parent.postMessage(helloMessage, '*', [mc.port2]);\n  debug('Sent hello message: ', helloMessage);\n\n  function changeSize(expanded: boolean) {\n    document.body.setAttribute('data-expanded', 'none');\n    if (expanded) {\n      const message: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: { updatedCSS: DEFAULT_EXPANDED_CSS },\n      };\n      myPort.postMessage(message);\n      debug('Setting expanded styles: ', message);\n      console.debug();\n      selector.style.left = position.left;\n      selector.style.top = position.top;\n      selector.style.right = position.right;\n      selector.style.bottom = position.bottom;\n      setTimeout(() => {\n        document.body.setAttribute('data-expanded', 'selector');\n      }, 20);\n    } else {\n      const message: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: { updatedCSS: { ...DEFAULT_COLLAPSED_CSS, ...position } },\n      };\n      debug('Setting collapsed styles: ', message);\n      myPort.postMessage(message);\n      setTimeout(() => {\n        document.body.setAttribute('data-expanded', 'logo');\n      }, 20);\n    }\n  }\n\n  myPort.addEventListener('message', e => {\n    if (isFdc3UserInterfaceHandshake(e.data)) {\n      // ok, port is ready, send the iframe position details\n      const message: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: { updatedCSS: { ...DEFAULT_COLLAPSED_CSS, ...position } },\n      };\n      myPort.postMessage(message);\n      debug('Received handshake, sending initial restyle: ', message);\n    } else if (isFdc3UserInterfaceChannels(e.data)) {\n      debug('Received channel details: ', e.data);\n      channels = e.data.payload.userChannels;\n      channelId = e.data.payload.selected;\n\n      const selectedColor =\n        (channelId ? channels.find(c => c.id == channelId)?.displayMetadata?.color : null) ?? 'white';\n      logo.style.backgroundColor = selectedColor;\n    }\n  });\n\n  close.addEventListener('click', () => {\n    changeSize(false);\n  });\n\n  logo.addEventListener('click', () => {\n    list.innerHTML = '';\n\n    //populate with channels\n    channels.forEach(channel => {\n      const li = document.createElement('div');\n      const bgColor = channel.displayMetadata?.color ?? 'white';\n      li.style.backgroundColor = bgColor;\n      li.style.color = selectHighestContrast(bgColor, 'white', 'black');\n      const description = document.createElement('em');\n      description.textContent = channel.id == channelId ? '  SELECTED ' : '';\n      li.textContent = channel.displayMetadata?.name ?? channel.id;\n\n      li.appendChild(description);\n      list.appendChild(li);\n      li.onclick = () => {\n        changeSize(false);\n        channelId = channel.id;\n        const message: Fdc3UserInterfaceChannelSelected = {\n          type: 'Fdc3UserInterfaceChannelSelected',\n          payload: {\n            selected: channel.id,\n          },\n        };\n        myPort.postMessage(message);\n      };\n    });\n\n    //add an element for deselecting the channel\n    const li = document.createElement('div');\n    li.style.backgroundColor = 'white';\n    li.style.color = 'black';\n    const description = document.createElement('em');\n    description.textContent = channelId == null ? '  SELECTED ' : '';\n    li.textContent = 'NONE';\n\n    li.appendChild(description);\n    list.appendChild(li);\n    li.onclick = () => {\n      changeSize(false);\n      channelId = null;\n      const message: Fdc3UserInterfaceChannelSelected = {\n        type: 'Fdc3UserInterfaceChannelSelected',\n        payload: {\n          selected: null,\n        },\n      };\n      myPort.postMessage(message);\n    };\n\n    changeSize(true);\n  });\n\n  dragElement(drag, selector, position);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/ui/contrast.ts",
    "content": "import Color from 'color';\n\nexport function selectHighestContrast(bgColorCSS: string, ...candidates: string[]) {\n  const bgColor = Color(bgColorCSS);\n  const contrasts: number[] = candidates.map(candidate => {\n    return bgColor.contrast(Color(candidate));\n  });\n  let bestCandidate = candidates[0],\n    highestContrast = contrasts[0];\n  for (let i = 1; i < contrasts.length; i++) {\n    if (contrasts[i] > highestContrast) {\n      bestCandidate = candidates[i];\n      highestContrast = contrasts[i];\n    }\n  }\n  return bestCandidate;\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/ui/drag.ts",
    "content": "import { Position } from './channel-selector.js';\n\nexport function dragElement(drag: HTMLElement, selector: HTMLElement, position: Position) {\n  let posXDrag = 0,\n    posYDrag = 0,\n    posXStart = 0,\n    posYStart = 0;\n  let top = 0,\n    left = 0,\n    screenX = 0,\n    screenY = 0;\n\n  drag.onmousedown = dragMouseDown;\n\n  globalThis.window.onresize = () => {\n    screenX = window.innerWidth;\n    screenY = window.innerHeight;\n  };\n\n  function updatePosition() {\n    position.left = left < screenX / 2 ? `${Math.max(left, 0)}px` : '';\n    position.top = top < screenY / 2 ? `${Math.max(top, 0)}px` : '';\n    position.right = left > screenX / 2 ? `${Math.max(screenX - left - selector.offsetWidth, 0)}px` : '';\n    position.bottom = top > screenY / 2 ? `${Math.max(screenY - top - selector.offsetHeight, 0)}px` : '';\n  }\n\n  function dragMouseDown(e: MouseEvent) {\n    console.debug('Channel Selector - DragMouseDown starting');\n    e.preventDefault();\n    // get the mouse cursor position at startup:\n    posXStart = e.clientX;\n    posYStart = e.clientY;\n    document.onmousemove = elementDrag;\n    document.onmouseup = closeDragElement;\n  }\n\n  function elementDrag(e: MouseEvent) {\n    e.preventDefault();\n    // calculate the new cursor position:\n    posXDrag = posXStart - e.clientX;\n    posYDrag = posYStart - e.clientY;\n    posXStart = e.clientX;\n    posYStart = e.clientY;\n    // set the element's new position:\n    top = Math.max(selector.offsetTop - posYDrag, 0);\n    left = Math.max(selector.offsetLeft - posXDrag, 0);\n    selector.style.top = top + 'px';\n    selector.style.left = left + 'px';\n    updatePosition();\n  }\n\n  function closeDragElement() {\n    document.onmouseup = null;\n    document.onmousemove = null;\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/ui/intent-resolver.ts",
    "content": "import {\n  Fdc3UserInterfaceHello,\n  Fdc3UserInterfaceResolve,\n  Fdc3UserInterfaceResolveAction,\n  Fdc3UserInterfaceRestyle,\n  isFdc3UserInterfaceHandshake,\n  isFdc3UserInterfaceResolve,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AppIdentifier } from '@finos/fdc3-standard';\n\nconst DEFAULT_COLLAPSED_CSS = {\n  position: 'fixed',\n  display: 'none',\n  zIndex: '1000',\n  right: '0',\n  bottom: '0',\n  width: '0',\n  height: '0',\n};\n\nconst DEFAULT_EXPANDED_CSS = {\n  position: 'fixed',\n  display: 'block',\n  zIndex: '1000',\n  left: '10%',\n  top: '10%',\n  right: '10%',\n  bottom: '10%',\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst debug = (...params: any[]) => {\n  console.debug('Demo Intent Resolver: ', ...params);\n};\n\nwindow.addEventListener('load', () => {\n  const parent = window.parent;\n\n  const mc = new MessageChannel();\n  const myPort = mc.port1;\n  myPort.start();\n\n  const list = document.getElementById('intent-list')!;\n\n  // ISSUE: 1302\n  const helloMessage: Fdc3UserInterfaceHello = {\n    type: 'Fdc3UserInterfaceHello',\n    payload: {\n      initialCSS: DEFAULT_COLLAPSED_CSS,\n      implementationDetails: 'Demo Intent Resolver v1.0',\n    },\n  };\n  // nosemgrep\n  parent.postMessage(helloMessage, '*', [mc.port2]);\n  debug('Sent hello message: ', helloMessage);\n\n  function callback(intent: string | null, app: AppIdentifier | null) {\n    const restyleMessage: Fdc3UserInterfaceRestyle = {\n      type: 'Fdc3UserInterfaceRestyle',\n      payload: { updatedCSS: DEFAULT_COLLAPSED_CSS },\n    };\n    myPort.postMessage(restyleMessage);\n    debug('Setting collapsed styles: ', restyleMessage);\n\n    if (intent && app) {\n      const message: Fdc3UserInterfaceResolveAction = {\n        type: 'Fdc3UserInterfaceResolveAction',\n        payload: {\n          action: 'click',\n          appIdentifier: app,\n          intent: intent,\n        },\n      };\n      myPort.postMessage(message);\n      debug('Sent resolution: ', message);\n    } else {\n      const message: Fdc3UserInterfaceResolveAction = {\n        type: 'Fdc3UserInterfaceResolveAction',\n        payload: {\n          action: 'cancel',\n        },\n      };\n      myPort.postMessage(message);\n      debug('Sent cancellation: ', message);\n    }\n  }\n\n  myPort.addEventListener('message', e => {\n    if (isFdc3UserInterfaceHandshake(e.data)) {\n      const message: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: { updatedCSS: DEFAULT_COLLAPSED_CSS },\n      };\n      myPort.postMessage(message);\n      debug('Received handshake, sending initial restyle: ', message);\n    } else if (isFdc3UserInterfaceResolve(e.data)) {\n      const message: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: { updatedCSS: DEFAULT_EXPANDED_CSS },\n      };\n      myPort.postMessage(message);\n      debug('Received request for resolution, setting expanded styles: ', message);\n      Array.from(list.children).forEach(i => i.remove());\n      const details: Fdc3UserInterfaceResolve['payload'] = e.data.payload;\n      details.appIntents.forEach(intent => {\n        intent.apps.forEach(app => {\n          const li = document.createElement('li');\n          const a = document.createElement('a');\n          const description = document.createElement('em');\n\n          if (app.instanceId) {\n            description.textContent = `${intent.intent.displayName ?? ''} on app instance ${app.instanceId} of ${app.appId}`;\n          } else {\n            description.textContent = ` ${intent.intent.displayName ?? ''} on a new instance of ${app.appId}`;\n          }\n\n          a.textContent = intent.intent.name;\n\n          li.appendChild(a);\n          li.appendChild(description);\n          list.appendChild(li);\n          a.setAttribute('href', '#');\n          a.onclick = () => callback(intent.intent.name, app);\n        });\n      });\n    }\n  });\n\n  document.getElementById('cancel')!.addEventListener('click', () => {\n    callback(null, null);\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/client/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/message-types.ts",
    "content": "export const DA_HELLO = 'da-hello';\nexport const APP_HELLO = 'app-hello';\nexport const APP_GOODBYE = 'app-goodbye';\nexport const FDC3_APP_EVENT = 'fdc3-app-event';\nexport const FDC3_DA_EVENT = 'fdc3-da-event';\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/src/server/main.ts",
    "content": "import express from 'express';\nimport ViteExpress from 'vite-express';\nimport { Server, Socket } from 'socket.io';\nimport { APP_GOODBYE, APP_HELLO, DA_HELLO, FDC3_APP_EVENT, FDC3_DA_EVENT } from '../message-types.js';\n\nconst app = express();\n\napp.get('/iframe', (_, res) => {\n  res.send('Hello Vite + TypeScript!');\n});\n\nconst httpServer = ViteExpress.listen(app, 4000, () =>\n  console.log(`\n  ___  ___  ___  ____ ___                  \n | __>| . \\\\|  _><__ /| . \\\\ ___ ._ _ _  ___ \n | _> | | || <__ <_ \\\\| | |/ ._>| ' ' |/ . \\\\\n |_|  |___/\\`___/<___/|___/\\\\___.|_|_|_|\\\\___/\n                                          \nServer is listening on port 4000. Head to http://localhost:4000/static/da/index.html`)\n);\n\nconst io = new Server(httpServer);\n\ntype ConnectedWorld = {\n  server: Socket;\n  apps: Map<string, Socket>;\n};\n\nenum ConnectionType {\n  APP,\n  DA,\n}\n\nconst instances: Map<string, ConnectedWorld> = new Map();\n\nio.on('connection', (socket: Socket) => {\n  let myInstance: ConnectedWorld | undefined;\n  let myId: string | undefined;\n  let connectionType: ConnectionType | undefined;\n\n  socket.on(DA_HELLO, function (id) {\n    myId = id;\n    const instance: ConnectedWorld = instances.get(id) ?? {\n      server: socket,\n      apps: new Map(),\n    };\n\n    instance.server = socket;\n    instances.set(id, instance);\n    connectionType = ConnectionType.DA;\n    console.log('instances ' + instances.size);\n    myInstance = instance;\n    console.log('Desktop Agent connected: ' + id);\n  });\n\n  socket.on(APP_HELLO, function (id: string, appId: string) {\n    const instance = instances.get(id);\n\n    if (instance != undefined) {\n      console.log(`An app connected to DA ${id} with id ${appId}`);\n      instance.apps.set(appId, socket);\n      myInstance = instance;\n      connectionType = ConnectionType.APP;\n      myId = appId;\n    } else {\n      console.log('App Tried Connecting to non-existent DA Instance ' + id + ' ' + myId);\n    }\n  });\n\n  socket.on(FDC3_APP_EVENT, function (data, from): void {\n    // message from app to da\n\n    if (myInstance == null && data.type == 'intentResolutionChoice') {\n      // message from app's intent resolver\n      myInstance = Array.from(instances.values()).find(cw => cw.apps.get(from));\n    }\n\n    if (myInstance == null && data.type == 'channelSelectionChoice') {\n      // message from app's channelSelector\n      myInstance = Array.from(instances.values()).find(cw => cw.apps.get(from));\n    }\n\n    if (myInstance != undefined) {\n      myInstance.server.emit(FDC3_APP_EVENT, data, from);\n    }\n  });\n\n  socket.on(FDC3_DA_EVENT, function (data, to): void {\n    // send message to app\n    const destSocket = myInstance?.apps.get(to);\n    if (destSocket) {\n      destSocket.emit(FDC3_DA_EVENT, data, to);\n    } else {\n      console.log('Failed to send message to app ' + to);\n    }\n  });\n\n  socket.on('disconnect', function (): void {\n    if (myInstance) {\n      if (connectionType == ConnectionType.DA) {\n        console.log('DA disconnected: ' + myId);\n        instances.delete(myId!);\n      } else {\n        myInstance.apps.delete(myId!);\n        console.log(`App Disconnected: ${myId} ( ${myInstance.apps.size} remaining )`);\n        myInstance.server.emit(APP_GOODBYE, myId!);\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app1/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 1</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"../../src/client/apps/app1.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App1</p>\n  <button id=\"broadcast\">Press Me To Broadcast</button>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app2/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 2</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app2.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App2</p>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app3/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 3</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app3.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App3</p>\n  <button id=\"broadcast\">Press Me To Broadcast</button>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app4/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 4</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app4.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App4</p>\n  <p>Listens for the ViewNews intent...</p>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app5/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 5</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app5.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App5</p>\n  <p>Listens for the ViewNews + ViewQuote intents</p>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app6/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 6</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app6.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App6</p>\n  <p>Asks for an intent result</p>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/app7/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n  <title>App 7</title>\n  <meta charset=\"UTF-8\" />\n  <script type=\"module\" src=\"/src/client/apps/app7.ts\"></script>\n</head>\n\n<body>\n  <p>FDC3 For the Web App7</p>\n  <p>Asks for an intent result, involves intent resolver</p>\n  <div id=\"log\"></div>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/appd.json",
    "content": "{\n    \"applications\": [\n        {\n            \"appId\": \"app1\",\n            \"name\": \"App One\",\n            \"title\": \"Broadcaster\",\n            \"description\": \"App will connect to the desktop agent and broadcast on the red channel when you hit the button\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app1/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        },\n        {\n            \"appId\": \"app2\",\n            \"name\": \"App Two\",\n            \"title\": \"Receiver\",\n            \"description\": \"App will connect to the desktop agent on startup and listen to messages on the red channel\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app2/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        },\n        {\n            \"appId\": \"app3\",\n            \"name\": \"App Three\",\n            \"title\": \"Receiver & Broadcaster\",\n            \"description\": \"App creates two APIs to the desktop agent, broadcasts in one and listens in the other.\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app3/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        },\n        {\n            \"appId\": \"workbench\",\n            \"name\": \"FDC3 Workbench\",\n            \"title\": \"FDC3 Workbench\",\n            \"description\": \"Part of the WebFDC3 Demo - Port of the FDC3 Workbench.  Must be started separately on localhost:4001\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4001/toolbox/fdc3-workbench/\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        },\n        {\n            \"appId\": \"app4\",\n            \"name\": \"App Four\",\n            \"title\": \"View News Intent Listener\",\n            \"description\": \"Listens for the ViewNews intent only\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app4/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": [],\n            \"interop\": {\n                \"intents\": {\n                    \"listensFor\": {\n                        \"ViewNews\": {\n                            \"displayName\": \"View News\",\n                            \"contexts\": [\n                                \"fdc3.instrument\"\n                            ]\n                        }\n                    }\n                }\n            }\n        },\n        {\n            \"appId\": \"app5\",\n            \"name\": \"App Five\",\n            \"title\": \"View News + View Quote Intent Listener\",\n            \"description\": \"Listens for the ViewNews intent only\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app5/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": [],\n            \"interop\": {\n                \"intents\": {\n                    \"listensFor\": {\n                        \"ViewNews\": {\n                            \"displayName\": \"View News\",\n                            \"contexts\": [\n                                \"fdc3.instrument\"\n                            ]\n                        },\n                        \"ViewQuote\": {\n                            \"displayName\": \"View Quote\",\n                            \"contexts\": [\n                                \"fdc3.instrument\"\n                            ]\n                        }\n                    }\n                }\n            }\n        },\n        {\n            \"appId\": \"app6\",\n            \"name\": \"App Six\",\n            \"title\": \"Intent Result\",\n            \"description\": \"App asks for the result of a ViewQuote intent\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app6/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        },\n        {\n            \"appId\": \"app7\",\n            \"name\": \"App Seven\",\n            \"title\": \"Intent Result 2\",\n            \"description\": \"App asks for the result of a ViewNews intent\",\n            \"type\": \"web\",\n            \"details\": {\n                \"url\": \"http://localhost:4000/static/app7/index.html\"\n            },\n            \"hostManifests\": {},\n            \"version\": \"1.0.0\",\n            \"publisher\": \"FINOS\",\n            \"icons\": []\n        }\n    ],\n    \"message\": \"OK\"\n}"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/channel-selector.html",
    "content": "<html lang=\"en\">\n  <head>\n    <title>Desktop Agent Intent Resolver</title>\n    <meta charset=\"UTF-8\" />\n    <script type=\"module\" src=\"/src/client/ui/channel-selector.ts\"></script>\n    <style>\n      body #logo,\n      body #selector {\n        display: none;\n      }\n\n      body[data-expanded=\"selector\"] #selector {\n        display: flex;\n      }\n\n      body[data-expanded=\"logo\"] #logo {\n        display: block;\n      }\n\n      .selector {\n        width: 300px;\n        height: 300px;\n        position: fixed;\n        z-index: 2;\n        background-color: #fff;\n        right: 10px;\n        bottom: 10px;\n        border-radius: .5rem;\n        border: 1px solid black;\n        font-family: Arial, Helvetica, sans-serif;\n        display: flex;\n        flex-direction: column;\n      }\n\n      .background {\n        z-index: 999;\n        width: 100%;\n        height: 100%;\n        background-color: #22222222; \n      }\n\n      .logo {\n        z-index: 3;\n        position: fixed;\n        left: 0;\n        top: 0;\n     }\n\n     .header {\n      display: flex;\n      flex-basis: 2rem;\n      margin-top: .5rem;\n      flex-grow: 0\n     }\n\n     .header img {\n      flex-grow: 0;\n      flex-basis: 1.5rem;\n      width: 1.5rem;\n    }\n\n     .header h1 {\n      flex-grow: 1;\n      font-size: 1.5rem;\n      margin: .5rem;\n     }\n\n     .channel-list {\n      flex-grow: 1;\n      background-color: white;\n      border: 1px solid black;\n      margin: .5rem;\n      overflow-y: scroll;\n      flex-basis: 10rem;\n      border-radius: .5rem;\n     }\n\n     .channel-list div {\n      padding: .5rem;\n      margin: .5rem;\n      border-radius: .5rem;\n      color: white;\n     }\n\n     #drag {\n      cursor: move;\n     }\n      \n    </style>\n  </head>\n\n  <body data-expanded=\"logo\">\n\n\n    <div class=\"background\" id=\"background\">\n    </div>\n    \n    <div id=\"selector\" class=\"selector\" style=\"background-color: #ddd\">\n      <div class=\"header\">\n        <h1>Channel Selector</h1>\n        <img id=\"close\" src=\"close.svg\" alt=\"Drag\">        \n        <img id=\"drag\" src=\"drag.svg\" alt=\"Drag\">        \n      </div>\n      <div id=\"channel-list\" class=\"channel-list\">\n          <div>blib</div>\n          <div>blib</div>\n          <div>blib</div>\n          <div>blib</div>\n      </div>\n    </div>\n    <div id=\"logo\" class=\"logo\">\n      <img src=\"channel.svg\" alt=\"Channel Selector\" width=\"100%\" />\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/embed.html",
    "content": "<html lang=\"en\">\n\n<head>\n    <title>Desktop Agent</title>\n    <meta charset=\"UTF-8\" />\n    <script type=\"module\" src=\"/src/client/da/embed.ts\"></script>\n</head>\n\n<body>\n    <p>Embedded iframe - never seen!</p>\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n    <title>Desktop Agent</title>\n    <meta charset=\"UTF-8\" />\n    <script type=\"module\" src=\"/src/client/da/dummy-desktop-agent.ts\"></script>\n    <style>\n#app-list {\n    margin-top: 16px;\n    display: grid;\n    gap: 10px;\n    grid-template-columns: repeat(auto-fill, 170px);\n    grid-template-rows: masonry;\n}\n\n.app {\n    width: 150px;\n    height: 200px;\n    border: 1px solid black;\n    border-radius: 8px;\n    padding: 8px;\n    position: relative;\n\n    h3 {\n        margin: 8px 0;\n    }\n\n    p {\n        font-style: italic;\n    }\n\n    button {\n        position: absolute;\n        bottom: 8px;\n        right: 8px;\n    }\n}\n    </style>\n</head>\n\n<body>\n    <p>Demo Desktop Agent</p>\n\n    <select name=\"opener\" id=\"opener\">\n        <option value=\"Frame\" default>Frame</option>\n        <option value=\"Tab\">New Tab</option>\n    </select>\n\n    <select name=\"approach\" id=\"approach\">\n        <option value=\"IFRAME\">Create Iframe</option>\n        <option value=\"PARENT_POST_MESSAGE\" default>Parent Post-Message</option>\n    </select>\n\n    <select name=\"ui\" id=\"ui\">\n        <option value=\"DEMO\" default>Demo's Own Implementation</option>\n        <option value=\"DEFAULT\">Default Web FDC3 (Running on fdc3.finos.org)</option>\n        <option value=\"LOCAL\">Default Web FDC3 (Running on Localhost)</option>\n    </select>\n\n    <div id=\"app-list\" />\n\n    </div>\n\n\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/intent-resolver.html",
    "content": "<html lang=\"en\">\n  <head>\n    <title>Desktop Agent Intent Resolver</title>\n    <meta charset=\"UTF-8\" />\n    <script type=\"module\" src=\"/src/client/ui/intent-resolver.ts\"></script>\n  </head>\n\n  <body style=\"background-color: #ddd\">\n    <h1>Intent Resolution</h1>\n    <ul id=\"intent-list\"></ul>\n    <button id=\"cancel\">Cancel</button>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/da/local-conformance.v2.json",
    "content": "{\n\t\"applications\": [\n\t\t{\n\t\t\t\"appId\": \"Conformance1\",\n\t\t\t\"name\": \"Conformance1\",\n\t\t\t\"title\": \"FDC3 2.0 Conformance Framework\",\n\t\t\t\"description\": \"FDC3 2.0 Conformance testing framework - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/app/index.html\"\n\t\t\t},\n\t\t\t\"screenshots\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"https://directory.fdc3.finos.org/assets/app/Conformance1.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\"\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"left\": \"0\",\n\t\t\t\t\t\t\"width\": 800,\n\t\t\t\t\t\t\"height\": 900\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"ConformanceListener\": {\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"fdc3.nothing\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"ChannelsAppId\",\n\t\t\t\"name\": \"ChannelsApp\",\n\t\t\t\"title\": \"Channels App\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/channels\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppAId\",\n\t\t\t\"name\": \"IntentAppA\",\n\t\t\t\"title\": \"Intent App A\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-a\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"aTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"A Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\",\n\t\t\t\t\t\t\t\t\"testContextZ\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sharedTestingIntent1\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 1\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppBId\",\n\t\t\t\"name\": \"IntentAppB\",\n\t\t\t\"title\": \"Intent App B\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-b\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent1\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 1\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\",\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextY\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppCId\",\n\t\t\t\"name\": \"IntentAppC\",\n\t\t\t\"title\": \"Intent App C\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-c\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"cTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"C Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppDId\",\n\t\t\t\"name\": \"IntentAppD\",\n\t\t\t\"title\": \"Intent App D\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-d\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppEId\",\n\t\t\t\"name\": \"IntentAppE\",\n\t\t\t\"title\": \"Intent App E\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-e\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppFId\",\n\t\t\t\"name\": \"IntentAppF\",\n\t\t\t\"title\": \"Intent App F\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-f\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel<testContextZ>\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppGId\",\n\t\t\t\"name\": \"IntentAppG\",\n\t\t\t\"title\": \"Intent App G\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-g\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppHId\",\n\t\t\t\"name\": \"IntentAppH\",\n\t\t\t\"title\": \"Intent App H\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-h\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppIId\",\n\t\t\t\"name\": \"IntentAppI\",\n\t\t\t\"title\": \"Intent App I\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-i\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"sharedTestingIntent2\": {\n\t\t\t\t\t\t\t\"displayName\": \"Shared Testing Intent 2\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextY\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"testContextZ\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppJId\",\n\t\t\t\"name\": \"IntentAppJ\",\n\t\t\t\"title\": \"Intent App J\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-j\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"privateChannelIsPrivate\": {\n\t\t\t\t\t\t\t\"displayName\": \"J Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"privateChannelDetails\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"privateChannelIsPrivateResult\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"IntentAppKId\",\n\t\t\t\"name\": \"IntentAppK\",\n\t\t\t\"title\": \"Intent App K\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/intent-k\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"interop\": {\n\t\t\t\t\"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t\t\"kTestingIntent\": {\n\t\t\t\t\t\t\t\"displayName\": \"K Testing Intent\",\n\t\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t\t\t\"testContextX\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"resultType\": \"channel<testContextZ>\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"OpenAppAId\",\n\t\t\t\"name\": \"OpenAppA\",\n\t\t\t\"title\": \"Open App A\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/open-a\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"OpenAppBId\",\n\t\t\t\"name\": \"OpenAppB\",\n\t\t\t\"title\": \"Open App B\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/open-b\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"MockAppId\",\n\t\t\t\"name\": \"MockApp\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/general\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"joinMultipleChannels\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"appId\": \"MetadataAppId\",\n\t\t\t\"name\": \"MetadataApp\",\n\t\t\t\"title\": \"App Title\",\n\t\t\t\"description\": \"Part of the FDC3 2.0 Conformance Tests - developed for FINOS by Scott Logic\",\n\t\t\t\"details\": {\n\t\t\t\t\"url\": \"http://localhost:3001/apps/metadata\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t\t\"sail\": {\n\t\t\t\t\t\"inject-api\": \"2.0\",\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"forceNewWindow\": true\n\t\t\t\t},\n\t\t\t\t\"demo\": {\n\t\t\t\t\t\"visible\": false\n\t\t\t\t},\n\t\t\t\t\"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t\t\"top\": \"center\",\n\t\t\t\t\t\t\"right\": 0,\n\t\t\t\t\t\t\"width\": 600,\n\t\t\t\t\t\t\"height\": 400\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t\t\"components\": {\n\t\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t\t\t\"launchableByUser\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t\t\t\"FSBLHeader\": true,\n\t\t\t\t\t\t\t\t\"titlebarType\": \"injected\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t\t\"intents\": {\n\t\t\t\t\t\t\t\"listensFor\": {}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"placeholder\",\n\t\t\t\"publisher\": \"FINOS\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"icons\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t\t{\n\t\t\t\t\t\"src\": \"http://localhost:3001/finos-icon-256.png\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"message\": \"OK\"\n}"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/dnd/index.html",
    "content": "<html>\n    <head>\n        <title>Drag and Drop Demo</title>\n\n    </head>\n    <body>\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n\n        <iframe id=\"mover\" src=\"movable.html\"></iframe>\n\n        <script>\n            window.onload = function() {\n                console.log('loaded');\n\n                window.onmessage = function(event) {\n                    console.log('message', event);\n                    document.getElementById('mover').setAttribute('style', event.data);\n                }   \n            }\n\n        </script>\n\n    </body>\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/dnd/movable.html",
    "content": "\n<html>\n\n    <style>\n        .background {\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n            position: fixed;\n            background-color: #22222202;\n        }\n\n        .handle {\n            position: fixed;\n            right: 10;\n            width: 200px;\n            height: 200px;\n            background-color: red;\n        }\n\n\n    </style>\n\n    <body>\n\n        <div class=\"Background\">\n\n\n        </div>\n\n        <div class=\"handle\" id=\"myDiv\">    \nDrag Me\n\n        </div>\n\n        <script>\n\n\n  \nfunction dragElement(elmnt) {\n  var posXDrag = 0, posYDrag = 0, posXStart = 0, posYStart = 0;\n  var top = 0, left = 0;\n  \n  if (document.getElementById(elmnt.id + \"header\")) {\n    // if present, the header is where you move the DIV from:\n    document.getElementById(elmnt.id + \"header\").onmousedown = dragMouseDown;\n  } else {\n    // otherwise, move the DIV from anywhere inside the DIV:\n    elmnt.onmousedown = dragMouseDown;\n  }\n\n\n    function fire(css) {\n        window.parent.postMessage(css, '*');\n    }\n\n    function fireGrow() {\n        fire('left: 0; right: 0; top: 0; bottom: 0; position: fixed; width:100%; height:100%');\n        elmnt.style = `left: ${left}px; right: 0; top: ${top}px; bottom: 0; position: fixed; width:200px height:200px`\n    }\n\n    function fireShrink() {\n        fire(`left: ${left}px; top: ${top}px; position: fixed; width:200px; height:200px`);\n        elmnt.style = `left: 0; right: 0; top: 0; bottom: 0; position: fixed; width:100%; height:100%`\n    }\n\n  function dragMouseDown(e) {\n    e = e || window.event;\n    e.preventDefault();\n    // get the mouse cursor position at startup:\n    posXStart = left + e.clientX;\n    posYStart = top + e.clientY;\n    document.onmouseup = closeDragElement;\n    // call a function whenever the cursor moves:\n    document.onmousemove = elementDrag;\n    fireGrow()\n  }\n\n  function elementDrag(e) {\n    e = e || window.event;\n    e.preventDefault();\n    // calculate the new cursor position:\n    posXDrag = posXStart - e.clientX;\n    posYDrag = posYStart - e.clientY;\n    posXStart = e.clientX;\n    posYStart = e.clientY;\n    // set the element's new position:\n    top = Math.max((elmnt.offsetTop - posYDrag),0)\n    left= Math.max((elmnt.offsetLeft - posXDrag), 0)\n    left = Math.min(left, window.innerWidth - 200)\n    elmnt.style.top = top + \"px\";\n    elmnt.style.left = left + \"px\";\n  }\n\n  function closeDragElement() {\n    // stop moving when mouse button is released:\n    document.onmouseup = null;\n    document.onmousemove = null;\n    fireShrink()\n    console.log('closeDragElement');\n  }\n\n  fireShrink()\n}\nwindow.onload = function() {\n    console.log('loaded');\n    dragElement(document.getElementById(\"myDiv\"));\n}\n\n\n        </script>\n\n    </body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/static/embed/index.html",
    "content": "<html lang=\"en\">\n\n<head>\n    <title>Desktop Agent - Embedded Communications Agent</title>\n    <meta charset=\"UTF-8\" />\n    <script type=\"module\" src=\"/src/client/da/embed.ts\"></script>\n</head>\n\n<body>\n    <p>\n        Nothing to see here\n    </p>\n\n</body>\n\n</html>"
  },
  {
    "path": "toolbox/fdc3-for-web/demo/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"NodeNext\",\n    \"lib\": [\n      \"ESNext\",\n      \"DOM\"\n    ],\n    \"moduleResolution\": \"NodeNext\",\n    \"strict\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\n    \"src\"\n  ],\n  \"references\": [\n    {\n      \"path\": \"../../../packages/fdc3-standard\"\n    },\n    {\n      \"path\": \"../../../packages/fdc3-get-agent\"\n    },\n    {\n      \"path\": \"../fdc3-web-impl\"\n    }\n  ]\n}"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/README.md",
    "content": "# FDC3 Web Implementation\n\nThis repository contains a [FDC3 2.2 Conformant](../../fdc3-conformance/README.md), headless implementation of the FDC3 DACP protocol. \n\nThis package forms the basis of the implementation of the FDC3 Desktop Agent reference implementation, found in [the demo module](../demo/README.md) as well as the web-version of [FDC3-Sail](https://github.com/finos/FDC3-Sail/).\n\nIt is expected that Desktop Agent implementations can either use this package as the basis for their own FDC3 implementation, use the tests provided here to test their implementation or rake inspiration from the codebase to implement their own FDC3 Desktop Agent from scratch.\n\n## How This Works\n\nThere are three main types of component here:\n\n- **MessageHandlers**: These are the core of the FDC3 implementation. They are responsible for handling incoming messages from apps and responding to them correctly.  There are four defined, breaking up the functionality of FDC3:  `BroadcastHandler` (handing channels and broadcasting), `IntentHandler` (handling intents, intent resolution etc.), `OpenHandler` (handling app launches) and `HeartbeatHandler` (handling app liveness and disconnection).\n\n - **FDC3Server**: This is the main entry point for the FDC3 implementation. It is responsible for setting up the message handlers and starting the server, implemented by `BasicFDC3Server` and `DefaultFDC3Server` classes. \n\n - **ServerContext**: This interface is responsible for maintaining the state of the server.  `ServerContext` really determines how FDC3 is run: how messages are sent, how apps are launched, how intents are resolved etc.  It is the main point of customization for an FDC3 implementation. If you are implementing an FDC3 Desktop Agent, you will need to implement this class yourself.   See the [Demo](../demo/README.md), which implements this in-browser as `DemoServerContext`.  "
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/package.json",
    "content": "{\n  \"name\": \"@finos/fdc3-web-impl\",\n  \"version\": \"2.2.2\",\n  \"author\": \"Fintech Open Source Foundation (FINOS)\",\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"publishConfig\": {\n    \"tag\": \"latest\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"type\": \"module\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"main\": \"dist/src/index.js\",\n  \"types\": \"dist/src/index.d.ts\",\n  \"scripts\": {\n    \"clean\": \"rimraf dist coverage node_modules test-results.xml generated\",\n    \"directory-openapi\": \"npx openapi-typescript ../../../packages/fdc3-standard/src/app-directory/specification/appd.schema.json -o generated/directory-schema.ts\",\n    \"test\": \"npm run directory-openapi && tsc && vitest run\",\n    \"test:watch\": \"vitest\",\n    \"test:coverage\": \"vitest run --coverage\",\n    \"build\": \"npm run directory-openapi && tsc\",\n    \"lint\": \"eslint src/\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3-standard\": \"2.2.2\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"uuid\": \"^9.0.1\"\n  },\n  \"devDependencies\": {\n    \"@cucumber/cucumber\": \"10.3.1\",\n    \"@cucumber/html-formatter\": \"11.0.4\",\n    \"@cucumber/messages\": \"^28.1.0\",\n    \"@cucumber/pretty-formatter\": \"1.0.1\",\n    \"@finos/testing\": \"2.2.2\",\n    \"@types/expect\": \"24.3.0\",\n    \"@types/lodash\": \"4.14.167\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"cucumber-console-formatter\": \"1.0.0\",\n    \"eslint-plugin-import\": \"^2.31.0\",\n    \"eslint-plugin-prettier\": \"3.3.1\",\n    \"is-ci\": \"2.0.0\",\n    \"jsonpath-plus\": \"^10.1.0\",\n    \"openapi-typescript\": \"^7.13.0\",\n    \"quickpickle\": \"^1.0.0\",\n    \"ts-node\": \"^10.9.2\",\n    \"uuid\": \"^9.0.1\"\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts",
    "content": "import { FDC3Server } from './FDC3Server.js';\nimport { AppRegistration, InstanceID, ServerContext, State } from './ServerContext.js';\nimport { BroadcastHandler, ChannelState } from './handlers/BroadcastHandler.js';\nimport { IntentHandler } from './handlers/IntentHandler.js';\nimport { Directory } from './directory/DirectoryInterface.js';\nimport { OpenHandler } from './handlers/OpenHandler.js';\nimport { HeartbeatHandler } from './handlers/HeartbeatHandler.js';\nimport {\n  AppRequestMessage,\n  WebConnectionProtocol4ValidateAppIdentity,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nexport interface MessageHandler {\n  /**\n   * Handles an AgentRequestMessage from the messaging source. This function\n   * is called by BasicFDC3Server on every message received and should only\n   * process those it supports.\n   */\n  accept(\n    msg: AppRequestMessage | WebConnectionProtocol4ValidateAppIdentity | WebConnectionProtocol6Goodbye,\n    sc: ServerContext<AppRegistration>,\n    from: InstanceID\n  ): Promise<void>;\n\n  /**\n   * Clean-up any state relating to a instance that has disconnected.\n   */\n  cleanup(instanceId: InstanceID, sc: ServerContext<AppRegistration>): void;\n\n  shutdown(): void;\n}\n\n/**\n * This defers all functionality to either MessageHandler's or the ServerContext objects.\n */\nexport class BasicFDC3Server implements FDC3Server {\n  readonly handlers: MessageHandler[];\n  private sc: ServerContext<AppRegistration>;\n\n  constructor(handlers: MessageHandler[], sc: ServerContext<AppRegistration>) {\n    this.handlers = handlers;\n    this.sc = sc;\n  }\n\n  cleanup(instanceId: InstanceID): void {\n    this.handlers.forEach(handler => handler.cleanup(instanceId, this.sc));\n    this.sc.setAppState(instanceId, State.Terminated);\n  }\n\n  async receive(\n    message: AppRequestMessage | WebConnectionProtocol4ValidateAppIdentity | WebConnectionProtocol6Goodbye,\n    from: InstanceID\n  ): Promise<void> {\n    const promises = this.handlers.map(h => h.accept(message, this.sc, from));\n    await Promise.allSettled(promises);\n  }\n\n  shutdown(): void {\n    this.handlers.forEach(h => h.shutdown());\n  }\n}\n\nexport class DefaultFDC3Server extends BasicFDC3Server {\n  constructor(\n    sc: ServerContext<AppRegistration>,\n    directory: Directory,\n    userChannels: ChannelState[],\n    heartbeats: boolean,\n    intentTimeoutMs: number = 20000,\n    openHandlerTimeoutMs: number = 15000\n  ) {\n    const handlers: MessageHandler[] = [\n      new BroadcastHandler(userChannels),\n      new IntentHandler(directory, intentTimeoutMs),\n      new OpenHandler(directory, openHandlerTimeoutMs),\n    ];\n\n    if (heartbeats) {\n      handlers.push(new HeartbeatHandler(openHandlerTimeoutMs / 3, openHandlerTimeoutMs, openHandlerTimeoutMs * 3));\n    }\n\n    super(handlers, sc);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/FDC3Server.ts",
    "content": "import { InstanceID } from './ServerContext.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\n\ntype AppRequestMessage = BrowserTypes.AppRequestMessage;\n\nexport interface FDC3Server {\n  /**\n   * Receive an incoming message\n   */\n  receive(message: AppRequestMessage, from: InstanceID): Promise<void>;\n\n  /**\n   * Cleanup state relating to an instance that has disconnected\n   */\n  cleanup(instanceId: InstanceID): void;\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts",
    "content": "import { AppIdentifier, AppIntent } from '@finos/fdc3-standard';\nimport { Context } from '@finos/fdc3-context';\nimport { FDC3Server } from './FDC3Server.js';\n\nexport enum State {\n  Pending /* App has started, but not completed FDC3 Handshake */,\n  Connected /* App has completed FDC3 handshake */,\n  NotResponding /* App has not responded to a heartbeat */,\n  Terminated /* App has sent a termination message */,\n}\n\nexport type AppRegistration = {\n  state: State;\n  appId: string;\n  instanceId: InstanceID;\n};\n\n/**\n * This is a unique, long, unguessable string that identifies a particular instance of an app.\n * All messages arriving at the desktop agent will have this UUID attached to them.\n * It is important that this is unguessable as it is a shared secret used to identify the app\n * when reconnecting after navigation or refresh.\n */\nexport type InstanceID = string;\n\n/**\n * Handles messaging to apps and opening apps\n */\nexport interface ServerContext<X extends AppRegistration> {\n  /**\n   * UUID for outgoing message\n   */\n  createUUID(): string;\n\n  /**\n   * Post an outgoing message to a particular app\n   */\n  post(message: object, instanceId: InstanceID): Promise<void>;\n\n  /**\n   * Opens a new instance of an application.\n   * Promise completes once the application window is opened\n   * @param appId - the appId of the application to open\n   * @param source - the AppIdentifier of the app that requested the open, if available\n   */\n  open(appId: string, source?: AppIdentifier): Promise<InstanceID>;\n\n  /** Set the FDC3Server instance associated with this context. This reference is\n   *  used to notify the server to cleanup state for apps that have been terminated.\n   *  The FDC3Server is passed a ServerContext when created and should call this fn\n   *  in its constructor.\n   */\n  setFDC3Server(server: FDC3Server): void;\n\n  /**\n   * Registers a particular instance id with a given app id\n   */\n  setInstanceDetails(uuid: InstanceID, details: X): void;\n\n  /**\n   * Returns the connection details for a particular instance of an app.\n   * Used in a variety of MessageHandler classes to retrieve details for\n   * an app and when validating an app's identity when connecting.\n   */\n  getInstanceDetails(uuid: InstanceID): X | undefined;\n\n  /**\n   * Registers an app as connected to the desktop agent.\n   */\n  setAppState(app: InstanceID, state: State): Promise<void>;\n\n  /**\n   * Returns the list of apps open and connected to FDC3 at the current time.\n   * Note, it is the implementor's job to ensure this list is\n   * up-to-date in the event of app crashes or disconnections.\n   */\n  getConnectedApps(): Promise<AppRegistration[]>;\n\n  /**\n   * Return the list of all apps that have ever been registered with the ServerContext.\n   */\n  getAllApps(): Promise<AppRegistration[]>;\n\n  /**\n   * Helper function for determining if an app is currently open and connected to the da\n   */\n  isAppConnected(app: InstanceID): Promise<boolean>;\n\n  /**\n   * Allows you to write a log message somewhere\n   */\n  log(message: string): void;\n\n  /**\n   * Name of the provider of this desktop agent server\n   */\n  provider(): string;\n\n  /**\n   * Version of the provider of this desktop agent server\n   */\n  providerVersion(): string;\n\n  /**\n   * Supported version of the FDC3 API of the desktop agent server.\n   */\n  fdc3Version(): string;\n\n  /**\n   * This is called prior to returning intents to the client.  It is a\n   * an opportunity for the server to either present an intent resolver\n   * or otherwise mess with the available intents, or do nothing.\n   */\n  narrowIntents(raiser: AppIdentifier, IappIntents: AppIntent[], context: Context): Promise<AppIntent[]>;\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/directory/BasicDirectory.ts",
    "content": "import { Directory, DirectoryApp, DirectoryIntent } from './DirectoryInterface.js';\n\nexport function genericResultTypeSame(real: string | undefined, required: string | undefined) {\n  if (required == undefined) {\n    return true;\n  } else if (real == required) {\n    return true;\n  } else if (real == undefined) {\n    return false; // required is not undefined, so asking for something\n  } else if (real.startsWith('channel<') && required == 'channel') {\n    return true;\n  } else {\n    return false;\n  }\n}\n\n/**\n * Basic directory implementation that allows queries over a set of apps.\n */\nexport class BasicDirectory implements Directory {\n  allApps: DirectoryApp[];\n\n  constructor(apps: DirectoryApp[]) {\n    this.allApps = apps;\n  }\n\n  private intentMatches(\n    i: DirectoryIntent,\n    contextType: string | undefined,\n    intentName: string | undefined,\n    resultType: string | undefined\n  ): boolean {\n    const out =\n      (intentName == undefined || i.intentName == intentName) &&\n      (contextType == undefined || (i.contexts ?? []).includes(contextType)) &&\n      genericResultTypeSame(i.resultType, resultType);\n    return out;\n  }\n\n  private retrieveIntentsForApp(a: DirectoryApp): DirectoryIntent[] {\n    const lf = a.interop?.intents?.listensFor ?? {};\n    const lfa = Object.entries(lf);\n    const lfAugmented = lfa.map(([key, value]) => {\n      return {\n        intentName: key,\n        ...value,\n        appId: a.appId,\n      };\n    });\n    return lfAugmented;\n  }\n\n  retrieveAllIntents(): DirectoryIntent[] {\n    const allIntents = this.retrieveAllApps().flatMap(a => this.retrieveIntentsForApp(a));\n\n    return allIntents;\n  }\n\n  retrieveIntents(\n    contextType: string | undefined,\n    intentName: string | undefined,\n    resultType: string | undefined\n  ): DirectoryIntent[] {\n    const matchingIntents = this.retrieveAllIntents().filter(i =>\n      this.intentMatches(i, contextType, intentName, resultType)\n    );\n    return matchingIntents;\n  }\n\n  retrieveApps(\n    contextType: string | undefined,\n    intentName?: string | undefined,\n    resultType?: string | undefined\n  ): DirectoryApp[] {\n    const result = this.retrieveAllApps().filter(\n      a =>\n        this.retrieveIntentsForApp(a).filter(i => this.intentMatches(i, contextType, intentName, resultType)).length > 0\n    );\n\n    return result;\n  }\n\n  retrieveAppsById(appId: string): DirectoryApp[] {\n    return this.retrieveAllApps().filter(a => a.appId == appId);\n  }\n\n  retrieveAllApps(): DirectoryApp[] {\n    return this.allApps;\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/directory/DirectoryInterface.ts",
    "content": "import { components } from '../../generated/directory-schema.js';\n\ntype schemas = components['schemas'];\n\nexport type DirectoryIntent = schemas['Intent'] & { intentName: string; appId: string };\nexport type DirectoryApp = schemas['Application'];\nexport type WebAppDetails = schemas['WebAppDetails'];\n\n/**\n * This interface wraps the functionality of the FDC3 Directory structure (stored in JSON),\n * providing lookup calls to functions that would be handled by inspecting the directory/directories JSON definitions.\n */\n\nexport interface Directory {\n  retrieveAllApps(): DirectoryApp[];\n\n  retrieveApps(\n    contextType: string | undefined,\n    intentName: string | undefined,\n    resultType: string | undefined\n  ): DirectoryApp[];\n\n  retrieveAllIntents(): DirectoryIntent[];\n\n  retrieveIntents(\n    contextType: string | undefined,\n    intentName?: string | undefined,\n    resultType?: string\n  ): DirectoryIntent[];\n\n  retrieveAppsById(appId: string): DirectoryApp[];\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts",
    "content": "import { MessageHandler } from '../BasicFDC3Server.js';\nimport { AppRegistration, InstanceID, ServerContext } from '../ServerContext.js';\nimport { AppIdentifier, ChannelError, DisplayMetadata, PrivateChannelEventTypes } from '@finos/fdc3-standard';\nimport { successResponse, errorResponse, FullAppIdentifier } from './support.js';\nimport {\n  AddContextListenerRequest,\n  AddEventListenerRequest,\n  AgentResponseMessage,\n  AppRequestMessage,\n  BroadcastEvent,\n  BroadcastRequest,\n  ChannelChangedEvent,\n  ContextListenerUnsubscribeRequest,\n  CreatePrivateChannelRequest,\n  EventListenerUnsubscribeRequest,\n  GetCurrentChannelRequest,\n  GetCurrentContextRequest,\n  GetOrCreateChannelRequest,\n  GetUserChannelsRequest,\n  JoinUserChannelRequest,\n  LeaveCurrentChannelRequest,\n  PrivateChannelAddEventListenerRequest,\n  PrivateChannelDisconnectRequest,\n  PrivateChannelOnAddContextListenerEvent,\n  PrivateChannelOnDisconnectEvent,\n  PrivateChannelOnUnsubscribeEvent,\n  PrivateChannelUnsubscribeEventListenerRequest,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { Context } from '@finos/fdc3-context';\n\ntype PrivateChannelEvents =\n  | PrivateChannelOnAddContextListenerEvent\n  | PrivateChannelOnUnsubscribeEvent\n  | PrivateChannelOnDisconnectEvent;\n\ntype ContextListenerRegistration = {\n  appId: string;\n  instanceId: string;\n  listenerUuid: string;\n  channelId: string | null;\n  contextType: string | null;\n};\n\ntype PrivateChannelEventListener = {\n  appId: string;\n  instanceId: string;\n  channelId: string;\n  eventType: PrivateChannelEventTypes | null;\n  listenerUuid: string;\n};\n\ntype DesktopAgentEventListener = {\n  appId: string;\n  instanceId: string;\n  eventType: string | null;\n  listenerUuid: string;\n};\n\nexport enum ChannelType {\n  'user',\n  'app',\n  'private',\n}\n\nexport type ChannelState = {\n  id: string;\n  type: ChannelType;\n  context: Context[];\n  displayMetadata: DisplayMetadata;\n};\n\nfunction onlyUniqueAppIds(value: AppIdentifier, index: number, self: AppIdentifier[]) {\n  const fi = self.findIndex(v => v.instanceId === value.instanceId);\n  return fi === index;\n}\n\nexport class BroadcastHandler implements MessageHandler {\n  private contextListeners: ContextListenerRegistration[] = [];\n  private privateChannelEventListeners: PrivateChannelEventListener[] = [];\n  private desktopAgentEventListeners: DesktopAgentEventListener[] = [];\n  private readonly state: ChannelState[] = [];\n  private readonly currentChannel: { [instanceId: string]: ChannelState } = {};\n\n  constructor(initialChannelState: ChannelState[]) {\n    this.state = initialChannelState;\n  }\n\n  shutdown(): void {}\n\n  cleanup(instanceId: InstanceID, sc: ServerContext<AppRegistration>): void {\n    const toUnsubscribe = this.contextListeners.filter(r => r.instanceId == instanceId);\n\n    //handle privateChannel disconnects\n    const privateChannelsToUnsubscribe = toUnsubscribe.filter(\n      u => this.state.find(chan => chan.id == u.channelId)?.type == ChannelType.private\n    );\n\n    const privateChannelsToDisconnect = new Set<string>();\n    privateChannelsToUnsubscribe.forEach(u => {\n      this.invokePrivateChannelEventListeners(\n        u.channelId,\n        'unsubscribe',\n        'privateChannelOnUnsubscribeEvent',\n        sc,\n        u.contextType ?? undefined\n      );\n      if (u.channelId) {\n        privateChannelsToDisconnect.add(u.channelId);\n      }\n    });\n\n    privateChannelsToDisconnect.forEach(chan => {\n      this.invokePrivateChannelEventListeners(chan, 'disconnect', 'privateChannelOnDisconnectEvent', sc);\n    });\n\n    //clean up state entries\n    this.contextListeners = this.contextListeners.filter(listener => listener.instanceId !== instanceId);\n    this.privateChannelEventListeners = this.privateChannelEventListeners.filter(\n      listener => listener.instanceId !== instanceId\n    );\n    this.desktopAgentEventListeners = this.desktopAgentEventListeners.filter(\n      listener => listener.instanceId !== instanceId\n    );\n  }\n\n  getCurrentChannel(from: FullAppIdentifier): ChannelState | null {\n    return this.currentChannel[from.instanceId];\n  }\n\n  fireChannelChangedEvent(channelId: string | null, sc: ServerContext<AppRegistration>, instanceId: string) {\n    const event: ChannelChangedEvent = {\n      meta: {\n        eventUuid: sc.createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'channelChangedEvent',\n      payload: {\n        newChannelId: channelId,\n      },\n    };\n\n    sc.post(event, instanceId);\n  }\n\n  getChannelById(id: string | null): ChannelState | null {\n    if (id == null) {\n      return null;\n    }\n    return this.state.find(c => c.id == id) ?? null;\n  }\n\n  convertChannelTypeToString(type: ChannelType): string {\n    switch (type) {\n      case ChannelType.app:\n        return 'app';\n      case ChannelType.user:\n        return 'user';\n      case ChannelType.private:\n        return 'private';\n    }\n  }\n\n  updateChannelState(channelId: string, context: Context) {\n    const cs = this.getChannelById(channelId);\n    if (cs) {\n      cs.context = cs.context.filter(c => c.type != context.type);\n      cs.context.unshift(context);\n    }\n  }\n\n  async accept(msg: AppRequestMessage, sc: ServerContext<AppRegistration>, uuid: InstanceID) {\n    const from = sc.getInstanceDetails(uuid);\n\n    if (from == null) {\n      // this handler only deals with connected apps\n      return;\n    }\n\n    try {\n      switch (msg.type as string | null) {\n        // app channels registration\n        case 'getOrCreateChannelRequest':\n          return this.handleGetOrCreateRequest(msg as GetOrCreateChannelRequest, sc, from);\n\n        // user channel management\n        case 'getUserChannelsRequest':\n          return this.handleGetUserChannelsRequest(msg as GetUserChannelsRequest, sc, from);\n        case 'leaveCurrentChannelRequest':\n          return this.handleLeaveCurrentChannelRequest(msg as LeaveCurrentChannelRequest, sc, from);\n        case 'joinUserChannelRequest':\n          return this.handleJoinUserChannelRequest(msg as JoinUserChannelRequest, sc, from);\n        case 'getCurrentChannelRequest':\n          return this.handleGetCurrentChannelRequest(msg as GetCurrentChannelRequest, sc, from);\n\n        // general broadcast\n        case 'broadcastRequest':\n          return this.handleBroadcastRequest(msg as BroadcastRequest, sc, from);\n\n        // context listeners\n        case 'addContextListenerRequest':\n          return this.handleAddContextListenerRequest(msg as AddContextListenerRequest, sc, from);\n        case 'contextListenerUnsubscribeRequest':\n          return this.handleContextListenerUnsubscribeRequest(msg as ContextListenerUnsubscribeRequest, sc, from);\n\n        // private channels create/disconnect\n        case 'createPrivateChannelRequest':\n          return this.handleCreatePrivateChannelRequest(msg as CreatePrivateChannelRequest, sc, from);\n        case 'privateChannelDisconnectRequest':\n          return this.handlePrivateChannelDisconnectRequest(msg as PrivateChannelDisconnectRequest, sc, from);\n\n        // private channel event listeners\n        case 'privateChannelAddEventListenerRequest':\n          return this.handlePrivateChannelAddEventListenerRequest(\n            msg as PrivateChannelAddEventListenerRequest,\n            from,\n            sc\n          );\n        case 'privateChannelUnsubscribeEventListenerRequest':\n          return this.handlePrivateChannelUnsubscribeEventListenerRequest(\n            msg as PrivateChannelUnsubscribeEventListenerRequest,\n            sc,\n            from\n          );\n\n        // handling state synchronization of channels\n        case 'getCurrentContextRequest':\n          return this.handleGetCurrentContextRequest(msg as GetCurrentContextRequest, sc, from);\n\n        // Handle channel events\n        case 'addEventListenerRequest':\n          return this.handleAddEventListenerRequest(msg as AddEventListenerRequest, sc, from);\n        case 'eventListenerUnsubscribeRequest':\n          return this.handleEventListenerUnsubscribeRequest(msg as EventListenerUnsubscribeRequest, sc, from);\n      }\n    } catch (e) {\n      const responseType = msg.type.replace(new RegExp('Request$'), 'Response');\n      errorResponse(sc, msg, from, (e as Error).message ?? e, responseType as AgentResponseMessage['type']);\n    }\n  }\n\n  handleAddEventListenerRequest(\n    arg0: AddEventListenerRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const lr: DesktopAgentEventListener = {\n      appId: from.appId,\n      instanceId: from.instanceId ?? 'no-instance-id',\n      listenerUuid: sc.createUUID(),\n      eventType: arg0.payload.type ?? null,\n    };\n\n    this.desktopAgentEventListeners.push(lr);\n    successResponse(sc, arg0, from, { listenerUUID: lr.listenerUuid }, 'addEventListenerResponse');\n  }\n\n  handleEventListenerUnsubscribeRequest(\n    arg0: EventListenerUnsubscribeRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const i = this.desktopAgentEventListeners.findIndex(r => r.listenerUuid == arg0.payload.listenerUUID);\n    if (i > -1) {\n      this.desktopAgentEventListeners.splice(i, 1);\n      successResponse(sc, arg0, from, {}, 'eventListenerUnsubscribeResponse');\n    } else {\n      errorResponse(sc, arg0, from, 'ListenerNotFound', 'eventListenerUnsubscribeResponse');\n    }\n  }\n\n  handleCreatePrivateChannelRequest(\n    arg0: CreatePrivateChannelRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const id = sc.createUUID();\n    this.state.push({\n      id,\n      type: ChannelType.private,\n      context: [],\n      displayMetadata: {},\n    });\n\n    successResponse(\n      sc,\n      arg0,\n      from,\n      { privateChannel: { id, type: this.convertChannelTypeToString(ChannelType.private) } },\n      'createPrivateChannelResponse'\n    );\n  }\n\n  handleGetCurrentContextRequest(\n    arg0: GetCurrentContextRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const channel = this.getChannelById(arg0.payload.channelId);\n    const type = arg0.payload.contextType;\n\n    if (channel) {\n      const context = type ? (channel.context.find(c => c.type == type) ?? null) : (channel.context[0] ?? null);\n      successResponse(sc, arg0, from, { context: context }, 'getCurrentContextResponse');\n    } else {\n      errorResponse(sc, arg0, from, ChannelError.NoChannelFound, 'getCurrentContextResponse');\n    }\n  }\n\n  handlePrivateChannelUnsubscribeEventListenerRequest(\n    arg0: PrivateChannelUnsubscribeEventListenerRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const i = this.privateChannelEventListeners.findIndex(r => r.listenerUuid == arg0.payload.listenerUUID);\n    if (i > -1) {\n      this.privateChannelEventListeners.splice(i, 1);\n      successResponse(sc, arg0, from, {}, 'privateChannelUnsubscribeEventListenerResponse');\n    } else {\n      errorResponse(sc, arg0, from, 'ListenerNotFound', 'privateChannelUnsubscribeEventListenerResponse');\n    }\n  }\n\n  handlePrivateChannelDisconnectRequest(\n    arg0: PrivateChannelDisconnectRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const toUnsubscribe = this.contextListeners\n      .filter(r => r.appId == from.appId && r.instanceId == from.instanceId)\n      .filter(r => r.channelId == arg0.payload.channelId);\n\n    toUnsubscribe.forEach(u => {\n      this.invokePrivateChannelEventListeners(\n        arg0.payload.channelId,\n        'unsubscribe',\n        'privateChannelOnUnsubscribeEvent',\n        sc,\n        u.contextType ?? undefined\n      );\n    });\n\n    this.contextListeners = this.contextListeners.filter(r => !toUnsubscribe.includes(r));\n    this.invokePrivateChannelEventListeners(\n      arg0.payload.channelId,\n      'disconnect',\n      'privateChannelOnDisconnectEvent',\n      sc\n    );\n    successResponse(sc, arg0, from, {}, 'privateChannelDisconnectResponse');\n  }\n\n  handleContextListenerUnsubscribeRequest(\n    arg0: ContextListenerUnsubscribeRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const i = this.contextListeners.findIndex(\n      r => r.listenerUuid == arg0.payload.listenerUUID && r.instanceId == from.instanceId\n    );\n\n    if (i > -1) {\n      const rl = this.contextListeners[i];\n      const channel = this.getChannelById(rl.channelId);\n      this.invokePrivateChannelEventListeners(\n        channel?.id ?? null,\n        'unsubscribe',\n        'privateChannelOnUnsubscribeEvent',\n        sc,\n        rl.contextType ?? undefined\n      );\n      this.contextListeners.splice(i, 1);\n      successResponse(sc, arg0, from, {}, 'contextListenerUnsubscribeResponse');\n    } else {\n      errorResponse(sc, arg0, from, 'ListenerNotFound', 'contextListenerUnsubscribeResponse');\n    }\n  }\n\n  handleAddContextListenerRequest(\n    arg0: AddContextListenerRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    let channelId = null;\n\n    if (arg0.payload?.channelId) {\n      // if channelId is provided, we need to check if it exists\n      const channel = this.getChannelById(arg0.payload?.channelId);\n\n      if (channel == null) {\n        errorResponse(sc, arg0, from, ChannelError.NoChannelFound, 'addContextListenerResponse');\n        return;\n      } else {\n        channelId = channel.id;\n      }\n    }\n\n    const lr: ContextListenerRegistration = {\n      appId: from.appId,\n      instanceId: from.instanceId ?? 'no-instance-id',\n      channelId: channelId,\n      listenerUuid: sc.createUUID(),\n      contextType: arg0.payload.contextType,\n    };\n\n    this.contextListeners.push(lr);\n    this.invokePrivateChannelEventListeners(\n      channelId,\n      'addContextListener',\n      'privateChannelOnAddContextListenerEvent',\n      sc,\n      arg0.payload.contextType ?? undefined\n    );\n    successResponse(sc, arg0, from, { listenerUUID: lr.listenerUuid }, 'addContextListenerResponse');\n  }\n\n  handleBroadcastRequest(arg0: BroadcastRequest, sc: ServerContext<AppRegistration>, from: FullAppIdentifier) {\n    const matchesExactChannel = (r: ContextListenerRegistration) => {\n      return r.channelId == arg0.payload.channelId;\n    };\n\n    const matchesUserChannel = (r: ContextListenerRegistration) => {\n      const uc = this.currentChannel[r.instanceId];\n      const ucId = uc ? uc.id : null;\n      return r.channelId == null && ucId == arg0.payload.channelId;\n    };\n\n    const matchingListeners = this.contextListeners\n      // Deliver the message to apps listening to the right channel\n      .filter(r => matchesExactChannel(r) || matchesUserChannel(r))\n      // Deliver the message to apps with matching context type listeners\n      .filter(r => r.contextType == null || r.contextType == arg0.payload.context.type)\n      // Don't deliver messages back to the broadcasting app\n      .filter(r => r.instanceId !== from.instanceId);\n\n    const matchingApps: FullAppIdentifier[] = matchingListeners\n      .map(r => {\n        return { appId: r.appId, instanceId: r.instanceId };\n      })\n      .filter(onlyUniqueAppIds);\n\n    const msg: BroadcastEvent = {\n      meta: {\n        eventUuid: sc.createUUID(),\n        timestamp: new Date(),\n      },\n      type: 'broadcastEvent',\n      payload: {\n        channelId: arg0.payload.channelId,\n        context: arg0.payload.context,\n        originatingApp: {\n          appId: from.appId,\n          instanceId: from.instanceId,\n        },\n      },\n    };\n\n    matchingApps.forEach(app => {\n      sc.post(msg, app.instanceId);\n    });\n\n    this.updateChannelState(arg0.payload.channelId, arg0.payload.context);\n    successResponse(sc, arg0, from, {}, 'broadcastResponse');\n  }\n\n  handleGetCurrentChannelRequest(\n    arg0: GetCurrentChannelRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const currentChannel = this.getCurrentChannel(from);\n    if (currentChannel) {\n      successResponse(\n        sc,\n        arg0,\n        from,\n        {\n          channel: {\n            id: currentChannel.id,\n            type: this.convertChannelTypeToString(currentChannel.type),\n            displayMetadata: currentChannel.displayMetadata,\n          },\n        },\n        'getCurrentChannelResponse'\n      );\n    } else {\n      successResponse(sc, arg0, from, { channel: null }, 'getCurrentChannelResponse');\n    }\n  }\n\n  handleJoinUserChannelRequest(\n    arg0: JoinUserChannelRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    // check it's a user channel\n    const newChannel = this.getChannelById(arg0.payload.channelId);\n    if (newChannel == null || newChannel.type != ChannelType.user) {\n      return errorResponse(sc, arg0, from, ChannelError.NoChannelFound, 'joinUserChannelResponse');\n    }\n\n    // join it.\n    const instanceId = from.instanceId ?? 'no-instance-id';\n    this.currentChannel[instanceId] = newChannel;\n    this.fireChannelChangedEvent(newChannel?.id, sc, instanceId);\n    successResponse(sc, arg0, from, {}, 'joinUserChannelResponse');\n  }\n\n  handleLeaveCurrentChannelRequest(\n    arg0: LeaveCurrentChannelRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const instanceId = from.instanceId ?? 'no-instance-id';\n    const currentChannel = this.currentChannel[instanceId];\n    if (currentChannel) {\n      delete this.currentChannel[instanceId];\n    }\n\n    this.fireChannelChangedEvent(null, sc, instanceId);\n    successResponse(sc, arg0, from, {}, 'leaveCurrentChannelResponse');\n  }\n\n  handleGetOrCreateRequest(\n    arg0: GetOrCreateChannelRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const id = arg0.payload.channelId;\n    let channel = this.getChannelById(id);\n\n    if (!channel) {\n      channel = {\n        id: id,\n        type: ChannelType.app,\n        context: [],\n        displayMetadata: {},\n      };\n      this.state.push(channel);\n    }\n\n    //only allow retrieval of app channels or user channels\n    if (channel.type == ChannelType.app || channel.type == ChannelType.user) {\n      successResponse(\n        sc,\n        arg0,\n        from,\n        { channel: { id: channel.id, type: this.convertChannelTypeToString(channel.type) } },\n        'getOrCreateChannelResponse'\n      );\n    } else {\n      //block retrieval of private channels\n      errorResponse(sc, arg0, from, ChannelError.AccessDenied, 'getOrCreateChannelResponse');\n    }\n  }\n\n  handleGetUserChannelsRequest(\n    arg0: GetUserChannelsRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ) {\n    const userChannels = this.state.filter(c => c.type == ChannelType.user);\n    successResponse(\n      sc,\n      arg0,\n      from,\n      {\n        userChannels: userChannels.map(c => ({\n          id: c.id,\n          type: this.convertChannelTypeToString(c.type),\n          displayMetadata: c.displayMetadata,\n        })),\n      },\n      'getUserChannelsResponse'\n    );\n  }\n\n  handlePrivateChannelAddEventListenerRequest(\n    arg0: PrivateChannelAddEventListenerRequest,\n    from: FullAppIdentifier,\n    sc: ServerContext<AppRegistration>\n  ) {\n    const channel = this.getChannelById(arg0.payload.privateChannelId);\n\n    if (channel == null || channel.type != ChannelType.private) {\n      errorResponse(sc, arg0, from, ChannelError.NoChannelFound, 'privateChannelAddEventListenerResponse');\n    } else {\n      const el = {\n        appId: from.appId,\n        instanceId: from.instanceId,\n        channelId: arg0.payload.privateChannelId,\n        eventType: arg0.payload.listenerType,\n        listenerUuid: sc.createUUID(),\n      } as PrivateChannelEventListener;\n      this.privateChannelEventListeners.push(el);\n      successResponse(sc, arg0, from, { listenerUUID: el.listenerUuid }, 'privateChannelAddEventListenerResponse');\n    }\n  }\n\n  invokePrivateChannelEventListeners(\n    privateChannelId: string | null,\n    eventType: PrivateChannelEventTypes,\n    messageType:\n      | 'privateChannelOnAddContextListenerEvent'\n      | 'privateChannelOnUnsubscribeEvent'\n      | 'privateChannelOnDisconnectEvent',\n    sc: ServerContext<AppRegistration>,\n    contextType?: string\n  ) {\n    if (privateChannelId) {\n      const msg: PrivateChannelEvents = {\n        type: messageType,\n        meta: {\n          eventUuid: sc.createUUID(),\n          timestamp: new Date(),\n        },\n        payload: {\n          privateChannelId,\n          contextType: contextType,\n        },\n      } as PrivateChannelEvents; //Typescript doesn't like comparing an object with a union property (messageType) with a union of object types\n\n      console.debug('invokePrivateChannelEventListeners msg: ', msg);\n      this.privateChannelEventListeners\n        .filter(\n          listener =>\n            listener.channelId == privateChannelId && (listener.eventType == eventType || listener.eventType == null)\n        )\n        .filter(onlyUniqueAppIds)\n        .forEach(e => {\n          console.debug(`invokePrivateChannelEventListeners: posting to instance ${e.instanceId}`);\n          sc.post(msg, e.instanceId);\n        });\n    }\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts",
    "content": "import { MessageHandler } from '../BasicFDC3Server.js';\nimport { AppRegistration, InstanceID, ServerContext, State } from '../ServerContext.js';\nimport {\n  AppRequestMessage,\n  HeartbeatEvent,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { FullAppIdentifier } from './support.js';\n\ntype HeartbeatDetails = {\n  instanceId: string;\n  time: number;\n  state: string;\n};\n\nfunction convertToText(s?: State): string {\n  if (s == undefined) {\n    return 'Unknown';\n  } else {\n    switch (s) {\n      case State.Pending:\n        return 'Pending';\n      case State.Connected:\n        return 'Connected';\n      case State.NotResponding:\n        return 'Not Responding';\n      case State.Terminated:\n        return 'Terminated';\n    }\n  }\n}\n\n/*\n * Handles heartbeat pings and responses\n */\nexport class HeartbeatHandler implements MessageHandler {\n  private readonly contexts: ServerContext<AppRegistration>[] = [];\n  private readonly lastHeartbeats: Map<InstanceID, number> = new Map();\n  private readonly timerFunction: NodeJS.Timeout;\n\n  constructor(pingInterval: number = 5000, disconnectedAfter: number = 30000, deadAfter: number = 60000) {\n    console.log(\n      `Setting up Heartbeat handler: pingInterval: ${pingInterval} ms, disconnectedAfter: ${disconnectedAfter} ms, deadAfter: ${deadAfter} ms`\n    );\n\n    this.timerFunction = setInterval(() => {\n      this.contexts.forEach(async sc => {\n        const apps = await sc.getAllApps();\n        apps\n          .filter(app => app.state == State.Connected || app.state == State.NotResponding)\n          .forEach(app => {\n            const now = new Date().getTime();\n            this.sendHeartbeat(sc, app);\n\n            // check when the last heartbeat happened\n            const lastHeartbeat = this.lastHeartbeats.get(app.instanceId);\n            const currentState = app.state;\n\n            if (lastHeartbeat != undefined) {\n              const timeSinceLastHeartbeat = now - lastHeartbeat;\n\n              if (timeSinceLastHeartbeat < disconnectedAfter && currentState != State.Connected) {\n                console.error(\n                  `Heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms. App is considered connected.`\n                );\n                sc.setAppState(app.instanceId, State.Connected);\n              } else if (timeSinceLastHeartbeat > disconnectedAfter && currentState == State.Connected) {\n                console.error(\n                  `No heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms. App is considered not responding.`\n                );\n                sc.setAppState(app.instanceId, State.NotResponding);\n              } else if (timeSinceLastHeartbeat > deadAfter && currentState == State.NotResponding) {\n                console.error(\n                  `No heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms. App is considered terminated.`\n                );\n                sc.setAppState(app.instanceId, State.Terminated);\n              } else {\n                // no action\n              }\n            } else {\n              // start the clock\n              this.lastHeartbeats.set(app.instanceId, now);\n            }\n          });\n      });\n    }, pingInterval);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  cleanup(_instanceId: InstanceID, _sc: ServerContext<AppRegistration>): void {\n    //TODO: Consider whether to clean-up last heartbeat times\n  }\n\n  heartbeatTimes(): HeartbeatDetails[] {\n    const now = new Date().getTime();\n    return Array.from(this.lastHeartbeats)\n      .map(e => {\n        return {\n          instanceId: e[0],\n          time: now - e[1],\n          state: convertToText(this.contexts.map(sc => sc.getInstanceDetails(e[0])).reduce((a, b) => a || b)?.state),\n        } as HeartbeatDetails;\n      })\n      .filter(e => e.state != 'Terminated');\n  }\n\n  shutdown(): void {\n    clearInterval(this.timerFunction);\n  }\n\n  async accept(\n    msg: AppRequestMessage | WebConnectionProtocol6Goodbye,\n    sc: ServerContext<AppRegistration>,\n    from: InstanceID\n  ): Promise<void> {\n    if (!this.contexts.includes(sc)) {\n      this.contexts.push(sc);\n    }\n\n    if (msg.type == 'heartbeatAcknowledgementRequest') {\n      const app = sc.getInstanceDetails(from);\n      if (app) {\n        this.lastHeartbeats.set(app.instanceId, new Date().getTime());\n      }\n    }\n\n    if (msg.type == 'WCP6Goodbye') {\n      const app = sc.getInstanceDetails(from);\n      if (app) {\n        sc.setAppState(from, State.Terminated);\n      }\n    }\n  }\n\n  async sendHeartbeat(sc: ServerContext<AppRegistration>, app: FullAppIdentifier): Promise<void> {\n    const event: HeartbeatEvent = {\n      type: 'heartbeatEvent',\n      meta: {\n        timestamp: new Date(),\n        eventUuid: sc.createUUID(),\n      },\n      payload: {},\n    };\n    sc.post(event, app.instanceId);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts",
    "content": "import { MessageHandler } from '../BasicFDC3Server.js';\nimport { AppRegistration, InstanceID, ServerContext, State } from '../ServerContext.js';\nimport { Directory, DirectoryIntent } from '../directory/DirectoryInterface.js';\nimport { Context } from '@finos/fdc3-context';\nimport { AppIntent, ResolveError, AppIdentifier } from '@finos/fdc3-standard';\nimport {\n  errorResponse,\n  errorResponseId,\n  FullAppIdentifier,\n  isFullAppIdentifier,\n  successResponse,\n  successResponseId,\n} from './support.js';\nimport {\n  IntentEvent,\n  FindIntentsByContextRequest,\n  FindIntentRequest,\n  AddIntentListenerRequest,\n  IntentListenerUnsubscribeRequest,\n  RaiseIntentRequest,\n  RaiseIntentForContextRequest,\n  IntentResultRequest,\n  AppRequestMessage,\n  AgentResponseMessage,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype ListenerRegistration = {\n  appId: string;\n  instanceId: string;\n  intentName: string;\n  listenerUUID: string;\n};\n\ntype IntentRequest = {\n  intent: string;\n  context: Context;\n  requestUuid: string;\n  from: FullAppIdentifier;\n  type: 'raiseIntentResponse' | 'raiseIntentForContextResponse';\n};\n\n/**\n * Re-writes the request to forward it on to the target application\n */\nasync function forwardRequest(\n  arg0: IntentRequest,\n  to: FullAppIdentifier,\n  sc: ServerContext<AppRegistration>,\n  ih: IntentHandler\n): Promise<void> {\n  const out: IntentEvent = {\n    type: 'intentEvent',\n    payload: {\n      context: arg0.context,\n      intent: arg0.intent,\n      originatingApp: {\n        appId: arg0.from.appId,\n        instanceId: arg0.from.instanceId,\n      },\n      raiseIntentRequestUuid: arg0.requestUuid,\n    },\n    meta: {\n      eventUuid: sc.createUUID(),\n      timestamp: new Date(),\n    },\n  };\n\n  // register the resolution destination\n  ih.pendingResolutions.set(arg0.requestUuid, arg0.from);\n  await sc.post(out, to.instanceId);\n  successResponseId(\n    sc,\n    arg0.requestUuid,\n    arg0.from,\n    {\n      intentResolution: {\n        intent: arg0.intent,\n        source: { appId: to.appId, instanceId: to.instanceId }, //make sure we're not carrying any excess fields from internal state\n      },\n    },\n    arg0.type\n  );\n}\n\n/**\n * A pending intent is one for an app that hasn't registered it's intent listener yet.\n * (Possibly it is being opened)\n *\n * Pending intents wait for that registration and then message the app.\n */\nclass PendingIntent {\n  complete: boolean = false;\n  r: IntentRequest;\n  appId: AppIdentifier;\n  sc: ServerContext<AppRegistration>;\n  ih: IntentHandler;\n\n  constructor(r: IntentRequest, sc: ServerContext<AppRegistration>, ih: IntentHandler, appId: AppIdentifier) {\n    this.r = r;\n    this.appId = appId;\n    this.sc = sc;\n    this.ih = ih;\n\n    // handle the timeout\n    setTimeout(() => {\n      if (!this.complete) {\n        errorResponseId(sc, r.requestUuid, r.from, ResolveError.IntentDeliveryFailed, r.type);\n        this.ih.pendingIntents.delete(this);\n      }\n    }, ih.timeoutMs);\n  }\n\n  async accept(arg0: ListenerRegistration): Promise<void> {\n    if (\n      arg0.appId == this.appId.appId &&\n      arg0.intentName == this.r.intent &&\n      (arg0.instanceId == this.appId.instanceId || this.appId.instanceId == undefined)\n    ) {\n      this.complete = true;\n      this.ih.pendingIntents.delete(this);\n      forwardRequest(this.r, { appId: arg0.appId, instanceId: arg0.instanceId }, this.sc, this.ih);\n    }\n  }\n}\n\nexport class IntentHandler implements MessageHandler {\n  private readonly directory: Directory;\n  private registrations: ListenerRegistration[] = [];\n  readonly pendingIntents: Set<PendingIntent> = new Set();\n  readonly pendingResolutions: Map<string, FullAppIdentifier> = new Map();\n  readonly timeoutMs: number;\n\n  constructor(d: Directory, timeoutMs: number) {\n    this.directory = d;\n    this.timeoutMs = timeoutMs;\n  }\n\n  cleanup(instanceId: InstanceID /*, _sc: ServerContext<AppRegistration> */): void {\n    this.registrations = this.registrations.filter(reg => reg.instanceId != instanceId);\n    //don't clean up pendingIntents as some apps may load\n\n    //cleanup pendingResolutions\n    this.pendingResolutions.forEach((val, key) => {\n      if (val.instanceId === instanceId) {\n        this.pendingResolutions.delete(key);\n      }\n    });\n  }\n\n  shutdown(): void {}\n\n  async narrowIntents(\n    raiser: AppIdentifier,\n    appIntents: AppIntent[],\n    context: Context,\n    sc: ServerContext<AppRegistration>\n  ): Promise<AppIntent[]> {\n    const out = await sc.narrowIntents(raiser, appIntents, context);\n    return out;\n  }\n\n  async accept(msg: AppRequestMessage, sc: ServerContext<AppRegistration>, uuid: InstanceID): Promise<void> {\n    const from = sc.getInstanceDetails(uuid);\n\n    if (from == null) {\n      // this handler only deals with connected apps\n      return;\n    }\n\n    try {\n      switch (msg.type as string) {\n        // finding intents\n        case 'findIntentsByContextRequest':\n          return await this.findIntentsByContextRequest(msg as FindIntentsByContextRequest, sc, from);\n        case 'findIntentRequest':\n          return await this.findIntentRequest(msg as FindIntentRequest, sc, from);\n\n        // listeners\n        case 'addIntentListenerRequest':\n          return await this.onAddIntentListener(msg as AddIntentListenerRequest, sc, from);\n        case 'intentListenerUnsubscribeRequest':\n          return await this.onUnsubscribe(msg as IntentListenerUnsubscribeRequest, sc, from);\n\n        // raising intents and returning results\n        case 'raiseIntentRequest':\n          return await this.raiseIntentRequest(msg as RaiseIntentRequest, sc, from);\n        case 'raiseIntentForContextRequest':\n          return await this.raiseIntentForContextRequest(msg as RaiseIntentForContextRequest, sc, from);\n        case 'intentResultRequest':\n          return await this.intentResultRequest(msg as IntentResultRequest, sc, from);\n      }\n    } catch (e) {\n      const responseType = msg.type.replace(new RegExp('Request$'), 'Response') as AgentResponseMessage['type'];\n      errorResponse(sc, msg, from, (e as Error).message ?? e, responseType);\n    }\n  }\n\n  /**\n   * Called when target app handles an intent\n   */\n  intentResultRequest(\n    arg0: IntentResultRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): void | PromiseLike<void> {\n    const requestId = arg0.payload.raiseIntentRequestUuid;\n    const to = this.pendingResolutions.get(requestId);\n    if (to) {\n      // post the result to the app that raised the intent\n      //   if its still connected, otherwise do nothing\n      successResponseId(\n        sc,\n        requestId,\n        to,\n        {\n          intentResult: arg0.payload.intentResult,\n        },\n        'raiseIntentResultResponse'\n      );\n\n      this.pendingResolutions.delete(requestId);\n    }\n    // respond to the app that handled the intent\n    successResponse(sc, arg0, from, {}, 'intentResultResponse');\n  }\n\n  onUnsubscribe(\n    arg0: IntentListenerUnsubscribeRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): void {\n    const id = arg0.payload.listenerUUID;\n    const fi = this.registrations.findIndex(e => e.listenerUUID == id);\n    if (fi > -1) {\n      this.registrations.splice(fi, 1);\n      successResponse(sc, arg0, from, {}, 'intentListenerUnsubscribeResponse');\n    } else {\n      errorResponse(sc, arg0, from, 'Non-Existent Listener', 'intentListenerUnsubscribeResponse');\n    }\n  }\n\n  onAddIntentListener(\n    arg0: AddIntentListenerRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): void {\n    const lr: ListenerRegistration = {\n      appId: from.appId,\n      instanceId: from.instanceId,\n      intentName: arg0.payload.intent,\n      listenerUUID: sc.createUUID(),\n    };\n\n    this.registrations.push(lr);\n    successResponse(\n      sc,\n      arg0,\n      from,\n      {\n        listenerUUID: lr.listenerUUID,\n      },\n      'addIntentListenerResponse'\n    );\n\n    // see if this intent listener is the destination for any pending intents\n    for (const x of this.pendingIntents) {\n      x.accept(lr);\n      if (x.complete) {\n        this.pendingIntents.delete(x);\n      }\n    }\n  }\n\n  hasListener(instanceId: string, intentName: string): boolean {\n    return this.registrations.find(r => r.instanceId == instanceId && r.intentName == intentName) != null;\n  }\n\n  async startWithPendingIntent(\n    arg0: IntentRequest,\n    sc: ServerContext<AppRegistration>,\n    target: AppIdentifier\n  ): Promise<void> {\n    // app exists but needs starting\n    const pi = new PendingIntent(arg0, sc, this, target);\n    this.pendingIntents.add(pi);\n    sc.open(target.appId, arg0.from).then(() => {\n      return undefined;\n    });\n  }\n\n  async raiseIntentRequestToSpecificInstance(\n    arg0: IntentRequest[],\n    sc: ServerContext<AppRegistration>,\n    target: FullAppIdentifier\n  ): Promise<void> {\n    if (!(await sc.isAppConnected(target.instanceId))) {\n      // instance doesn't exist\n      return errorResponseId(\n        sc,\n        arg0[0].requestUuid,\n        arg0[0].from,\n        ResolveError.TargetInstanceUnavailable,\n        arg0[0].type\n      );\n    }\n\n    const requestsWithListeners = arg0.filter(r => this.hasListener(target.instanceId, r.intent));\n\n    if (requestsWithListeners.length == 0) {\n      this.createPendingIntentIfAllowed(arg0[0], sc, target);\n    } else {\n      // ok, deliver to the current running app.\n      return forwardRequest(requestsWithListeners[0], target, sc, this);\n    }\n  }\n\n  async createPendingIntentIfAllowed(ir: IntentRequest, sc: ServerContext<AppRegistration>, target: AppIdentifier) {\n    // if this app declares that it supports the intent, we'll create a pending intent\n    const matchingIntents: DirectoryIntent[] = this.directory.retrieveIntents(ir.context.type, ir.intent, undefined);\n    const declared = matchingIntents.find(i => i.appId == target.appId);\n\n    if (declared) {\n      // maybe listener hasn't been registered yet - create a pending intent\n      const pi = new PendingIntent(ir, sc, this, target);\n      this.pendingIntents.add(pi);\n    } else {\n      errorResponseId(sc, ir.requestUuid, ir.from, ResolveError.NoAppsFound, ir.type);\n    }\n  }\n\n  async raiseIntentRequestToSpecificAppId(\n    arg0: IntentRequest[],\n    sc: ServerContext<AppRegistration>,\n    target: AppIdentifier\n  ): Promise<void> {\n    const appRecords = this.directory.retrieveAppsById(target.appId);\n    if (appRecords.length == 0) {\n      return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.TargetAppUnavailable, arg0[0].type);\n    }\n\n    const convertDirectoryIntentsToAppIntents = (intents: DirectoryIntent[], appId: string): AppIntent[] => {\n      // group by intent name\n      const intentNames = new Set(intents.map(i => i.intentName));\n      return Array.from(intentNames).map(intentName => {\n        const intentsWithName = intents.filter(i => i.intentName === intentName);\n        return {\n          intent: { name: intentName, displayName: intentName },\n          apps: intentsWithName.filter(i => i.appId === appId).map(i => ({ appId: i.appId })),\n        };\n      });\n    };\n\n    const intentsAllHaveApps = (appIntents: AppIntent[]): boolean => {\n      return appIntents.every(ai => ai.apps.length > 0);\n    };\n\n    // in this version of the method, we always open an app as no\n    // specific instance is specified.  But only if the app supports the intent.\n    const context: Context = arg0[0].context;\n    const matchingIntents: DirectoryIntent[] = this.directory.retrieveIntents(context.type, arg0[0].intent, undefined);\n    const appIntents = convertDirectoryIntentsToAppIntents(matchingIntents, target.appId);\n\n    if (appIntents.length == 0) {\n      return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.NoAppsFound, arg0[0].type);\n    }\n\n    if (!intentsAllHaveApps(appIntents)) {\n      return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.IntentDeliveryFailed, arg0[0].type);\n    }\n\n    const narrowedAppIntents = await this.narrowIntents(arg0[0].from, appIntents, context, sc);\n\n    if (narrowedAppIntents.length == 1) {\n      if (narrowedAppIntents[0].apps.length == 1) {\n        // no running instance, single app\n        const appRecords = this.directory.retrieveAppsById(target.appId);\n        if (appRecords.length >= 1) {\n          const ir: IntentRequest = {\n            ...arg0[0],\n            intent: narrowedAppIntents[0].intent.name,\n          };\n          return this.startWithPendingIntent(ir, sc, target);\n        }\n      }\n    }\n    // app doesn't exist\n    return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.NoAppsFound, arg0[0].type);\n  }\n\n  oneAppOnly(appIntent: AppIntent): boolean {\n    const apps = appIntent.apps.map(a => a.appId);\n    const uniqueApps = apps.filter((v, i, a) => a.indexOf(v) === i).length;\n    return uniqueApps == 1;\n  }\n\n  async raiseIntentToAnyApp(arg0: IntentRequest[], sc: ServerContext<AppRegistration>): Promise<void> {\n    const connectedApps = await sc.getConnectedApps();\n    const matchingIntents = arg0.flatMap(i => this.directory.retrieveIntents(i.context.type, i.intent, undefined));\n    const matchingRegistrations = arg0.flatMap(i => this.registrations.filter(r => r.intentName == i.intent));\n    const uniqueIntentNames = [\n      ...matchingIntents.map(i => i.intentName),\n      ...matchingRegistrations.map(r => r.intentName),\n    ].filter((v, i, a) => a.indexOf(v) === i);\n\n    const allIntents = this.directory.retrieveAllIntents();\n\n    const appIntents: AppIntent[] = uniqueIntentNames.map(i => {\n      const directoryAppsWithIntent = matchingIntents.filter(mi => mi.intentName == i).map(mi => mi.appId);\n      const runningDirectoryApps = connectedApps.filter(ca => directoryAppsWithIntent.includes(ca.appId));\n      const appRegistrations = matchingRegistrations\n        .filter(registration => registration.intentName === i) // filter registrations for the current intent\n        .map(listener => ({ appId: listener.appId, instanceId: listener.instanceId, state: State.Connected }))\n        .filter(appRegistration => allIntents.every(intent => intent.appId !== appRegistration.appId)); // filter out apps that have intents registered in the directory\n\n      const runningApps: AppRegistration[] = [...runningDirectoryApps, ...appRegistrations];\n\n      return {\n        intent: {\n          name: i,\n          displayName: i,\n        },\n        apps: [\n          ...runningApps,\n          ...directoryAppsWithIntent.map(d => {\n            return { appId: d };\n          }),\n        ],\n      };\n    });\n\n    const narrowedAppIntents = await this.narrowIntents(arg0[0].from, appIntents, arg0[0].context, sc);\n\n    if (narrowedAppIntents.length == 0) {\n      // nothing can resolve the intent, fail\n      return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.NoAppsFound, arg0[0].type);\n    }\n\n    if (narrowedAppIntents.length == 1) {\n      const theAppIntent = narrowedAppIntents[0];\n      if (this.oneAppOnly(theAppIntent)) {\n        const instanceCount = theAppIntent.apps.filter(a => a.instanceId).length;\n        const ir: IntentRequest = {\n          ...arg0[0],\n          intent: narrowedAppIntents[0].intent.name,\n        };\n        if (instanceCount == 1 && isFullAppIdentifier(theAppIntent.apps[0])) {\n          // app is running\n          return forwardRequest(ir, theAppIntent.apps[0], sc, this);\n        } else if (instanceCount == 0) {\n          return this.startWithPendingIntent(ir, sc, theAppIntent.apps[0]);\n        }\n      }\n    }\n\n    if (arg0[0].type == 'raiseIntentResponse') {\n      // raise intent\n      return successResponseId(\n        sc,\n        arg0[0].requestUuid,\n        arg0[0].from,\n        {\n          appIntent: narrowedAppIntents[0],\n        },\n        arg0[0].type\n      );\n    } else {\n      // raise intent for context\n      return successResponseId(sc, arg0[0].requestUuid, arg0[0].from, { appIntents: narrowedAppIntents }, arg0[0].type);\n    }\n  }\n\n  async raiseIntentRequest(\n    arg0: RaiseIntentRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): Promise<void> {\n    const intentRequest: IntentRequest = {\n      context: arg0.payload.context,\n      from,\n      intent: arg0.payload.intent,\n      requestUuid: arg0.meta.requestUuid,\n      type: 'raiseIntentResponse',\n    };\n\n    const target = arg0.payload.app;\n    if (target) {\n      if (isFullAppIdentifier(target)) {\n        return this.raiseIntentRequestToSpecificInstance([intentRequest], sc, target);\n      } else if (target.appId) {\n        return this.raiseIntentRequestToSpecificAppId([intentRequest], sc, target);\n      } else {\n        //invalid target\n        console.warn('Received an invalid target argument for raiseIntent', target, arg0);\n        return errorResponseId(\n          sc,\n          arg0.meta.requestUuid,\n          from,\n          ResolveError.TargetAppUnavailable,\n          'raiseIntentResponse'\n        );\n      }\n    } else {\n      //No target\n      return this.raiseIntentToAnyApp([intentRequest], sc);\n    }\n  }\n\n  async raiseIntentForContextRequest(\n    arg0: RaiseIntentForContextRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): Promise<void> {\n    // dealing with a specific instance of an app\n    const mappedIntents = this.directory.retrieveIntents(arg0.payload.context.type, undefined, undefined);\n    const uniqueIntentNames = mappedIntents.filter((v, i, a) => a.findIndex(v2 => v2.intentName == v.intentName) == i);\n    const possibleIntentRequests: IntentRequest[] = uniqueIntentNames.map(i => {\n      return {\n        context: arg0.payload.context,\n        from,\n        intent: i.intentName,\n        requestUuid: arg0.meta.requestUuid,\n        type: 'raiseIntentForContextResponse',\n      };\n    });\n\n    if (possibleIntentRequests.length == 0) {\n      return errorResponseId(\n        sc,\n        arg0.meta.requestUuid,\n        from,\n        ResolveError.NoAppsFound,\n        'raiseIntentForContextResponse'\n      );\n    }\n\n    const target = arg0.payload.app;\n    if (target) {\n      if (isFullAppIdentifier(target)) {\n        return this.raiseIntentRequestToSpecificInstance(possibleIntentRequests, sc, target);\n      } else if (target.appId) {\n        return this.raiseIntentRequestToSpecificAppId(possibleIntentRequests, sc, target);\n      } else {\n        //invalid target\n        console.warn('Received an invalid target argument for raiseIntentForContext', target, arg0);\n        return errorResponseId(\n          sc,\n          arg0.meta.requestUuid,\n          from,\n          ResolveError.TargetAppUnavailable,\n          'raiseIntentForContextResponse'\n        );\n      }\n    } else {\n      //No target\n      return this.raiseIntentToAnyApp(possibleIntentRequests, sc);\n    }\n  }\n\n  async findIntentsByContextRequest(\n    r: FindIntentsByContextRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): Promise<void> {\n    const { context, resultType } = r.payload;\n\n    const apps1 = this.directory.retrieveIntents(context?.type, undefined, resultType);\n\n    // fold apps so same intents aren't duplicated\n    const apps2: AppIntent[] = [];\n    //don't use foreach as the handling function is async and needs to process serially\n    for (let index = 0; index < apps1.length; index++) {\n      const a1 = apps1[index];\n      const existing = apps2.find(a2 => a2.intent.name == a1.intentName);\n      const runningInstances = await this.retrieveRunningInstances(a1.appId, sc);\n      if (existing) {\n        existing.apps.push({ appId: a1.appId });\n        runningInstances.forEach(ri => existing.apps.push({ appId: a1.appId, instanceId: ri.instanceId }));\n      } else {\n        const appIntent: AppIntent = {\n          intent: {\n            name: a1.intentName,\n            displayName: a1.displayName ?? a1.intentName,\n          },\n          apps: [\n            {\n              appId: a1.appId,\n            },\n          ],\n        };\n        runningInstances.forEach(ri => appIntent.apps.push({ appId: a1.appId, instanceId: ri.instanceId }));\n        apps2.push(appIntent);\n      }\n    }\n\n    successResponse(\n      sc,\n      r,\n      from,\n      {\n        appIntents: apps2,\n      },\n      'findIntentsByContextResponse'\n    );\n  }\n\n  async findIntentRequest(\n    r: FindIntentRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): Promise<void> {\n    const { intent, context, resultType } = r.payload;\n\n    // listeners for connected applications\n    const apps2 = (await this.retrieveListeners(intent, sc)).map(lr => {\n      return {\n        appId: lr.appId,\n        instanceId: lr.instanceId,\n      };\n    }) as AppIdentifier[];\n\n    // directory entries\n    const apps1 = this.directory.retrieveApps(context?.type, intent, resultType).map(a => {\n      return {\n        appId: a.appId,\n      };\n    });\n\n    //combine the lists, no need to de-duplicate as we should return both a directory record with just appId + any instance with appId/instanceId\n    const finalApps = [...apps1, ...apps2];\n\n    // just need this for the (deprecated) display name\n    const allMatchingIntents = this.directory.retrieveIntents(context?.type, intent, resultType);\n    const displayName = allMatchingIntents.length > 0 ? allMatchingIntents[0].displayName : undefined;\n\n    successResponse(\n      sc,\n      r,\n      from,\n      {\n        appIntent: {\n          intent: {\n            name: intent,\n            displayName,\n          },\n          apps: finalApps,\n        },\n      },\n      'findIntentResponse'\n    );\n  }\n\n  async retrieveListeners(\n    intentName: string | undefined,\n    sc: ServerContext<AppRegistration>\n  ): Promise<ListenerRegistration[]> {\n    const activeApps = await sc.getConnectedApps();\n    const matching = this.registrations.filter(r => r.intentName == intentName);\n    const active = matching.filter(r => activeApps.find(a => a.instanceId == r.instanceId));\n    return active;\n  }\n\n  async retrieveRunningInstances(appId: string, sc: ServerContext<AppRegistration>) {\n    const activeApps = await sc.getConnectedApps();\n    const filteredApps = activeApps.filter(a => a.appId === appId);\n    return filteredApps;\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts",
    "content": "import { MessageHandler } from '../BasicFDC3Server.js';\nimport { AppRegistration, InstanceID, ServerContext, State } from '../ServerContext.js';\nimport { Directory, DirectoryApp } from '../directory/DirectoryInterface.js';\nimport { ContextElement } from '@finos/fdc3-context';\nimport { OpenError, ResolveError, AppIdentifier, AppMetadata, ImplementationMetadata } from '@finos/fdc3-standard';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { errorResponse, FullAppIdentifier, successResponse } from './support.js';\nimport {\n  AgentResponseMessage,\n  AppRequestMessage,\n  GetInfoRequest,\n  isAddContextListenerRequest,\n  isFindInstancesRequest,\n  isGetAppMetadataRequest,\n  isGetInfoRequest,\n  isOpenRequest,\n  isWebConnectionProtocol4ValidateAppIdentity,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype BroadcastEvent = BrowserTypes.BroadcastEvent;\ntype AddContextListenerRequest = BrowserTypes.AddContextListenerRequest;\ntype FindInstancesRequest = BrowserTypes.FindInstancesRequest;\ntype GetAppMetadataRequest = BrowserTypes.GetAppMetadataRequest;\ntype OpenRequest = BrowserTypes.OpenRequest;\ntype WebConnectionProtocol4ValidateAppIdentity = BrowserTypes.WebConnectionProtocol4ValidateAppIdentity;\ntype WebConnectionProtocol5ValidateAppIdentityFailedResponse =\n  BrowserTypes.WebConnectionProtocol5ValidateAppIdentityFailedResponse;\ntype WebConnectionProtocol5ValidateAppIdentitySuccessResponse =\n  BrowserTypes.WebConnectionProtocol5ValidateAppIdentitySuccessResponse;\n\nenum AppState {\n  Opening,\n  DeliveringContext,\n  Done,\n}\n\nclass PendingApp {\n  private readonly sc: ServerContext<AppRegistration>;\n  private readonly msg: OpenRequest;\n  readonly context: ContextElement | undefined;\n  readonly source: FullAppIdentifier;\n  state: AppState = AppState.Opening;\n  private openedApp: AppIdentifier | undefined = undefined;\n\n  constructor(\n    sc: ServerContext<AppRegistration>,\n    msg: OpenRequest,\n    context: ContextElement | undefined,\n    source: FullAppIdentifier,\n    timeoutMs: number\n  ) {\n    this.context = context;\n    this.source = source;\n    this.sc = sc;\n    this.msg = msg;\n\n    setTimeout(() => {\n      if (this.state != AppState.Done) {\n        this.onError();\n      }\n    }, timeoutMs);\n  }\n\n  private onSuccess() {\n    this.sc.setAppState(this.openedApp!.instanceId!, State.Connected);\n    successResponse(\n      this.sc,\n      this.msg,\n      this.source,\n      {\n        appIdentifier: {\n          appId: this.openedApp!.appId,\n          instanceId: this.openedApp!.instanceId,\n        },\n      },\n      'openResponse'\n    );\n  }\n\n  private onError() {\n    errorResponse(this.sc, this.msg, this.source, OpenError.AppTimeout, 'openResponse');\n  }\n\n  setOpened(openedApp: AppIdentifier) {\n    this.openedApp = openedApp;\n    if (this.context) {\n      this.state = AppState.DeliveringContext;\n    } else {\n      this.setDone();\n    }\n  }\n\n  setDone() {\n    this.state = AppState.Done;\n    this.onSuccess();\n  }\n}\n\nexport class OpenHandler implements MessageHandler {\n  private readonly directory: Directory;\n  readonly pending: Map<InstanceID, PendingApp> = new Map();\n  readonly timeoutMs: number;\n\n  constructor(d: Directory, timeoutMs: number) {\n    this.directory = d;\n    this.timeoutMs = timeoutMs;\n  }\n\n  cleanup(/*instanceId: InstanceID, sc: ServerContext<AppRegistration>*/): void {\n    //don't cleanup pending if the opening app closes as we should still deliver context\n  }\n\n  shutdown(): void {}\n\n  async accept(\n    msg: AppRequestMessage | WebConnectionProtocol4ValidateAppIdentity,\n    sc: ServerContext<AppRegistration>,\n    uuid: InstanceID\n  ): Promise<void> {\n    if (isWebConnectionProtocol4ValidateAppIdentity(msg)) {\n      return this.handleValidate(msg as WebConnectionProtocol4ValidateAppIdentity, sc, uuid);\n    } else if (isAddContextListenerRequest(msg)) {\n      //handle context listener adds for pending applications (i.e. opened but awaiting context listener addition to deliver context)\n      //  additional handling is performed in BroadcastHandler\n      return this.handleAddContextListener(msg as AddContextListenerRequest, sc, uuid);\n    } else {\n      const from = sc.getInstanceDetails(uuid);\n      if (from) {\n        try {\n          if (isOpenRequest(msg)) {\n            return this.open(msg, sc, from);\n          } else if (isFindInstancesRequest(msg)) {\n            return this.findInstances(msg, sc, from);\n          } else if (isGetAppMetadataRequest(msg)) {\n            return this.getAppMetadata(msg, sc, from);\n          } else if (isGetInfoRequest(msg)) {\n            return this.getInfo(msg, sc, from);\n          }\n        } catch (e) {\n          const responseType = msg.type.replace(new RegExp('Request$'), 'Response') as AgentResponseMessage['type'];\n          errorResponse(sc, msg, from, (e as Error).message ?? e, responseType);\n        }\n      } else {\n        console.warn('Received message from unknown source, ignoring', msg, uuid);\n      }\n    }\n  }\n\n  /**\n   * This deals with sending pending context to listeners of newly-opened apps.\n   */\n  handleAddContextListener(\n    arg0: AddContextListenerRequest,\n    sc: ServerContext<AppRegistration>,\n    from: InstanceID\n  ): void {\n    const pendingOpen = this.pending.get(from);\n    if (pendingOpen) {\n      const contextType = arg0.payload.contextType;\n      if (pendingOpen.context && pendingOpen.state == AppState.DeliveringContext) {\n        if (contextType == pendingOpen.context.type || contextType == undefined) {\n          // ok, we can deliver to this listener\n          const message: BroadcastEvent = {\n            meta: {\n              eventUuid: sc.createUUID(),\n              timestamp: new Date(),\n            },\n            type: 'broadcastEvent',\n            payload: {\n              channelId: null,\n              context: pendingOpen.context,\n              originatingApp: {\n                appId: pendingOpen.source.appId,\n                instanceId: pendingOpen.source.instanceId,\n              },\n            },\n          };\n\n          pendingOpen.setDone();\n          this.pending.delete(from);\n          sc.post(message, from);\n        }\n      }\n    }\n  }\n\n  filterPublicDetails(appD: DirectoryApp, appID: AppIdentifier): AppMetadata {\n    return {\n      appId: appD.appId,\n      name: appD.name,\n      version: appD.version,\n      title: appD.title,\n      tooltip: appD.tooltip,\n      description: appD.description,\n      icons: appD.icons,\n      screenshots: appD.screenshots,\n      instanceId: appID.instanceId,\n    };\n  }\n\n  getAppMetadata(arg0: GetAppMetadataRequest, sc: ServerContext<AppRegistration>, from: FullAppIdentifier): void {\n    const appID = arg0.payload.app;\n    const details = this.directory.retrieveAppsById(appID.appId);\n    if (details.length > 0) {\n      successResponse(\n        sc,\n        arg0,\n        from,\n        {\n          appMetadata: this.filterPublicDetails(details[0], appID),\n        },\n        'getAppMetadataResponse'\n      );\n    } else {\n      errorResponse(sc, arg0, from, ResolveError.TargetAppUnavailable, 'getAppMetadataResponse');\n    }\n  }\n\n  async findInstances(\n    arg0: FindInstancesRequest,\n    sc: ServerContext<AppRegistration>,\n    from: FullAppIdentifier\n  ): Promise<void> {\n    const appId = arg0.payload.app.appId;\n    const openApps = await sc.getConnectedApps();\n    const matching = openApps\n      .filter(a => a.appId == appId)\n      .map(a => {\n        return {\n          appId: a.appId,\n          instanceId: a.instanceId,\n        };\n      });\n    successResponse(\n      sc,\n      arg0,\n      from,\n      {\n        appIdentifiers: matching,\n      },\n      'findInstancesResponse'\n    );\n  }\n\n  async open(arg0: OpenRequest, sc: ServerContext<AppRegistration>, from: FullAppIdentifier): Promise<void> {\n    const toOpen = arg0.payload.app;\n    const context = arg0.payload.context;\n\n    try {\n      const uuid = await sc.open(toOpen.appId, from);\n      this.pending.set(uuid, new PendingApp(sc, arg0, context, from, this.timeoutMs));\n    } catch (e) {\n      errorResponse(sc, arg0, from, (e as Error).message ?? e, 'openResponse');\n    }\n  }\n\n  async getInfo(arg0: GetInfoRequest, sc: ServerContext<AppRegistration>, from: FullAppIdentifier): Promise<void> {\n    const implMetadata: ImplementationMetadata = this.getImplementationMetadata(sc, {\n      appId: from.appId,\n      instanceId: from.instanceId,\n    });\n    successResponse(\n      sc,\n      arg0,\n      from,\n      {\n        implementationMetadata: implMetadata,\n      },\n      'getInfoResponse'\n    );\n  }\n\n  getImplementationMetadata(sc: ServerContext<AppRegistration>, appIdentity: AppIdentifier) {\n    const appMetadata = this.filterPublicDetails(this.directory.retrieveAppsById(appIdentity.appId)[0], appIdentity);\n    return {\n      provider: sc.provider(),\n      providerVersion: sc.providerVersion(),\n      fdc3Version: sc.fdc3Version(),\n      optionalFeatures: {\n        DesktopAgentBridging: false,\n        OriginatingAppMetadata: true,\n        UserChannelMembershipAPIs: true,\n      },\n      appMetadata: appMetadata,\n    };\n  }\n\n  async handleValidate(\n    arg0: WebConnectionProtocol4ValidateAppIdentity,\n    sc: ServerContext<AppRegistration>,\n    from: InstanceID\n  ): Promise<void> {\n    const responseMeta = {\n      connectionAttemptUuid: arg0.meta.connectionAttemptUuid,\n      timestamp: new Date(),\n    };\n\n    const returnError = () => {\n      const msg: WebConnectionProtocol5ValidateAppIdentityFailedResponse = {\n        meta: responseMeta,\n        type: 'WCP5ValidateAppIdentityFailedResponse',\n        payload: {\n          message: 'App Instance not found',\n        },\n      };\n      sc.post(msg, from);\n    };\n\n    const returnSuccess = (appId: string, instanceId: string) => {\n      const implMetadata: ImplementationMetadata = this.getImplementationMetadata(sc, { appId, instanceId });\n      const msg: WebConnectionProtocol5ValidateAppIdentitySuccessResponse = {\n        meta: responseMeta,\n        type: 'WCP5ValidateAppIdentityResponse',\n        payload: {\n          appId: appId,\n          instanceId: instanceId,\n          instanceUuid: from,\n          implementationMetadata: implMetadata,\n        },\n      };\n      sc.post(msg, instanceId);\n    };\n\n    if (arg0.payload.instanceUuid) {\n      // existing app reconnecting\n      console.debug('App attempting to reconnect:', arg0.payload.instanceUuid);\n      const appIdentity = sc.getInstanceDetails(arg0.payload.instanceUuid);\n\n      if (appIdentity) {\n        // in this case, the app is reconnecting, so let's just re-assign the identity\n        console.debug(\n          `Reassigned existing identity, appId: `,\n          appIdentity.appId,\n          ', instanceId',\n          arg0.payload.instanceUuid\n        );\n        sc.setInstanceDetails(from, appIdentity);\n        sc.setAppState(from, State.Connected);\n        return returnSuccess(appIdentity.appId, appIdentity.instanceId);\n      } else {\n        //we didn't find the identity, assign a new one\n        console.debug('Existing identity not found for, assigning a new one: ', arg0.payload.instanceUuid);\n      }\n    }\n\n    // we need to assign an identity to this app - this should have been generated when it was launched\n    const appIdentity = sc.getInstanceDetails(from);\n    if (appIdentity) {\n      sc.setAppState(appIdentity.instanceId, State.Connected);\n      returnSuccess(appIdentity.appId, appIdentity.instanceId);\n\n      // make sure, if the opener is listening for this app to open, then it gets informed\n      const pendingOpen = this.pending.get(from);\n      if (pendingOpen) {\n        if (pendingOpen.state == AppState.Opening) {\n          pendingOpen.setOpened(appIdentity);\n        }\n      }\n    } else {\n      returnError();\n    }\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts",
    "content": "import { AgentResponseMessage, AppRequestMessage } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { AppRegistration, ServerContext } from '../ServerContext.js';\nimport { AppIdentifier } from '@finos/fdc3-standard';\n\n/** Interface representing a full specified app identifier (instanceId is optional in the API type). */\nexport interface FullAppIdentifier {\n  readonly appId: string;\n  readonly instanceId: string;\n}\n\nexport function isFullAppIdentifier(identifier: AppIdentifier | FullAppIdentifier): identifier is FullAppIdentifier {\n  const typedIdentifier = identifier as FullAppIdentifier;\n  return typedIdentifier.instanceId !== undefined && typedIdentifier.appId !== undefined;\n}\n\nexport function successResponse(\n  sc: ServerContext<AppRegistration>,\n  request: AppRequestMessage,\n  to: FullAppIdentifier,\n  payload: AgentResponseMessage['payload'],\n  type: AgentResponseMessage['type']\n) {\n  return successResponseId(sc, request.meta.requestUuid, to, payload, type);\n}\n\nexport function errorResponse(\n  sc: ServerContext<AppRegistration>,\n  request: AppRequestMessage,\n  to: FullAppIdentifier,\n  error: string,\n  type: AgentResponseMessage['type']\n) {\n  return errorResponseId(sc, request.meta.requestUuid, to, error, type);\n}\n\nexport function successResponseId(\n  sc: ServerContext<AppRegistration>,\n  requestId: string,\n  to: FullAppIdentifier,\n  payload: AgentResponseMessage['payload'],\n  type: AgentResponseMessage['type']\n) {\n  const msg = {\n    meta: {\n      responseUuid: sc.createUUID(),\n      requestUuid: requestId,\n      timestamp: new Date(),\n    },\n    type,\n    payload,\n  };\n  sc.post(msg, to.instanceId!);\n}\n\nexport function errorResponseId(\n  sc: ServerContext<AppRegistration>,\n  requestId: string,\n  to: FullAppIdentifier,\n  error: string,\n  type: AgentResponseMessage['type']\n) {\n  sc.post(\n    {\n      meta: {\n        responseUuid: sc.createUUID(),\n        requestUuid: requestId,\n        timestamp: new Date(),\n      },\n      type,\n      payload: {\n        error,\n      },\n    } as AgentResponseMessage,\n    to.instanceId!\n  );\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/src/index.ts",
    "content": "import { ServerContext, InstanceID, State, AppRegistration } from './ServerContext.js';\nimport { BasicFDC3Server, DefaultFDC3Server } from './BasicFDC3Server.js';\nimport { FDC3Server } from './FDC3Server.js';\nimport { Directory, DirectoryApp, DirectoryIntent, WebAppDetails } from './directory/DirectoryInterface.js';\nimport { BasicDirectory } from './directory/BasicDirectory.js';\nimport { BroadcastHandler, ChannelState, ChannelType } from './handlers/BroadcastHandler.js';\nimport { IntentHandler } from './handlers/IntentHandler.js';\nimport { OpenHandler } from './handlers/OpenHandler.js';\n\nexport {\n  type InstanceID,\n  type ServerContext,\n  State,\n  type AppRegistration,\n  BasicFDC3Server,\n  DefaultFDC3Server,\n  type FDC3Server,\n  type Directory,\n  BasicDirectory,\n  type DirectoryApp,\n  type DirectoryIntent,\n  BroadcastHandler,\n  ChannelState,\n  IntentHandler,\n  OpenHandler,\n  ChannelType,\n  type WebAppDetails,\n};\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/apps.feature",
    "content": "Feature: Opening and Requesting App Details\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | returnBook  | fdc3.book    | {empty}     |\n    And \"storageApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | loanBook    | fdc3.book    | fdc3.loan   |\n    And A newly instantiated FDC3 Server\n    And \"libraryApp/a1\" is opened with connection id \"a1\"\n\n  Scenario: Looking up app metadata\n    When \"libraryApp/a1\" requests metadata for \"storageApp\"\n    Then messaging will have outgoing posts\n      | msg.payload.appMetadata.appId | to.instanceId | msg.matches_type       |\n      | storageApp                    | a1            | getAppMetadataResponse |\n\n  Scenario: Looking up app metadata from missing app\n    When \"libraryApp/a1\" requests metadata for \"unknownApp\"\n    Then messaging will have outgoing posts\n      | msg.payload.error    | to.instanceId | msg.type               |\n      | TargetAppUnavailable | a1            | getAppMetadataResponse |\n\n  Scenario: Looking up DesktopAgent metadata\n    When \"libraryApp/a1\" requests info on the DesktopAgent\n    Then messaging will have outgoing posts\n      | msg.payload.implementationMetadata.provider | to.instanceId | msg.matches_type       |\n      | cucumber-provider                           | a1            | getInfoResponse        |\n\n  Scenario: Opening An App\n    When \"libraryApp/a1\" opens app \"storageApp\"\n    And \"uuid-0\" sends validate\n    Then messaging will have outgoing posts\n      | msg.matches_type                | msg.payload.appIdentifier.appId | msg.payload.appIdentifier.instanceId | msg.payload.appId | msg.payload.instanceId | to.instanceId | to.appId   |\n      | WCP5ValidateAppIdentityResponse | {null}                          | {null}                               | storageApp        | uuid-0                 | uuid-0        | storageApp |\n      | openResponse                    | storageApp                      | uuid-0                               | {null}            | {null}                 | a1            | libraryApp |\n\n  Scenario: Storage App Reconnects\n    When \"libraryApp/a1\" opens app \"storageApp\"\n    And \"uuid-0\" sends validate\n    And we wait for a period of \"100\" ms\n    And \"uuid-0\" revalidates\n    Then messaging will have outgoing posts\n      | msg.matches_type                | msg.payload.appIdentifier.appId | msg.payload.appIdentifier.instanceId | msg.payload.appId | msg.payload.instanceId | to.instanceId | to.appId   |\n      | WCP5ValidateAppIdentityResponse | {null}                          | {null}                               | storageApp        | uuid-0                 | uuid-0        | storageApp |\n      | openResponse                    | storageApp                      | uuid-0                               | {null}            | {null}                 | a1            | libraryApp |\n      | WCP5ValidateAppIdentityResponse | {null}                          | {null}                               | storageApp        | uuid-0                 | uuid-0        | storageApp |\n\n  Scenario: Opening An App With Context\n    When \"libraryApp/a1\" opens app \"storageApp\" with context data \"fdc3.instrument\"\n    And \"uuid-0\" sends validate\n    And we wait for a period of \"100\" ms\n    And \"storageApp/uuid-0\" adds a context listener on \"{null}\" with type \"fdc3.instrument\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                | msg.payload.channelId | msg.payload.context.type | to.instanceId | to.appId   | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | WCP5ValidateAppIdentityResponse | {null}                | {null}                   | uuid-0        | storageApp | {null}                           | {null}                                |\n      | addContextListenerResponse      | {empty}               | {empty}                  | uuid-0        | storageApp | {null}                           | {null}                                |\n      | openResponse                    | {empty}               | {empty}                  | a1            | libraryApp | {null}                           | {null}                                |\n      | broadcastEvent                  | {null}                | fdc3.instrument          | uuid-0        | storageApp | libraryApp                       | a1                                    |\n\n  Scenario: Opening An App With Context, But No Listener Added\n    When \"libraryApp/a1\" opens app \"storageApp\" with context data \"fdc3.instrument\"\n    And \"uuid-0\" sends validate\n    And we wait for the listener timeout\n    Then messaging will have outgoing posts\n      | msg.type                        | msg.payload.error | to.instanceId | to.appId   |\n      | WCP5ValidateAppIdentityResponse | {null}            | uuid-0        | storageApp |\n      | openResponse                    | AppTimeout        | a1            | libraryApp |\n\n  Scenario: Opening A Missing App\n    When \"libraryApp/a1\" opens app \"missingApp\"\n    Then messaging will have outgoing posts\n      | msg.type     | msg.payload.error | to.instanceId |\n      | openResponse | AppNotFound       | a1            |\n\n  Scenario: Find Instances with No Apps Running\n    And \"libraryApp/a1\" findsInstances of \"App1\"\n    Then messaging will have outgoing posts\n      | msg.matches_type      | msg.payload.appIdentifiers.length | to.instanceId |\n      | findInstancesResponse |                                 0 | a1            |\n\n  Scenario: Find Instances with Some Apps Running\n    When \"storageApp/b1\" is opened with connection id \"b1\"\n    And \"storageApp/b2\" is opened with connection id \"b2\"\n    And \"libraryApp/a1\" findsInstances of \"storageApp\"\n    And we wait for a period of \"100\" ms\n    Then messaging will have outgoing posts\n      | msg.matches_type      | msg.payload.appIdentifiers.length | msg.payload.appIdentifiers[0].instanceId | msg.payload.appIdentifiers[1].instanceId | to.instanceId | msg.payload.appId |\n      | findInstancesResponse |                                 2 | b1                                       | b2                                       | a1            | {null}            |\n\n  Scenario: Unknown App Attempts Reconnect\n    When \"uuid-0\" revalidates\n    Then messaging will have outgoing posts\n      | msg.type                              | msg.payload.message    |\n      | WCP5ValidateAppIdentityFailedResponse | App Instance not found |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/broadcast.feature",
    "content": "Feature: Relaying Broadcast messages\n\n  Background:\n    Given schemas loaded\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"App2/a2\" is opened with connection id \"a2\"\n\n  Scenario: Broadcast message to no-one\n    When \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type  |\n      | broadcastResponse |\n    And messaging will have 1 posts\n\n  Scenario: Broadcast message sent to one listener\n    When \"App2/a2\" adds a context listener on \"one\" with type \"fdc3.instrument\"\n    And we wait for a period of \"100\" ms\n    And \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.appId | to.instanceId | msg.payload.channelId | msg.payload.context.type | msg.payload.context.id.ticker | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | addContextListenerResponse | App2     | a2            | {null}                | {null}                   | {null}                        | {null}                           | {null}                                |\n      | broadcastEvent             | App2     | a2            | one                   | fdc3.instrument          | AAPL                          | App1                             | a1                                    |\n      | broadcastResponse          | App1     | a1            | {null}                | {null}                   | {null}                        | {null}                           | {null}                                |\n\n  Scenario: Broadcast message sent but listener has unsubscribed\n    When \"App2/a2\" adds a context listener on \"one\" with type \"fdc3.instrument\"\n    And \"App2/a2\" removes context listener with id \"uuid3\"\n    And \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                   | to.appId | to.instanceId | msg.payload.listenerUUID |\n      | addContextListenerResponse         | App2     | a2            | uuid3                    |\n      | contextListenerUnsubscribeResponse | App2     | a2            | {null}                   |\n      | broadcastResponse                  | App1     | a1            | {null}                   |\n\n  Scenario: Retrieve an existing user channel via getOrCreateChannel\n    When \"App1/a1\" creates or gets an app channel called \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.instanceId | msg.payload.channel.id | msg.payload.channel.type | msg.payload.error |\n      | getOrCreateChannelResponse | a1            | one                    | user                     | {null}            |\n\n  Scenario: Retrieve a new app channel via getOrCreateChannel\n    When \"App1/a1\" creates or gets an app channel called \"myAppChannel\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.instanceId | msg.payload.channel.id | msg.payload.channel.type | msg.payload.error |\n      | getOrCreateChannelResponse | a1            | myAppChannel           | app                      | {null}            |\n\n  Scenario: Get The Latest Context From A Channel\n    Given \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    And \"App1/a1\" asks for the latest context on \"one\" with type \"fdc3.instrument\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | to.appId | to.instanceId | msg.payload.context.id.ticker | msg.payload.context.type |\n      | getCurrentContextResponse | App1     | a1            | AAPL                          | fdc3.instrument          |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/disconnect-cleanup.feature",
    "content": "Feature: App Disconnection and Cleanup\n\n  Background:\n    Given schemas loaded\n\n  Scenario: Apps that disconnect and reconnect to the DA should receive one copy of a broadcast message from an app channel as state was cleaned up\n    Given A newly instantiated FDC3 Server\n    When \"App1/a1\" is opened with connection id \"a1\"\n    And \"App2/a2\" is opened with connection id \"a2\"\n    And \"App2/a2\" adds a context listener on \"one\" with type \"fdc3.instrument\"\n    And we wait for a period of \"100\" ms\n    And \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.appId | to.instanceId | msg.payload.channelId | msg.payload.context.type | msg.payload.context.id.ticker |\n      | addContextListenerResponse | App2     | a2            | {null}                | {null}                   | {null}                        |\n      | broadcastEvent             | App2     | a2            | one                   | fdc3.instrument          | AAPL                          |\n      | broadcastResponse          | App1     | a1            | {null}                | {null}                   | {null}                        |\n    And \"App2/a2\" is closed\n    And \"App2/a2\" is opened with connection id \"a2\"\n    And \"App2/a2\" adds a context listener on \"one\" with type \"fdc3.instrument\"\n    And we wait for a period of \"100\" ms\n    And \"App1/a1\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.appId | to.instanceId | msg.payload.channelId | msg.payload.context.type | msg.payload.context.id.ticker |\n      | addContextListenerResponse | App2     | a2            | {null}                | {null}                   | {null}                        |\n      | broadcastEvent             | App2     | a2            | one                   | fdc3.instrument          | AAPL                          |\n      | broadcastResponse          | App1     | a1            | {null}                | {null}                   | {null}                        |\n  \n\n  Scenario: Apps that disconnect and reconnect to the DA should NOT receive intent results from the previous connection as state was cleaned up\n    Given \"libraryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | returnBook  | fdc3.book    | {empty}     |\n    And \"App1\" is an app with the following intents\n      | Intent Name | Context Type    | Result Type |\n      | viewNews    | fdc3.instrument | {empty}     |\n    And A newly instantiated FDC3 Server\n    When \"LibraryApp/l1\" is opened with connection id \"l1\"\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"LibraryApp/l1\" registers an intent listener for \"returnBook\"\n    And \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"LibraryApp/l1\" with requestUuid \"ABC123\"\n    And we wait for a period of \"100\" ms\n    And \"App1/a1\" is closed\n    And we wait for a period of \"100\" ms\n    And \"LibraryApp/l1\" sends a intentResultRequest with eventUuid \"uuid7\" and contextType \"fdc3.book\" and raiseIntentUuid \"ABC123\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.meta.eventUuid | msg.meta.requestUuid | to.appId   | to.instanceId | msg.payload.raiseIntentRequestUuid | msg.payload.intentResolution.source.instanceId | msg.payload.intentResult.context.type |\n      | intentEvent               | uuid7              | {null}               | LibraryApp | l1            | ABC123                             | {null}                                         | {null}                                |\n      | raiseIntentResponse       | {null}             | ABC123               | App1       | a1            | {null}                             | l1                                             | {null}                                |\n      | intentResultResponse      | {null}             | uuid10               | LibraryApp | l1            | {null}                             | {null}                                         | {null}                                |\n\nScenario: Disconnecting from the DA when subscribed to a private channel channel sends unsubscribe and disconnect messages\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"App2/a2\" is opened with connection id \"a2\"\n    And \"App2/a1\" creates a private channel\n    #TODO: have a2 retrieve the private channel by raising an intent - its currently using a1 reference to the channel\n    And I refer to \"uuid3\" as \"channel1Id\"\n    When \"App2/a2\" adds an \"disconnect\" event listener on \"{channel1Id}\"\n    And \"App1/a1\" adds a context listener on \"{channel1Id}\" with type \"fdc3.instrument\"\n    And \"App2/a2\" adds an \"unsubscribe\" event listener on \"{channel1Id}\"\n    And \"App1/a1\" is closed\n    Then messaging will have outgoing posts\n      | msg.matches_type                 | msg.payload.privateChannelId | msg.payload.contextType | to.appId | to.instanceId |\n      | privateChannelOnUnsubscribeEvent | {channel1Id}                 | fdc3.instrument         | App2     | a2            |\n      | privateChannelOnDisconnectEvent  | {channel1Id}                 | {null}                  | App2     | a2            |"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/event-listeners.feature",
    "content": "Feature: Client can add an event Listener\n\n  Background:\n    Given schemas loaded\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n\n  Scenario: App Adds A typed Event Listener\n    When \"App1/a1\" adds an event listener for \"USER_CHANNEL_CHANGED\"\n    And we wait for a period of \"100\" ms\n    And \"App1/a1\" removes event listener with id \"uuid2\"\n    And we wait for a period of \"100\" ms\n    Then messaging will have outgoing posts\n      | msg.matches_type                 | to.instanceId | to.appId | msg.payload.listenerUUID |\n      | addEventListenerResponse         | a1            | App1     | uuid2                    |\n      | eventListenerUnsubscribeResponse | a1            | App1     | {null}                   |\n\n  Scenario: App Adds An Untyped Event Listener\n    When \"App1/a1\" adds an event listener for \"{null}\"\n    And we wait for a period of \"100\" ms\n    When \"App1/a1\" removes event listener with id \"uuid2\"\n    And we wait for a period of \"100\" ms\n    Then messaging will have outgoing posts\n      | msg.matches_type                 | to.instanceId | to.appId | msg.payload.listenerUUID |\n      | addEventListenerResponse         | a1            | App1     | uuid2                    |\n      | eventListenerUnsubscribeResponse | a1            | App1     | {null}                   |\n\n  Scenario: Unsubscribe a non-existent Event Listener\n    When \"App1/a1\" removes event listener with id \"uuid-na\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                 | to.instanceId | to.appId | msg.payload.error |\n      | eventListenerUnsubscribeResponse | a1            | App1     | ListenerNotFound  |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/find-intent.feature",
    "content": "Feature: Find Intent API\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type      |\n      | loanBook    | fdc3.book    | fdc3.loan        |\n      | streamBook  | fdc3.book    | channel<chapter> |\n      | returnBook  | fdc3.book    | {empty}          |\n      | streamAny   | fdc3.book    | channel          |\n    And \"bakeryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type      |\n      | viewStock   | fdc3.product | {empty}          |\n    And \"butcherApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type      |\n      | viewStock   | fdc3.product | {empty}          |\n    And \"chandlerApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type      |\n      | viewStock   | fdc3.product | {empty}          |\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"App1/b1\" is opened with connection id \"b1\"\n    And \"App1/b1\" registers an intent listener for \"returnBook\"\n    And \"butcherApp/b2\" is opened with connection id \"b2\"\n    And \"butcherApp/b2\" registers an intent listener for \"viewStock\"\n    #first app returned by directory must have an instance to cover all branches in findIntentsByContextRequest\n    And \"bakeryApp/b3\" is opened with connection id \"b3\"\n    And \"bakeryApp/b3\" registers an intent listener for \"viewStock\"\n    And we wait for a period of \"100\" ms\n\n  Scenario: Unsuccessful Find Intents Request\n    When \"App1/a1\" finds intents with intent \"loanBook\" and contextType \"fdc3.instrument\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId |\n      | findIntentResponse | loanBook                          |                                 0 | a1            |\n\n  Scenario: Unsuccessful Find Intents Request With Result Type\n    When \"App1/a1\" finds intents with intent \"loanBook\" and contextType \"{empty}\" and result type \"unknownContext\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId |\n      | findIntentResponse | loanBook                          |                                 0 | a1            |\n\n  Scenario: Successful Find Intents Request\n    When \"App1/a1\" finds intents with intent \"loanBook\" and contextType \"{empty}\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | msg.payload.appIntent.apps[0].appId | to.instanceId | msg.payload.appIntent.intent.displayName |\n      | findIntentResponse | loanBook                          |                                 1 | libraryApp                          | a1            | loan book                                |\n\n  Scenario: Find Intents Requests should include both the app and running instances of it \n    When \"App1/a1\" finds intents with intent \"viewStock\" and contextType \"fdc3.product\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId |\n      | findIntentResponse | viewStock                         |                                 5 | a1            |\n    When \"butcherApp/b2\" is closed\n    And \"App1/a1\" finds intents with intent \"viewStock\" and contextType \"fdc3.product\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId |\n      | findIntentResponse | viewStock                         |                                 4 | a1            |\n\n  Scenario: Find Intents by Context Request\n    When \"App/a1\" finds intents with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.matches_type             | msg.payload.appIntents[0].intent.name | msg.payload.appIntents.length | to.instanceId | msg.payload.appIntents[0].intent.displayName |\n      | findIntentsByContextResponse | loanBook                              |                             4 | a1            | loan book                                    |\n\n  Scenario: Find Intents by Context Request with multiple results\n    When \"App/a1\" finds intents with contextType \"fdc3.product\"\n    Then messaging will have outgoing posts\n      | msg.matches_type             | msg.payload.appIntents[0].intent.name | msg.payload.appIntents.length | to.instanceId | msg.payload.appIntents[0].apps.length |\n      | findIntentsByContextResponse | viewStock                             |                             1 | a1            | 5                                     |\n\n  Scenario: Find Intents by Context Request with multiple results which should not include an instance that has closed\n    When \"butcherApp/b2\" is closed\n    When \"App/a1\" finds intents with contextType \"fdc3.product\"\n    Then messaging will have outgoing posts\n      | msg.matches_type             | msg.payload.appIntents[0].intent.name | msg.payload.appIntents.length | to.instanceId | msg.payload.appIntents[0].apps.length |\n      | findIntentsByContextResponse | viewStock                             |                             1 | a1            | 4                                     |\n\n  Scenario: Successful Find Intents Request With Channel\n    When \"App1/a1\" finds intents with intent \"streamBook\" and contextType \"fdc3.book\" and result type \"channel\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | msg.payload.appIntent.apps[0].appId | to.instanceId |\n      | findIntentResponse | streamBook                        |                                 1 | libraryApp                          | a1            |\n\n  Scenario: Successful Find Intents Request With A Typed Channel\n    When \"App1/a1\" finds intents with intent \"streamBook\" and contextType \"{empty}\" and result type \"channel<chapter>\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | msg.payload.appIntent.apps[0].appId | to.instanceId |\n      | findIntentResponse | streamBook                        |                                 1 | libraryApp                          | a1            |\n\n  Scenario: Unsuccessful Find Intents Request With an untyped Channel\n    When \"App1/a1\" finds intents with intent \"streamAny\" and contextType \"{empty}\" and result type \"channel<spurious>\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length |\n      | findIntentResponse | streamAny                         |                                 0 |\n\n  Scenario: Find Intent includes results for a running app with intent listener\n    When \"App1/a1\" finds intents with intent \"returnBook\" and contextType \"fdc3.book\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId |\n      | findIntentResponse | returnBook                        |                                 2 | a1            |\n    And messaging will have outgoing posts\n      | msg.payload.appIntent.apps[1].appId | msg.payload.appIntent.apps[1].instanceId |\n      | App1                                | b1                                       |\n    And messaging will have outgoing posts\n      | msg.payload.appIntent.apps[0].appId | msg.payload.appIntent.apps[0].instanceId |\n      | libraryApp                          | {empty}                                  |\n\n  Scenario: Disconnecting The Intent Listener\n    When \"App1/b1\" unsubscribes an intent listener with id \"uuid3\"\n    And \"App1/a1\" finds intents with intent \"returnBook\" and contextType \"fdc3.book\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                  | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId | msg.payload.appIntent.apps[0].appId |\n      | intentListenerUnsubscribeResponse | {null}                            | {null}                            | b1            | {null}                              |\n      | findIntentResponse                | returnBook                        |                                 1 | a1            | libraryApp                          |\n\n  Scenario: Find Intent excludes results for a closed app with intent listener\n    When \"App1/b1\" is closed\n    And \"App1/a1\" finds intents with intent \"returnBook\" and contextType \"fdc3.book\" and result type \"{empty}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type   | msg.payload.appIntent.intent.name | msg.payload.appIntent.apps.length | to.instanceId | msg.payload.appIntent.apps[0].appId |\n      | findIntentResponse | returnBook                        |                                 1 | a1            | libraryApp                          |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/heartbeat.feature",
    "content": "Feature: Heartbeat Messages Between Apps and Server\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | returnBook  | fdc3.book    | {empty}     |\n    And A newly instantiated FDC3 Server with heartbeat checking\n\n  Scenario: App Responds to heartbeats\n    When \"libraryApp/a1\" is opened with connection id \"a1\"\n    And \"a1\" sends validate\n    And we wait for a period of \"400\" ms\n    And \"libraryApp/a1\" sends a heartbeat response to eventUuid \"a1_1\"\n    And we wait for a period of \"400\" ms\n    And \"libraryApp/a1\" sends a heartbeat response to eventUuid \"a1_2\"\n    And we wait for a period of \"400\" ms\n    And \"libraryApp/a1\" sends a heartbeat response to eventUuid \"a1_3\"\n    And we wait for a period of \"400\" ms\n    And \"libraryApp/a1\" sends a heartbeat response to eventUuid \"a1_4\"\n    And we wait for a period of \"400\" ms\n    Then I test the liveness of \"libraryApp/a1\"\n    Then \"{result}\" is true\n    And messaging will have outgoing posts\n      | msg.matches_type | to.instanceId | to.appId   |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n    And I shutdown the server\n    And I get the heartbeat times\n    Then \"{result}\" is an array of objects with the following contents\n      | instanceId | state     |\n      | a1         | Connected |\n\n  Scenario: App Doesn't Respond to heartbeats\n  Apps are considered dead if they don't respond to a heartbeat request within the timeout period\n\n    When \"libraryApp/a1\" is opened with connection id \"a1\"\n    And \"a1\" sends validate\n    And we wait for a period of \"3500\" ms\n    Then I test the liveness of \"libraryApp/a1\"\n    Then \"{result}\" is false\n    And messaging will have outgoing posts\n      | msg.matches_type | to.instanceId | to.appId   |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n      | heartbeatEvent   | a1            | libraryApp |\n    And I shutdown the server\n    And I get the heartbeat times\n    Then \"{result}\" is empty\n\n  Scenario: App says Goodbye\n    When \"libraryApp/a1\" is opened with connection id \"a1\"\n    And \"a1\" sends validate\n    And we wait for a period of \"500\" ms\n    And \"libraryApp/a1\" sends a goodbye message\n    Then I test the liveness of \"libraryApp/a1\"\n    Then \"{result}\" is false\n    And I shutdown the server\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/intent-result.feature",
    "content": "Feature: Intent Results Are Correctly Delivered\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | returnBook  | fdc3.book    | {empty}     |\n    And \"App1\" is an app with the following intents\n      | Intent Name | Context Type    | Result Type |\n      | viewNews    | fdc3.instrument | {empty}     |\n    And A newly instantiated FDC3 Server\n    And \"LibraryApp/l1\" is opened with connection id \"l1\"\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"LibraryApp/l1\" registers an intent listener for \"returnBook\"\n\n  Scenario: Waiting for an intent listener to be Added\n    When \"LibraryApp/l1\" raises an intent for \"viewNews\" with contextType \"fdc3.instrument\" on app \"App1/a1\" with requestUuid \"ABC123\"\n    And \"App1/a1\" registers an intent listener for \"viewNews\"\n    And \"App1/a1\" sends a intentResultRequest with eventUuid \"uuid10\" and void contents and raiseIntentUuid \"ABC123\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.meta.eventUuid | to.appId   | to.instanceId | msg.payload.raiseIntentRequestUuid | msg.payload.intentResolution.source.instanceId | msg.payload.intentResult.context.type |\n      | intentEvent               | uuid10             | App1       | a1            | ABC123                             | {null}                                         | {null}                                |\n      | raiseIntentResponse       | {null}             | LibraryApp | l1            | {null}                             | a1                                             | {null}                                |\n      | raiseIntentResultResponse | {null}             | LibraryApp | l1            | {null}                             | {null}                                         | {null}                                |\n      | intentResultResponse      | {null}             | App1       | a1            | {null}                             | {null}                                         | {null}                                |\n\n  Scenario: App Returns An Intent Response\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"LibraryApp/l1\" with requestUuid \"ABC123\"\n    When \"LibraryApp/l1\" sends a intentResultRequest with eventUuid \"uuid7\" and contextType \"fdc3.book\" and raiseIntentUuid \"ABC123\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.meta.eventUuid | msg.meta.requestUuid | to.appId   | to.instanceId | msg.payload.raiseIntentRequestUuid | msg.payload.intentResolution.source.instanceId | msg.payload.intentResult.context.type |\n      | intentEvent               | uuid7              | {null}               | LibraryApp | l1            | ABC123                             | {null}                                         | {null}                                |\n      | raiseIntentResponse       | {null}             | ABC123               | App1       | a1            | {null}                             | l1                                             | {null}                                |\n      | raiseIntentResultResponse | {null}             | ABC123               | App1       | a1            | {null}                             | {null}                                         | fdc3.book                             |\n      | intentResultResponse      | {null}             | uuid9                | LibraryApp | l1            | {null}                             | {null}                                         | {null}                                |\n\n  Scenario: App Returns An Intent Result\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"LibraryApp/l1\" with requestUuid \"ABC123\"\n    When \"LibraryApp/l1\" sends a intentResultRequest with eventUuid \"uuid7\" and private channel \"pc1\" and raiseIntentUuid \"ABC123\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.meta.eventUuid | to.appId   | to.instanceId | msg.payload.raiseIntentRequestUuid | msg.payload.intentResolution.source.instanceId | msg.payload.intentResult.channel.id |\n      | intentEvent               | uuid7              | LibraryApp | l1            | ABC123                             | {null}                                         | {null}                              |\n      | raiseIntentResponse       | {null}             | App1       | a1            | {null}                             | l1                                             | {null}                              |\n      | raiseIntentResultResponse | {null}             | App1       | a1            | {null}                             | {null}                                         | pc1                                 |\n      | intentResultResponse      | {null}             | LibraryApp | l1            | {null}                             | {null}                                         | {null}                              |\n\n  Scenario: App Returns A Void Intent Result\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"LibraryApp/l1\" with requestUuid \"ABC123\"\n    When \"LibraryApp/l1\" sends a intentResultRequest with eventUuid \"uuid7\" and void contents and raiseIntentUuid \"ABC123\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.meta.eventUuid | to.appId   | to.instanceId | msg.payload.raiseIntentRequestUuid | msg.payload.intentResolution.source.instanceId | msg.payload.intentResult.context.type |\n      | intentEvent               | uuid7              | LibraryApp | l1            | ABC123                             | {null}                                         | {null}                                |\n      | raiseIntentResponse       | {null}             | App1       | a1            | {null}                             | l1                                             | {null}                                |\n      | raiseIntentResultResponse | {null}             | App1       | a1            | {null}                             | {null}                                         | {null}                                |\n      | intentResultResponse      | {null}             | LibraryApp | l1            | {null}                             | {null}                                         | {null}                                |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/private-channel.feature",
    "content": "Feature: Relaying Private Channel Broadcast messages\n\n  Background:\n    Given schemas loaded\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"App2/a2\" is opened with connection id \"a2\"\n    And \"App2/a1\" creates a private channel\n    #TODO: have a2 retrieve the private channel by raising an intent - its currently using a1 reference to the channel\n    And I refer to \"uuid3\" as \"channel1Id\"\n\n  Scenario: Creating a new private channel\n    When \"App2/a1\" creates a private channel\n    Then messaging will have outgoing posts\n      | msg.matches_type             | msg.payload.privateChannel.id | msg.payload.privateChannel.type | to.appId | to.instanceId |\n      | createPrivateChannelResponse | uuid6                         | private                         | App2     | a1            |\n\n  Scenario: Broadcast message to no-one\n    When \"App1/a1\" broadcasts \"fdc3.instrument\" on \"{channel1Id}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type  |\n      | broadcastResponse |\n\n  Scenario: Broadcast message sent to one listener\n    When \"App2/a2\" adds a context listener on \"{channel1Id}\" with type \"fdc3.instrument\"\n    And \"App1/a1\" broadcasts \"fdc3.instrument\" on \"{channel1Id}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | msg.payload.channelId | msg.payload.context.id.ticker | msg.payload.context.type | to.appId | to.instanceId | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | addContextListenerResponse | {null}                | {null}                        | {null}                   | App2     | a2            | {null}                           | {null}                                |\n      | broadcastEvent             | {channel1Id}          | AAPL                          | fdc3.instrument          | App2     | a2            | App1                             | a1                                    |\n      | broadcastResponse          | {null}                | {null}                        | {null}                   | App1     | a1            | {null}                           | {null}                                |\n\n  Scenario: Event Listener created for addContextListener and unsubscribe\n    When \"App2/a2\" adds an \"addContextListener\" event listener on \"{channel1Id}\"\n    And \"App2/a2\" adds an \"unsubscribe\" event listener on \"{channel1Id}\"\n    And \"App1/a1\" adds a context listener on \"{channel1Id}\" with type \"fdc3.instrument\"\n    And we wait for a period of \"10\" ms\n    Then messaging will have outgoing posts\n      | msg.matches_type                        | to.appId | to.instanceId | msg.payload.privateChannelId | msg.payload.contextType | msg.payload.listenerUUID |\n      | privateChannelAddEventListenerResponse  | App2     | a2            | {null}                       | {null}                  | uuid6                    |\n      | privateChannelAddEventListenerResponse  | App2     | a2            | {null}                       | {null}                  | uuid9                    |\n      | privateChannelOnAddContextListenerEvent | App2     | a2            | {channel1Id}                 | fdc3.instrument         | {null}                   |\n      | addContextListenerResponse              | App1     | a1            | {null}                       | {null}                  | uuid12                   |\n    And \"App1/a1\" removes context listener with id \"uuid12\"\n    Then messaging will have outgoing posts\n      | msg.type                           | msg.payload.privateChannelId | msg.payload.contextType | to.appId | to.instanceId |\n      | privateChannelOnUnsubscribeEvent   | {channel1Id}                 | fdc3.instrument         | App2     | a2            |\n      | contextListenerUnsubscribeResponse | {null}                       | {null}                  | App1     | a1            |\n\n  Scenario: Disconnecting from a channel sends unsubscribe and disconnect messages\n    When \"App2/a2\" adds an \"disconnect\" event listener on \"{channel1Id}\"\n    And \"App1/a1\" adds a context listener on \"{channel1Id}\" with type \"fdc3.instrument\"\n    And \"App2/a2\" adds an \"unsubscribe\" event listener on \"{channel1Id}\"\n    And \"App1/a1\" disconnects from private channel \"{channel1Id}\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                 | msg.payload.privateChannelId | msg.payload.contextType | to.appId | to.instanceId |\n      | privateChannelOnUnsubscribeEvent | {channel1Id}                 | fdc3.instrument         | App2     | a2            |\n      | privateChannelOnDisconnectEvent  | {channel1Id}                 | {null}                  | App2     | a2            |\n      | privateChannelDisconnectResponse | {null}                       | {null}                  | App1     | a1            |\n\n  Scenario: addContextListener Event Listener add and removed, shouldn't fire when addContextListener called.\n    When \"App2/a2\" adds an \"addContextListener\" event listener on \"{channel1Id}\"\n    And \"App2/a2\" removes event listener \"uuid6\"\n    And \"App1/a1\" adds a context listener on \"{channel1Id}\" with type \"fdc3.instrument\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                               | to.appId | to.instanceId | msg.payload.privateChannelId | msg.payload.contextType | msg.payload.listenerUUID |\n      | privateChannelAddEventListenerResponse         | App2     | a2            | {null}                       | {null}                  | uuid6                    |\n      | privateChannelUnsubscribeEventListenerResponse | App2     | a2            | {null}                       | {null}                  | {null}                   |\n      | addContextListenerResponse                     | App1     | a1            | {null}                       | {null}                  | uuid11                   |\n\n  Scenario: I can't register an app channel with the same ID as a private channel\n    When \"App2/a2\" creates or gets an app channel called \"{channel1Id}\"\n    Then messaging will have outgoing posts\n      | msg.type                   | to.appId | to.instanceId | msg.payload.error |\n      | getOrCreateChannelResponse | App2     | a2            | AccessDenied      |\n\n  Scenario: A newly created private channel cannot be retrieved via getOrCreateChannel\n    When \"App1/a1\" creates a private channel\n    And I refer to \"uuid6\" as \"channel2Id\"\n    And \"App2/a2\" creates or gets an app channel called \"{channel2Id}\"\n    Then messaging will have outgoing posts\n      | msg.type                   | to.appId | to.instanceId | msg.payload.error |\n      | getOrCreateChannelResponse | App2     | a2            | AccessDenied      |\n\n  Scenario: Subscribe to a non-existent channel\n    When \"App2/a2\" adds a context listener on \"IDontExist\" with type \"fdc3.instrument\"\n    Then messaging will have outgoing posts\n      | msg.type                   | to.appId | to.instanceId | msg.payload.error |\n      | addContextListenerResponse | App2     | a2            | NoChannelFound    |\n\n  Scenario: Can't unsubscribe an unconnected listener\n    When \"App2/a2\" adds a context listener on \"{channelId}\" with type \"fdc3.instrument\"\n    And \"App2/a2\" removes context listener with id \"uuid6\"\n    And \"App2/a2\" removes context listener with id \"uuid6\"\n    Then messaging will have outgoing posts\n      | msg.type                           | to.appId | to.instanceId | msg.payload.error |\n      | contextListenerUnsubscribeResponse | App2     | a2            | {null}            |\n      | contextListenerUnsubscribeResponse | App2     | a2            | ListenerNotFound  |\n\n  Scenario: Can't unsubscribe an someone else's listener\n    When \"App2/a2\" adds a context listener on \"{channelId}\" with type \"fdc3.instrument\"\n    And \"App1/a1\" removes context listener with id \"uuid6\"\n    Then messaging will have outgoing posts\n      | msg.type                           | to.appId | to.instanceId | msg.payload.error |\n      | addContextListenerResponse         | App2     | a2            | {null}            |\n      | contextListenerUnsubscribeResponse | App1     | a1            | ListenerNotFound  |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/raise-intent-with-context.feature",
    "content": "Feature: Raising Intents For Context\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name    | Context Type  | Result Type |\n      | returnBook     | fdc3.book     | {empty}     |\n      | borrowBook     | fdc3.book     | {empty}     |\n      | borrowMagazine | fdc3.magazine | {empty}     |\n    And \"listenerApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | borrowBook  | fdc3.book    | {empty}     |\n    And \"unusedApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"listenerApp/b1\" is opened with connection id \"b1\"\n    And \"listenerApp/b1\" registers an intent listener for \"returnBook\"\n\n  Scenario: Raising an Intent With Context to a Non-Existent App\n    And \"App1/a1\" raises an intent with contextType \"fdc3.magazine\" on app \"completelyMadeUp\"\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.error    | to.instanceId | to.appId |\n      | raiseIntentForContextResponse | TargetAppUnavailable | a1            | App1     |\n\n  Scenario: Raising An Intent With Context To A Non-Existent App Instance\n    When \"App1/a1\" raises an intent with contextType \"fdc3.book\" on app \"libraryApp/unknownInstance\"\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.error         | to.instanceId |\n      | raiseIntentForContextResponse | TargetInstanceUnavailable | a1            |\n\nScenario: Raising An Intent With Context To An Invalid Instance\n    When \"App1/a1\" raises an intent with contextType \"fdc3.book\" on an invalid app instance\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.error         | to.instanceId |\n      | raiseIntentForContextResponse | TargetAppUnavailable      | a1            |\n\n  Scenario: Raising An Intent With Context To A Running App\n    When \"App1/a1\" raises an intent with contextType \"fdc3.book\" on app \"listenerApp/b1\"\n    Then messaging will have outgoing posts\n      | msg.matches_type              | msg.payload.context.type | msg.payload.intent | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId | msg.payload.intentResolution.intent | to.instanceId | to.appId    | msg.payload.intentResolution.source.appId |\n      | intentEvent                   | fdc3.book                | returnBook         | App1                             | a1                                    | {null}                              | b1            | listenerApp | {null}                                    |\n      | raiseIntentForContextResponse | {null}                   | {null}             | {null}                           | {null}                                | returnBook                          | a1            | App1        | listenerApp                               |\n\n  Scenario: Raising An Intent With Context To A Non-Running App\n    When \"App1/a1\" raises an intent with contextType \"fdc3.magazine\" on app \"libraryApp\"\n    And \"uuid-0\" sends validate\n    And \"libraryApp/0\" registers an intent listener for \"borrowMagazine\"\n    Then messaging will have outgoing posts\n      | msg.matches_type              | msg.payload.intent | to.instanceId | to.appId   | msg.payload.context.type |\n      | addIntentListenerResponse     | {null}             |             0 | libraryApp | {null}                   |\n      | intentEvent                   | borrowMagazine     |             0 | libraryApp | fdc3.magazine            |\n      | raiseIntentForContextResponse | {null}             | a1            | App1       | {null}                   |\n\n  Scenario: Raising an Intent With Context to a Non-Existent App Instance\n    And \"App1/a1\" raises an intent with contextType \"fdc3.book\" on app \"unusedApp/u1\"\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.error         | to.instanceId | to.appId |\n      | raiseIntentForContextResponse | TargetInstanceUnavailable | a1            | App1     |\n\n  Scenario: Raising An Intent With Context To A Broken App that doesn't add an intent listener\n    When \"App1/a1\" raises an intent with contextType \"fdc3.magazine\" on app \"libraryApp\"\n    And \"uuid-0\" sends validate\n    And we wait for the intent timeout\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.error    | to.instanceId | to.appId |\n      | raiseIntentForContextResponse | IntentDeliveryFailed | a1            | App1     |\n\n  Scenario: User Must Choose An Intent using The Intent Resolver\n    When \"App1/a1\" raises an intent with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.appIntents[0].intent.name | msg.payload.appIntents[1].intent.name | to.instanceId | to.appId |\n      | raiseIntentForContextResponse | returnBook                            | borrowBook                            | a1            | App1     |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[0].apps[0].appId | msg.payload.appIntent.apps[0].instanceId |\n      | libraryApp                              | {null}                                   |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[0].appId | msg.payload.appIntents[1].apps[0].instanceId |\n      | listenerApp                             | b1                                           |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[1].appId | msg.payload.appIntents[1].apps[1].instanceId |\n      | libraryApp                              | {null}                                       |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[2].appId | msg.payload.appIntents[1].apps[2].instanceId |\n      | listenerApp                             | {null}                                       |\n\nScenario: Dynamic registrations are displayed in the app resolver\n    When \"App2/a2\" registers an intent listener for \"returnBook\" with contextType \"fdc3.book\"\n    When \"App1/a1\" raises an intent with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.type                      | msg.payload.appIntents[0].intent.name | msg.payload.appIntents[1].intent.name | to.instanceId | to.appId |\n      | raiseIntentForContextResponse | returnBook                            | borrowBook                            | a1            | App1     |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[0].apps[0].appId | msg.payload.appIntents[0].apps[0].instanceId |\n      | App2                                    | a2                                           |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[0].appId | msg.payload.appIntents[1].apps[0].instanceId |\n      | listenerApp                             | b1                                           |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[1].appId | msg.payload.appIntents[1].apps[1].instanceId |\n      | libraryApp                              | {null}                                       |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntents[1].apps[2].appId | msg.payload.appIntents[1].apps[2].instanceId |\n      | listenerApp                             | {null}                                       |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/raise-intent.feature",
    "content": "Feature: Raising Intents\n\n  Background:\n    Given schemas loaded\n    And \"libraryApp\" is an app with the following intents\n      | Intent Name  | Context Type    | Result Type |\n      | returnBook   | fdc3.book       | {empty}     |\n      | borrowBook   | fdc3.book       | {empty}     |\n      | sleepyIntent | fdc3.periodical | {empty}     |\n    And \"listenerApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n      | borrowBook  | fdc3.book    | {empty}     |\n    And \"uniqueIntentApp\" is an app with the following intents\n      | Intent Name  | Context Type  | Result Type |\n      | uniqueIntent | fdc3.magazine | {empty}     |\n    And \"unusedApp\" is an app with the following intents\n      | Intent Name | Context Type | Result Type |\n    And A newly instantiated FDC3 Server\n    And \"uniqueIntentApp/c1\" is opened with connection id \"c1\"\n    And \"uniqueIntentApp/c1\" registers an intent listener for \"uniqueIntent\"\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"listenerApp/b1\" is opened with connection id \"b1\"\n    And \"listenerApp/b1\" registers an intent listener for \"returnBook\"\n\n  Scenario: Context Not Handled By App\n    When \"App1/a1\" raises an intent for \"borrowBook\" with contextType \"fdc3.magazine\" on app \"listenerApp/b1\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error | to.instanceId |\n      | raiseIntentResponse | NoAppsFound       | a1            |\n\n  Scenario: Raising an Intent that should auto-resolve (only one option)\n    And \"App1/a1\" raises an intent for \"uniqueIntent\" with contextType \"fdc3.magazine\"\n    Then messaging will have outgoing posts\n      | msg.matches_type    | msg.payload.context.type | msg.payload.intent | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId | msg.payload.intentResolution.intent | to.instanceId | to.appId        | msg.payload.intentResolution.source.appId |\n      | intentEvent         | fdc3.magazine            | uniqueIntent       | App1                             | a1                                    | {null}                              | c1            | uniqueIntentApp | {null}                                    |\n      | raiseIntentResponse | {null}                   | {null}             | {null}                           | {null}                                | uniqueIntent                        | a1            | App1            | uniqueIntentApp                           |\n\n  Scenario: Raising an Intent to a Non-Existent App\n    And \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"completelyMadeUp\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error    | to.instanceId | to.appId |\n      | raiseIntentResponse | TargetAppUnavailable | a1            | App1     |\n\n  Scenario: Raising An Intent To A Non-Existent App Instance\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"libraryApp/unknownInstance\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error         | to.instanceId |\n      | raiseIntentResponse | TargetInstanceUnavailable | a1            |\n\n  Scenario: Raising An Intent To A Running App instance by instanceId\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"listenerApp/b1\"\n    Then messaging will have outgoing posts\n      | msg.matches_type    | msg.payload.context.type | msg.payload.intent | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId | msg.payload.intentResolution.intent | to.instanceId | to.appId    | msg.payload.intentResolution.source.appId |\n      | intentEvent         | fdc3.book                | returnBook         | App1                             | a1                                    | {null}                              | b1            | listenerApp | {null}                                    |\n      | raiseIntentResponse | {null}                   | {null}             | {null}                           | {null}                                | returnBook                          | a1            | App1        | listenerApp                               |\n\n  Scenario: Raising An Intent To A Non-Running App\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"libraryApp\"\n    And \"uuid-0\" sends validate\n    And \"libraryApp/0\" registers an intent listener for \"returnBook\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.payload.intent | to.instanceId | to.appId   | msg.payload.context.type |\n      | addIntentListenerResponse | {null}             |             0 | libraryApp | {null}                   |\n      | intentEvent               | returnBook         |             0 | libraryApp | fdc3.book                |\n      | raiseIntentResponse       | {null}             | a1            | App1       | {null}                   |\n\n  Scenario: Raising An Intent That Appplies to A Non-Running But Uniquely Identifiable App\n    When \"App1/a1\" raises an intent for \"sleepyIntent\" with contextType \"fdc3.periodical\"\n    And \"uuid-0\" sends validate\n    And \"libraryApp/0\" registers an intent listener for \"sleepyIntent\"\n    Then messaging will have outgoing posts\n      | msg.matches_type          | msg.payload.intent | to.instanceId | to.appId   | msg.payload.context.type |\n      | addIntentListenerResponse | {null}             |             0 | libraryApp | {null}                   |\n      | intentEvent               | sleepyIntent       |             0 | libraryApp | fdc3.periodical          |\n      | raiseIntentResponse       | {null}             | a1            | App1       | {null}                   |\n\n  Scenario: Raising an Intent to a Non-Existent App Instance\n    And \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"unusedApp/u1\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error         | to.instanceId | to.appId |\n      | raiseIntentResponse | TargetInstanceUnavailable | a1            | App1     |\n\n  Scenario: Raising an Intent to an invalid App Instance\n    And \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on an invalid app instance\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error    | to.instanceId | to.appId |\n      | raiseIntentResponse | TargetAppUnavailable | a1            | App1     |\n\n  Scenario: Raising An Intent To A Non-Running App without A Context Type in the listener\n    When \"App1/a1\" raises an intent for \"stampBook\" with contextType \"fdc3.book\" on app \"libraryApp\"\n    Then messaging will have outgoing posts\n      | msg.payload.error | msg.type            |\n      | NoAppsFound       | raiseIntentResponse |\n\n  Scenario: Raising An Intent To A Broken App that doesn't add an intent listener\n    When \"App1/a1\" raises an intent for \"returnBook\" with contextType \"fdc3.book\" on app \"libraryApp\"\n    And \"uuid-0\" sends validate\n    And we wait for the intent timeout\n    Then running apps will be\n      | appId           | instanceId |\n      | uniqueIntentApp | c1         |\n      | listenerApp     | b1         |\n      | App1            | a1         |\n      | libraryApp      | uuid-0     |\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.error    | to.instanceId | to.appId |\n      | raiseIntentResponse | IntentDeliveryFailed | a1            | App1     |\n\n  Scenario: User Must Choose An Intent using The Intent Resolver\n    When \"App1/a1\" raises an intent for \"borrowBook\" with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.appIntent.intent.name | msg.payload.appIntent.intent.displayName | to.instanceId | to.appId |\n      | raiseIntentResponse | borrowBook                        | borrowBook                               | a1            | App1     |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[0].appId | msg.payload.appIntent.apps[0].instanceId |\n      | listenerApp                         | b1                                       |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[1].appId | msg.payload.appIntent.apps[1].instanceId |\n      | libraryApp                          | {null}                                   |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[2].appId | msg.payload.appIntent.apps[2].instanceId |\n      | listenerApp                         | {null}                                   |\n\n\n  Scenario: Dynamic registrations are displayed in the app resolver\n    When \"App2/a2\" registers an intent listener for \"borrowBook\" with contextType \"fdc3.book\"\n    When \"App1/a1\" raises an intent for \"borrowBook\" with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.type            | msg.payload.appIntent.intent.name | msg.payload.appIntent.intent.displayName | to.instanceId | to.appId |\n      | raiseIntentResponse | borrowBook                        | borrowBook                               | a1            | App1     |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[0].appId | msg.payload.appIntent.apps[0].instanceId |\n      | listenerApp                         | b1                                       |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[1].appId | msg.payload.appIntent.apps[1].instanceId |\n      | App2                                | a2                                       |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[2].appId | msg.payload.appIntent.apps[2].instanceId |\n      | libraryApp                          | {null}                                   |\n    Then messaging will have outgoing posts\n      | msg.payload.appIntent.apps[3].appId | msg.payload.appIntent.apps[3].instanceId |\n      | listenerApp                         | {null}                                   |\n\n  Scenario: Raising An Invalid Intent to the server (no instance)\n    When \"App1/a1\" raises an intent for \"borrowBook\" with contextType \"fdc3.book\" on app \"listenerApp/z1\"\n    Then messaging will have outgoing posts\n      | msg.payload.error         | msg.type            |\n      | TargetInstanceUnavailable | raiseIntentResponse |\n\n  Scenario: Raising An Invalid Intent (no app)\n    When \"App1/a1\" raises an intent for \"borrowBook\" with contextType \"fdc3.book\" on app \"nonExistentApp\"\n    Then messaging will have outgoing posts\n      | msg.payload.error    | msg.type            |\n      | TargetAppUnavailable | raiseIntentResponse |\n\n  Scenario: Raising An Invalid Intent (non existent intent)\n    When \"App1/a1\" raises an intent for \"nonExistentIntent\" with contextType \"fdc3.book\"\n    Then messaging will have outgoing posts\n      | msg.payload.error | msg.type            |\n      | NoAppsFound       | raiseIntentResponse |\n\n  Scenario: Raising An Invalid Intent (non existent intent but valid app)\n    When \"App1/a1\" raises an intent for \"nonExistentIntent\" with contextType \"fdc3.book\" on app \"listenerApp/b1\"\n    Then messaging will have outgoing posts\n      | msg.payload.error | msg.type            |\n      | NoAppsFound       | raiseIntentResponse |"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/features/user-channels.feature",
    "content": "Feature: Relaying Private Channel Broadcast messages\n\n  Background:\n      This creates user channels \"one\", \"two\" and \"three\"\n\n    Given schemas loaded\n    And A newly instantiated FDC3 Server\n    And \"App1/a1\" is opened with connection id \"a1\"\n    And \"App2/a2\" is opened with connection id \"a2\"\n\n  Scenario: List User Channels\n    When \"App1/a1\" gets the list of user channels\n    Then messaging will have outgoing posts\n      | msg.payload.userChannels[0].id | msg.payload.userChannels[1].id | msg.payload.userChannels[2].id | msg.payload.userChannels[0].type | to.instanceId | msg.matches_type        |\n      | one                            | two                            | three                          | user                             | a1            | getUserChannelsResponse |\n\n  Scenario: Initial User Channel\n        At startup, the user channel shouldn't be set\n\n    When \"App1/a1\" gets the current user channel\n    Then messaging will have outgoing posts\n      | msg.payload.channel.id | to.instanceId | msg.matches_type          |\n      | {null}                 | a1            | getCurrentChannelResponse |\n\n  Scenario: Changing Channel\n        You should be able to join a channel knowing it's ID.\n\n    When \"App/a1\" joins user channel \"one\"\n    And \"App1/a1\" gets the current user channel\n    Then messaging will have outgoing posts\n      | msg.payload.channel.id | to.instanceId | msg.matches_type          |\n      | {null}                 | a1            | channelChangedEvent       |\n      | {null}                 | a1            | joinUserChannelResponse   |\n      | one                    | a1            | getCurrentChannelResponse |\n\n  Scenario: Adding a Typed Listener on a given User Channel\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"fdc3.instrument\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.payload.channelId | msg.payload.context.type | msg.matches_type  | to.instanceId | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | one                   | fdc3.instrument          | broadcastEvent    | a1            | App2                             | a2                                    |\n      | {null}                | {null}                   | broadcastResponse | a2            | {null}                           | {null}                                |\n\n  Scenario: Adding an Un-Typed Listener on a given User Channel\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"{null}\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.payload.channelId | msg.payload.context.type | msg.matches_type  | to.instanceId | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | one                   | fdc3.instrument          | broadcastEvent    | a1            | App2                             | a2                                    |\n      | {null}                | {null}                   | broadcastResponse | a2            | {null}                           | {null}                                |\n\n  Scenario: If you haven't joined a channel, your listener receives nothing\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"{null}\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"two\"\n    Then messaging will have outgoing posts\n      | msg.matches_type           | to.instanceId |\n      | channelChangedEvent        | a1            |\n      | joinUserChannelResponse    | a1            |\n      | addContextListenerResponse | a1            |\n      | broadcastResponse          | a2            |\n\n  Scenario: After unsubscribing, my listener shouldn't receive any more messages\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"{null}\"\n    And \"App/a1\" removes context listener with id \"uuid5\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type                   | msg.payload.listenerUUID |\n      | channelChangedEvent                | {null}                   |\n      | joinUserChannelResponse            | {null}                   |\n      | addContextListenerResponse         | uuid6                    |\n      | contextListenerUnsubscribeResponse | {null}                   |\n      | broadcastEvent                     | {null}                   |\n      | broadcastResponse                  | {null}                   |\n\n  Scenario: I should be able to leave a user channel, and not receive messages on it\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"{null}\"\n    And \"App/a1\" leaves the current user channel\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.matches_type            |\n      | channelChangedEvent         |\n      | joinUserChannelResponse     |\n      | addContextListenerResponse  |\n      | channelChangedEvent         |\n      | leaveCurrentChannelResponse |\n      | broadcastResponse           |\n\n  Scenario: Joining a user channel that doesn't exist throws an error\n    When \"App/a1\" joins user channel \"four\"\n    Then messaging will have outgoing posts\n      | msg.payload.error | msg.type                |\n      | NoChannelFound    | joinUserChannelResponse |\n\n  Scenario: Joining an app channel throws an error\n    When \"App/a2\" creates or gets an app channel called \"bizboz\"\n    When \"App/a1\" joins user channel \"bizboz\"\n    Then messaging will have outgoing posts\n      | msg.payload.error | msg.type                |\n      | NoChannelFound    | joinUserChannelResponse |\n\n  Scenario: You can get the details of the last context type sent\n    When \"App/a1\" joins user channel \"one\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    And \"App2/a2\" broadcasts \"fdc3.country\" on \"one\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"fdc3.instrument\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"fdc3.country\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"{null}\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"fdc3.sausage\"\n    Then messaging will have outgoing posts\n      | msg.payload.context.type | msg.payload.context.name | msg.matches_type          |\n      | fdc3.instrument          | Apple                    | getCurrentContextResponse |\n      | fdc3.country             | Sweden                   | getCurrentContextResponse |\n      | fdc3.country             | Sweden                   | getCurrentContextResponse |\n      | {null}                   | {null}                   | getCurrentContextResponse |\n\n  Scenario: Changing channel changes the listener channels too\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"{null}\"\n    And \"App/a1\" joins user channel \"two\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"two\"\n    And \"App2/a2\" broadcasts \"fdc3.country\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.payload.channelId | msg.payload.context.type | msg.matches_type  | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | two                   | fdc3.instrument          | broadcastEvent    | App2                             | a2                                    |\n      | {null}                | {null}                   | broadcastResponse | {null}                           | {null}                                |\n      | {null}                | {null}                   | broadcastResponse | {null}                           | {null}                                |\n\n  Scenario: A user channel retrieved via getOrCreateChannel is the same channel\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" adds a user-channel context listener with type \"fdc3.instrument\"\n    And \"App2/a2\" creates or gets an app channel called \"one\"\n    And \"App2/a2\" broadcasts \"fdc3.instrument\" on \"one\"\n    Then messaging will have outgoing posts\n      | msg.payload.channelId | msg.payload.context.type | msg.matches_type  | to.instanceId | msg.payload.originatingApp.appId | msg.payload.originatingApp.instanceId |\n      | one                   | fdc3.instrument          | broadcastEvent    | a1            | App2                             | a2                                    |\n      | {null}                | {null}                   | broadcastResponse | a2            | {null}                           | {null}                                |\n\n  Scenario: You can get the details of the last context type when none is set\n    When \"App/a1\" joins user channel \"one\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"fdc3.instrument\"\n    And \"App/a1\" gets the latest context on \"one\" with type \"{null}\"\n    Then messaging will have outgoing posts\n      | msg.payload.context.type | msg.payload.context.name | msg.matches_type          |\n      | {null}                   | {null}                   | getCurrentContextResponse |\n      | {null}                   | {null}                   | getCurrentContextResponse |\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/app-channel.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { createMeta } from './generic.steps.js';\nimport { handleResolve } from '@finos/testing';\nimport { BrowserTypes } from '@finos/fdc3-schema';\ntype GetOrCreateChannelRequest = BrowserTypes.GetOrCreateChannelRequest;\n\nWhen('{string} creates or gets an app channel called {string}', (world: CustomWorld, app: string, channel: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {\n      channelId: handleResolve(channel, world),\n    },\n    type: 'getOrCreateChannelRequest',\n  } as GetOrCreateChannelRequest;\n\n  world.server.receive(message, uuid);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/broadcast.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { createMeta } from './generic.steps.js';\nimport {} from '@finos/fdc3-standard';\nimport { handleResolve } from '@finos/testing';\nimport { contextMap } from './generic.steps.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\n\ntype AddContextListenerRequest = BrowserTypes.AddContextListenerRequest;\ntype ContextListenerUnsubscribeRequest = BrowserTypes.ContextListenerUnsubscribeRequest;\ntype BroadcastRequest = BrowserTypes.BroadcastRequest;\ntype GetCurrentContextRequest = BrowserTypes.GetCurrentContextRequest;\n\nWhen(\n  '{string} adds a context listener on {string} with type {string}',\n  (world: CustomWorld, app: string, channelId: string, contextType: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        channelId: handleResolve(channelId, world),\n        contextType: handleResolve(contextType, world),\n      },\n      type: 'addContextListenerRequest',\n    } as AddContextListenerRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} adds a user-channel context listener with type {string}',\n  (world: CustomWorld, app: string, contextType: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        channelId: null, // null indicates it's added at the DesktopAgent level and listens on the current user-channel\n        contextType: handleResolve(contextType, world),\n      },\n      type: 'addContextListenerRequest',\n    } as AddContextListenerRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} asks for the latest context on {string} with type {string}',\n  (world: CustomWorld, app: string, channelId: string, contextType: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        channelId: handleResolve(channelId, world),\n        contextType,\n      },\n      type: 'getCurrentContextRequest',\n    } as GetCurrentContextRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n\nWhen('{string} removes context listener with id {string}', (world: CustomWorld, app: string, id: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n  const message = {\n    meta,\n    payload: {\n      listenerUUID: id,\n    },\n    type: 'contextListenerUnsubscribeRequest',\n  } as ContextListenerUnsubscribeRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen(\n  '{string} broadcasts {string} on {string}',\n  (world: CustomWorld, app: string, contextType: string, channelId: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n    const message = {\n      meta,\n      payload: {\n        channelId: handleResolve(channelId, world),\n        context: contextMap[contextType],\n      },\n      type: 'broadcastRequest',\n    } as BroadcastRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/event-listeners.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { createMeta } from './generic.steps.js';\nimport {} from '@finos/fdc3-standard';\nimport { handleResolve } from '@finos/testing';\nimport { BrowserTypes } from '@finos/fdc3-schema';\n\ntype AddEventListenerRequest = BrowserTypes.AddEventListenerRequest;\ntype EventListenerUnsubscribeRequest = BrowserTypes.EventListenerUnsubscribeRequest;\n\nWhen('{string} adds an event listener for {string}', (world: CustomWorld, app: string, type: string) => {\n  const meta = createMeta(world, app);\n  const resolvedType = handleResolve(type, world);\n\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {\n      type: resolvedType,\n    },\n    type: 'addEventListenerRequest',\n  } as AddEventListenerRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} removes event listener with id {string}', (world: CustomWorld, app: string, id: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n  const message = {\n    meta,\n    payload: {\n      listenerUUID: id,\n    },\n    type: 'eventListenerUnsubscribeRequest',\n  } as EventListenerUnsubscribeRequest;\n\n  world.server.receive(message, uuid);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/generic.steps.ts",
    "content": "import { Given, When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { TestServerContext } from '../support/TestServerContext.js';\nimport { DefaultFDC3Server } from '../../src/BasicFDC3Server.js';\nimport { BasicDirectory } from '../../src/directory/BasicDirectory.js';\nimport { ChannelType } from '../../src/handlers/BroadcastHandler.js';\nimport { Context } from '@finos/fdc3-context';\nimport { AppIdentifier } from '@finos/fdc3-standard';\nimport { setupGenericSteps } from '@finos/testing';\nimport path from 'path';\n\nexport const APP_FIELD = 'apps';\n\nexport const contextMap: Record<string, Context> = {\n  'fdc3.instrument': {\n    type: 'fdc3.instrument',\n    name: 'Apple',\n    id: {\n      ticker: 'AAPL',\n    },\n  },\n  'fdc3.country': {\n    type: 'fdc3.country',\n    name: 'Sweden',\n    id: {\n      COUNTRY_ISOALPHA2: 'SE',\n      COUNTRY_ISOALPHA3: 'SWE',\n    },\n  },\n  'fdc3.unsupported': {\n    type: 'fdc3.unsupported',\n    bogus: true,\n  },\n  'fdc3.book': {\n    type: 'fdc3.book',\n    author: 'Greg Wallace',\n    title: 'Cooking with Greg',\n    id: {\n      ISBN: '1234',\n    },\n  },\n  'fdc3.magazine': {\n    type: 'fdc3.magazine',\n    title: 'The Economist',\n    price: 3.99,\n    id: {\n      ISSN: '1234',\n    },\n  },\n  'fdc3.periodical': {\n    type: 'fdc3.periodical',\n    title: 'The American Poetry Review',\n    price: 13.99,\n    id: {\n      ISSN: '45643',\n    },\n  },\n  'fdc3.product': {\n    type: 'fdc3.product',\n    title: 'Current bun',\n    id: {\n      productId: 'cb1',\n    },\n  },\n};\n\nfunction defaultChannels() {\n  return [\n    {\n      id: 'one',\n      type: ChannelType.user,\n      context: [],\n      displayMetadata: {\n        name: 'One Channel',\n        color: 'orange',\n      },\n    },\n    {\n      id: 'two',\n      type: ChannelType.user,\n      context: [],\n      displayMetadata: {\n        name: 'Two Channel',\n        color: 'skyblue',\n      },\n    },\n    {\n      id: 'three',\n      type: ChannelType.user,\n      context: [],\n      displayMetadata: {\n        name: 'Three Channel',\n        color: 'ochre',\n      },\n    },\n  ];\n}\n\nexport function createMeta(cw: CustomWorld, appStr: string) {\n  let app: AppIdentifier;\n  if (appStr.includes('/')) {\n    const [appId, instanceId] = appStr.split('/');\n    app = { appId, instanceId };\n  } else {\n    app = { appId: appStr };\n  }\n\n  return {\n    requestUuid: cw.sc.createUUID(),\n    timestamp: new Date(),\n    source: app,\n  };\n}\n\n// Register shared generic steps from @finos/testing\nconst schemaBasePath = path.join(import.meta.dirname, '../../../../../packages/');\nsetupGenericSteps(schemaBasePath);\n\nGiven('A newly instantiated FDC3 Server', (world: CustomWorld) => {\n  const apps = world.props[APP_FIELD] ?? [];\n  const d = new BasicDirectory(apps);\n  world.sc = new TestServerContext(world);\n  world.server = new DefaultFDC3Server(world.sc, d, defaultChannels(), false, 2000, 2000);\n});\n\nGiven('A newly instantiated FDC3 Server with heartbeat checking', (world: CustomWorld) => {\n  const apps = world.props[APP_FIELD] ?? [];\n  const d = new BasicDirectory(apps);\n\n  world.sc = new TestServerContext(world);\n  world.server = new DefaultFDC3Server(world.sc, d, defaultChannels(), true, 2000, 1000);\n});\n\nWhen('I shutdown the server', (world: CustomWorld) => {\n  world.server.shutdown();\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/heartbeat.steps.ts",
    "content": "import { Given, Then } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport {\n  HeartbeatAcknowledgementRequest,\n  WebConnectionProtocol6Goodbye,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { createMeta } from './generic.steps.js';\nimport { HeartbeatHandler } from '../../src/handlers/HeartbeatHandler.js';\n\nGiven(\n  '{string} sends a heartbeat response to eventUuid {string}',\n  (world: CustomWorld, appStr: string, eventUuid: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n    const message = {\n      meta,\n      payload: {\n        heartbeatEventUuid: eventUuid,\n      },\n      type: 'heartbeatAcknowledgementRequest',\n    } as HeartbeatAcknowledgementRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n\nGiven('{string} sends a goodbye message', (world: CustomWorld, appStr: string) => {\n  const meta = createMeta(world, appStr);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n  const message: WebConnectionProtocol6Goodbye = {\n    meta,\n    type: 'WCP6Goodbye',\n  };\n\n  world.server.receive(message, uuid);\n});\n\nThen('I test the liveness of {string}', async (world: CustomWorld, appStr: string) => {\n  const out = await world.sc.isAppConnected(createMeta(world, appStr).source.instanceId ?? 'UNKNOWN');\n  world.props['result'] = out;\n});\n\nThen('I get the heartbeat times', async (world: CustomWorld) => {\n  const hbh = world.server.handlers[3];\n  const out = (hbh as HeartbeatHandler).heartbeatTimes();\n  world.props['result'] = out;\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/intents.steps.ts",
    "content": "import { Given, When } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { CustomWorld } from '../world/index.js';\nimport { DirectoryApp } from '../../src/directory/DirectoryInterface.js';\nimport { APP_FIELD, contextMap, createMeta } from './generic.steps.js';\nimport { handleResolve } from '@finos/testing';\nimport { BrowserTypes } from '@finos/fdc3-schema';\n\ntype FindIntentRequest = BrowserTypes.FindIntentRequest;\ntype FindIntentsByContextRequest = BrowserTypes.FindIntentsByContextRequest;\ntype AddIntentListenerRequest = BrowserTypes.AddIntentListenerRequest;\ntype IntentListenerUnsubscribeRequest = BrowserTypes.IntentListenerUnsubscribeRequest;\ntype RaiseIntentRequest = BrowserTypes.RaiseIntentRequest;\ntype RaiseIntentForContextRequest = BrowserTypes.RaiseIntentForContextRequest;\ntype IntentResultRequest = BrowserTypes.IntentResultRequest;\n\ntype ListensFor = {\n  [key: string]: {\n    displayName?: string | undefined;\n    contexts: string[];\n    resultType?: string | undefined;\n  };\n};\n\nfunction decamelize(str: string, separator: string) {\n  separator = typeof separator === 'undefined' ? '_' : separator;\n\n  return str\n    .replace(/([a-z\\d])([A-Z])/g, '$1' + separator + '$2')\n    .replace(/([A-Z]+)([A-Z][a-z\\d]+)/g, '$1' + separator + '$2')\n    .toLowerCase();\n}\n\nfunction convertDataTableToListensFor(cw: CustomWorld, dt: DataTable): ListensFor {\n  const hashes = dt.hashes();\n  const out: ListensFor = {};\n  hashes.forEach(h => {\n    out[h['Intent Name']] = {\n      displayName: decamelize(h['Intent Name'], ' '),\n      contexts: [handleResolve(h['Context Type'], cw)],\n      resultType: handleResolve(h['Result Type'], cw),\n    };\n  });\n\n  return out;\n}\n\nGiven('{string} is an app with the following intents', (world: CustomWorld, appId: string, dt: DataTable) => {\n  const currentApps = world.props[APP_FIELD] ?? [];\n\n  const newApp: DirectoryApp = {\n    appId,\n    type: 'web',\n    description: '',\n    title: '',\n    details: {},\n    interop: {\n      intents: {\n        listensFor: convertDataTableToListensFor(world, dt),\n      },\n    },\n  };\n\n  currentApps.push(newApp);\n\n  world.props[APP_FIELD] = currentApps;\n});\n\nWhen(\n  '{string} finds intents with intent {string} and contextType {string} and result type {string}',\n  async (world: CustomWorld, appStr: string, intentName: string, contextType: string, resultType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        intent: handleResolve(intentName, world)!,\n        resultType: handleResolve(resultType, world),\n        context: contextMap[contextType],\n      },\n      type: 'findIntentRequest',\n    } as FindIntentRequest;\n\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} finds intents with contextType {string}',\n  async (world: CustomWorld, appStr: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        context: contextMap[contextType],\n      },\n      type: 'findIntentsByContextRequest',\n    } as FindIntentsByContextRequest;\n\n    await world.server.receive(message, uuid);\n  }\n);\n\nGiven(\n  '{string} registers an intent listener for {string}',\n  async (world: CustomWorld, appStr: string, intent: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n    const message = {\n      type: 'addIntentListenerRequest',\n      meta,\n      payload: {\n        intent: handleResolve(intent, world),\n      },\n    } as AddIntentListenerRequest;\n    await world.server.receive(message, uuid);\n  }\n);\n\nGiven(\n  '{string} registers an intent listener for {string} with contextType {string}',\n  async (world: CustomWorld, appStr: string, intent: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      type: 'addIntentListenerRequest',\n      meta,\n      payload: {\n        intent: handleResolve(intent, world),\n        contextType: handleResolve(contextType, world),\n      },\n    } as AddIntentListenerRequest;\n    await world.server.receive(message, uuid);\n  }\n);\n\nGiven(\n  '{string} unsubscribes an intent listener with id {string}',\n  async (world: CustomWorld, appStr: string, id: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      type: 'intentListenerUnsubscribeRequest',\n      meta,\n      payload: {\n        listenerUUID: handleResolve(id, world),\n      },\n    } as IntentListenerUnsubscribeRequest;\n    await world.server.receive(message, uuid);\n  }\n);\n\nfunction raise(\n  cw: CustomWorld,\n  intentName: string,\n  contextType: string,\n  dest: string | null,\n  meta: RaiseIntentRequest['meta']\n): RaiseIntentRequest {\n  const destMeta = dest != null ? createMeta(cw, dest) : null;\n  const message = {\n    type: 'raiseIntentRequest',\n    meta: {\n      ...meta,\n    },\n    payload: {\n      intent: handleResolve(intentName, cw),\n      context: contextMap[contextType],\n      app: dest ? destMeta!.source : null,\n    },\n  } as RaiseIntentRequest;\n  return message;\n}\n\nfunction raiseWithContext(\n  cw: CustomWorld,\n  contextType: string,\n  dest: string | null,\n  meta: RaiseIntentForContextRequest['meta']\n): RaiseIntentForContextRequest {\n  const destMeta = dest != null ? createMeta(cw, dest) : null;\n  const message = {\n    type: 'raiseIntentForContextRequest',\n    meta: {\n      ...meta,\n    },\n    payload: {\n      context: contextMap[contextType],\n      app: dest ? destMeta!.source : null,\n    },\n  } as RaiseIntentForContextRequest;\n  return message;\n}\n\nfunction raiseWithInvalidTarget(\n  cw: CustomWorld,\n  intentName: string,\n  contextType: string,\n  meta: RaiseIntentRequest['meta']\n): RaiseIntentRequest {\n  const message = {\n    type: 'raiseIntentRequest',\n    meta: {\n      ...meta,\n    },\n    payload: {\n      intent: handleResolve(intentName, cw),\n      context: contextMap[contextType],\n      app: 'SPOON',\n    },\n  } as unknown as RaiseIntentRequest;\n  return message;\n}\n\nfunction raiseWithContextAnInvalidTarget(\n  contextType: string,\n  meta: RaiseIntentForContextRequest['meta']\n): RaiseIntentForContextRequest {\n  const message = {\n    type: 'raiseIntentForContextRequest',\n    meta: {\n      ...meta,\n    },\n    payload: {\n      context: contextMap[contextType],\n      app: 'SPOON',\n    },\n  } as unknown as RaiseIntentForContextRequest;\n  return message;\n}\n\nWhen(\n  '{string} raises an intent with contextType {string}',\n  async (world: CustomWorld, appStr: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raiseWithContext(world, contextType, null, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent with contextType {string} on app {string}',\n  async (world: CustomWorld, appStr: string, contextType: string, dest: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raiseWithContext(world, contextType, dest, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent for {string} with contextType {string}',\n  async (world: CustomWorld, appStr: string, intentName: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raise(world, intentName, contextType, null, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent for {string} with contextType {string} on app {string}',\n  async (world: CustomWorld, appStr: string, intentName: string, contextType: string, dest: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raise(world, intentName, contextType, dest, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent for {string} with contextType {string} on an invalid app instance',\n  async (world: CustomWorld, appStr: string, intentName: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raiseWithInvalidTarget(world, intentName, contextType, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent with contextType {string} on an invalid app instance',\n  async (world: CustomWorld, appStr: string, contextType: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raiseWithContextAnInvalidTarget(contextType, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} raises an intent for {string} with contextType {string} on app {string} with requestUuid {string}',\n  async (\n    world: CustomWorld,\n    appStr: string,\n    intentName: string,\n    contextType: string,\n    dest: string,\n    requestUuid: string\n  ) => {\n    const meta = {\n      ...createMeta(world, appStr),\n      requestUuid,\n    };\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = raise(world, intentName, contextType, dest, meta);\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen('we wait for the intent timeout', () => {\n  return new Promise<void>(resolve => {\n    setTimeout(() => resolve(), 2100);\n  });\n});\n\nWhen(\n  '{string} sends a intentResultRequest with eventUuid {string} and contextType {string} and raiseIntentUuid {string}',\n  async (world: CustomWorld, appStr: string, eventUuid: string, contextType: string, raiseIntentUuid: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid1 = world.sc.getInstanceUUID(meta.source)!;\n    const message: IntentResultRequest = {\n      type: 'intentResultRequest',\n      meta: {\n        ...meta,\n      },\n      payload: {\n        intentResult: {\n          context: contextMap[contextType],\n        },\n        intentEventUuid: eventUuid,\n        raiseIntentRequestUuid: raiseIntentUuid,\n      },\n    };\n    await world.server.receive(message, uuid1);\n  }\n);\n\nWhen(\n  '{string} sends a intentResultRequest with eventUuid {string} and void contents and raiseIntentUuid {string}',\n  async (world: CustomWorld, appStr: string, eventUuid: string, raiseIntentUuid: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message: IntentResultRequest = {\n      type: 'intentResultRequest',\n      meta: {\n        ...meta,\n      },\n      payload: {\n        intentResult: {},\n        intentEventUuid: eventUuid,\n        raiseIntentRequestUuid: raiseIntentUuid,\n      },\n    };\n    await world.server.receive(message, uuid);\n  }\n);\n\nWhen(\n  '{string} sends a intentResultRequest with eventUuid {string} and private channel {string} and raiseIntentUuid {string}',\n  async (world: CustomWorld, appStr: string, eventUuid: string, channelId: string, raiseIntentUuid: string) => {\n    const meta = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n    const message: IntentResultRequest = {\n      type: 'intentResultRequest',\n      meta: {\n        ...meta,\n      },\n      payload: {\n        intentResult: {\n          channel: {\n            type: 'private',\n            id: channelId,\n          },\n        },\n        intentEventUuid: eventUuid,\n        raiseIntentRequestUuid: raiseIntentUuid,\n      },\n    };\n    await world.server.receive(message, uuid);\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/messaging.steps.ts",
    "content": "import { Then } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { CustomWorld } from '../world/index.js';\nimport { expect } from 'vitest';\nimport { matchData } from '@finos/testing';\n\nThen('messaging will have outgoing posts', (world: CustomWorld, dt: DataTable) => {\n  const matching = dt.rows().length;\n  let toUse = world.sc?.postedMessages;\n  if (toUse.length > matching) {\n    toUse = toUse.slice(toUse.length - matching, toUse.length);\n  }\n  matchData(world, toUse, dt);\n});\n\nThen('messaging will have {int} posts', (world: CustomWorld, count: number) => {\n  expect(world.sc.postedMessages.length).toEqual(count);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/private-channel.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { createMeta } from './generic.steps.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { handleResolve } from '@finos/testing';\n\ntype CreatePrivateChannelRequest = BrowserTypes.CreatePrivateChannelRequest;\ntype PrivateChannelAddEventListenerRequest = BrowserTypes.PrivateChannelAddEventListenerRequest;\ntype PrivateChannelUnsubscribeEventListenerRequest = BrowserTypes.PrivateChannelUnsubscribeEventListenerRequest;\ntype PrivateChannelDisconnectRequest = BrowserTypes.PrivateChannelDisconnectRequest;\n\nWhen('{string} creates a private channel', (world: CustomWorld, app: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {},\n    type: 'createPrivateChannelRequest',\n  } as CreatePrivateChannelRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} removes event listener {string}', (world: CustomWorld, app: string, listenerUUID: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {\n      listenerUUID,\n    },\n    type: 'privateChannelUnsubscribeEventListenerRequest',\n  } as PrivateChannelUnsubscribeEventListenerRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen(\n  '{string} adds an {string} event listener on {string}',\n  (world: CustomWorld, app: string, listenerType: string, channelId: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        privateChannelId: handleResolve(channelId, world),\n        listenerType,\n      },\n      type: 'privateChannelAddEventListenerRequest',\n    } as PrivateChannelAddEventListenerRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n\nWhen('{string} disconnects from private channel {string}', (world: CustomWorld, app: string, channelId: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n\n  const message = {\n    meta,\n    payload: {\n      channelId: handleResolve(channelId, world),\n    },\n    type: 'privateChannelDisconnectRequest',\n  } as PrivateChannelDisconnectRequest;\n\n  world.server.receive(message, uuid);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/start-app.steps.ts",
    "content": "import { Then, When } from 'quickpickle';\nimport { DataTable } from '@cucumber/cucumber';\nimport { CustomWorld } from '../world/index.js';\nimport { contextMap, createMeta } from './generic.steps.js';\nimport { matchData } from '@finos/testing';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { State } from '../../src/ServerContext.js';\nimport { GetInfoRequest } from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\ntype OpenRequest = BrowserTypes.OpenRequest;\ntype GetAppMetadataRequest = BrowserTypes.GetAppMetadataRequest;\ntype FindInstancesRequest = BrowserTypes.FindInstancesRequest;\ntype WebConnectionProtocol4ValidateAppIdentity = BrowserTypes.WebConnectionProtocol4ValidateAppIdentity;\n\nWhen('{string} is opened with connection id {string}', (world: CustomWorld, app: string, uuid: string) => {\n  const meta = createMeta(world, app);\n  world.sc.setInstanceDetails(uuid, {\n    appId: meta.source.appId,\n    instanceId: meta.source.instanceId!,\n    state: State.Connected,\n  });\n});\n\nWhen('{string} is closed', (world: CustomWorld, app: string) => {\n  const meta = createMeta(world, app);\n  world.server.cleanup(meta.source.instanceId!);\n});\n\nWhen('{string} sends validate', (world: CustomWorld, uuid: string) => {\n  const identity = world.sc.getInstanceDetails(uuid);\n  if (identity) {\n    const message: WebConnectionProtocol4ValidateAppIdentity = {\n      type: 'WCP4ValidateAppIdentity',\n      meta: {\n        connectionAttemptUuid: world.sc.createUUID(),\n        timestamp: new Date(),\n      },\n      payload: {\n        actualUrl: 'something',\n        identityUrl: 'something',\n      },\n    };\n    world.sc.setAppState(identity.instanceId, State.Connected);\n    world.server.receive(message, uuid);\n  } else {\n    throw new Error(`Did not find app identity ${uuid}`);\n  }\n});\n\nWhen('{string} revalidates', (world: CustomWorld, uuid: string) => {\n  const message: WebConnectionProtocol4ValidateAppIdentity = {\n    type: 'WCP4ValidateAppIdentity',\n    meta: {\n      connectionAttemptUuid: world.sc.createUUID(),\n      timestamp: new Date(),\n    },\n    payload: {\n      instanceUuid: uuid,\n      actualUrl: 'something',\n      identityUrl: 'something',\n    },\n  };\n\n  world.server.receive(message, uuid);\n});\n\nThen('running apps will be', async (world: CustomWorld, dataTable: DataTable) => {\n  const apps = await world.sc.getConnectedApps();\n  matchData(world, apps, dataTable);\n});\n\nWhen('{string} opens app {string}', (world: CustomWorld, appStr: string, open: string) => {\n  const from = createMeta(world, appStr);\n  const uuid = world.sc.getInstanceUUID(from.source)!;\n  const message: OpenRequest = {\n    type: 'openRequest',\n    meta: from,\n    payload: {\n      app: {\n        appId: open,\n        desktopAgent: 'n/a',\n      },\n    },\n  };\n  world.server.receive(message, uuid);\n});\n\nWhen(\n  '{string} opens app {string} with context data {string}',\n  (world: CustomWorld, appStr: string, open: string, context: string) => {\n    const from = createMeta(world, appStr);\n    const uuid = world.sc.getInstanceUUID(from.source)!;\n    const message: OpenRequest = {\n      type: 'openRequest',\n      meta: from,\n      payload: {\n        app: {\n          appId: open,\n          desktopAgent: 'n/a',\n        },\n        context: contextMap[context],\n      },\n    };\n    world.server.receive(message, uuid);\n  }\n);\n\nWhen('{string} requests metadata for {string}', (world: CustomWorld, appStr: string, open: string) => {\n  const from = createMeta(world, appStr);\n  const uuid = world.sc.getInstanceUUID(from.source)!;\n  const message: GetAppMetadataRequest = {\n    type: 'getAppMetadataRequest',\n    meta: from,\n    payload: {\n      app: {\n        appId: open,\n        desktopAgent: 'n/a',\n      },\n    },\n  };\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} requests info on the DesktopAgent', (world: CustomWorld, appStr: string) => {\n  const from = createMeta(world, appStr);\n  const uuid = world.sc.getInstanceUUID(from.source)!;\n  const message: GetInfoRequest = {\n    type: 'getInfoRequest',\n    meta: from,\n    payload: {},\n  };\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} findsInstances of {string}', (world: CustomWorld, appStr: string, open: string) => {\n  const from = createMeta(world, appStr);\n  const uuid = world.sc.getInstanceUUID(from.source)!;\n  const message: FindInstancesRequest = {\n    type: 'findInstancesRequest',\n    meta: from,\n    payload: {\n      app: {\n        appId: open,\n      },\n    },\n  };\n  world.server.receive(message, uuid);\n});\n\nWhen('we wait for the listener timeout', () => {\n  return new Promise<void>(resolve => {\n    setTimeout(() => resolve(), 3100);\n  });\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/step-definitions/user-channel.steps.ts",
    "content": "import { When } from 'quickpickle';\nimport { CustomWorld } from '../world/index.js';\nimport { createMeta } from './generic.steps.js';\nimport { BrowserTypes } from '@finos/fdc3-schema';\nimport { handleResolve } from '@finos/testing';\n\ntype GetUserChannelsRequest = BrowserTypes.GetUserChannelsRequest;\ntype GetCurrentChannelRequest = BrowserTypes.GetCurrentChannelRequest;\ntype JoinUserChannelRequest = BrowserTypes.JoinUserChannelRequest;\ntype LeaveCurrentChannelRequest = BrowserTypes.LeaveCurrentChannelRequest;\ntype GetCurrentContextRequest = BrowserTypes.GetCurrentContextRequest;\n\nWhen('{string} gets the list of user channels', (world: CustomWorld, app: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {},\n    type: 'getUserChannelsRequest',\n  } as GetUserChannelsRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} gets the current user channel', (world: CustomWorld, app: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {},\n    type: 'getCurrentChannelRequest',\n  } as GetCurrentChannelRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} leaves the current user channel', (world: CustomWorld, app: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {},\n    type: 'leaveCurrentChannelRequest',\n  } as LeaveCurrentChannelRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen('{string} joins user channel {string}', (world: CustomWorld, app: string, channel: string) => {\n  const meta = createMeta(world, app);\n  const uuid = world.sc.getInstanceUUID(meta.source)!;\n  const message = {\n    meta,\n    payload: {\n      channelId: handleResolve(channel, world),\n    },\n    type: 'joinUserChannelRequest',\n  } as JoinUserChannelRequest;\n\n  world.server.receive(message, uuid);\n});\n\nWhen(\n  '{string} gets the latest context on {string} with type {string}',\n  (world: CustomWorld, app: string, channel: string, type: string) => {\n    const meta = createMeta(world, app);\n    const uuid = world.sc.getInstanceUUID(meta.source)!;\n    const message = {\n      meta,\n      payload: {\n        channelId: handleResolve(channel, world),\n        contextType: handleResolve(type, world),\n      },\n      type: 'getCurrentContextRequest',\n    } as GetCurrentContextRequest;\n\n    world.server.receive(message, uuid);\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/steps.ts",
    "content": "// Main step definitions entry point for quickpickle\n// This file is loaded by vitest as a setupFile\n\nimport { setWorldConstructor } from 'quickpickle';\nimport { CustomWorld } from './world/index.js';\n\n// Set up the world constructor\nsetWorldConstructor(CustomWorld);\n\n// Import all step definitions\nimport './step-definitions/generic.steps.js';\nimport './step-definitions/app-channel.steps.js';\nimport './step-definitions/broadcast.steps.js';\nimport './step-definitions/event-listeners.steps.js';\nimport './step-definitions/heartbeat.steps.js';\nimport './step-definitions/intents.steps.js';\nimport './step-definitions/messaging.steps.js';\nimport './step-definitions/private-channel.steps.js';\nimport './step-definitions/start-app.steps.js';\nimport './step-definitions/user-channel.steps.js';\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/support/TestServerContext.ts",
    "content": "import { FDC3Server } from '../../src/FDC3Server.js';\nimport { ServerContext, InstanceID, State, AppRegistration } from '../../src/ServerContext.js';\nimport { CustomWorld } from '../world/index.js';\nimport { Context } from '@finos/fdc3-context';\nimport { OpenError, AppIdentifier, AppIntent } from '@finos/fdc3-standard';\n\ntype ConnectionDetails = AppRegistration & {\n  msg?: object;\n};\n\ntype MessageRecord = {\n  to?: AppIdentifier;\n  uuid?: InstanceID;\n  msg: object;\n};\n\nexport class TestServerContext implements ServerContext<ConnectionDetails> {\n  public postedMessages: MessageRecord[] = [];\n  private readonly cw: CustomWorld;\n  private instances: ConnectionDetails[] = [];\n  private nextInstanceId: number = 0;\n  private nextUUID: number = 0;\n  private server: FDC3Server | null = null;\n\n  constructor(cw: CustomWorld) {\n    this.cw = cw;\n  }\n\n  setFDC3Server(server: FDC3Server): void {\n    this.server = server;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  async narrowIntents(_raiser: AppIdentifier, appIntents: AppIntent[], _context: Context): Promise<AppIntent[]> {\n    return appIntents;\n  }\n\n  getInstanceDetails(uuid: string) {\n    return this.instances.find(ca => ca.instanceId === uuid);\n  }\n\n  setInstanceDetails(uuid: InstanceID, appId: ConnectionDetails) {\n    if (uuid != appId.instanceId) {\n      throw new Error('UUID mismatch');\n    }\n    this.instances = this.instances.filter(ca => ca.instanceId !== uuid);\n    this.instances.push(appId);\n  }\n\n  async open(appId: string): Promise<InstanceID> {\n    const ni = this.nextInstanceId++;\n    if (appId.includes('missing')) {\n      throw new Error(OpenError.AppNotFound);\n    } else {\n      const uuid = 'uuid-' + ni;\n      this.instances.push({ appId, instanceId: uuid, state: State.Pending });\n      return uuid;\n    }\n  }\n\n  async setAppState(app: InstanceID, newState: State): Promise<void> {\n    const found = this.instances.find(a => a.instanceId == app);\n    if (found) {\n      const currentState = found.state;\n      if (currentState !== State.Terminated && newState === State.Terminated) {\n        this.server?.cleanup(app);\n      }\n      found.state = newState;\n    }\n  }\n\n  async getConnectedApps(): Promise<AppRegistration[]> {\n    return (await this.getAllApps()).filter(a => a.state == State.Connected);\n  }\n\n  async getAllApps(): Promise<AppRegistration[]> {\n    return this.instances.map(x => {\n      return {\n        appId: x.appId,\n        instanceId: x.instanceId,\n        state: x.state,\n      };\n    });\n  }\n\n  async isAppConnected(app: InstanceID): Promise<boolean> {\n    const found = this.instances.find(a => a.instanceId == app && a.state == State.Connected);\n    return found != null;\n  }\n\n  provider(): string {\n    return 'cucumber-provider';\n  }\n  providerVersion(): string {\n    return '1.2.3.TEST';\n  }\n  fdc3Version(): string {\n    return '2.0';\n  }\n\n  createUUID(): string {\n    return 'uuid' + this.nextUUID++;\n  }\n\n  async post(msg: object, to: InstanceID): Promise<void> {\n    if (to == null) {\n      this.postedMessages.push({ msg });\n    } else {\n      const id = this.getInstanceDetails(to);\n      const app = id\n        ? {\n            appId: id!.appId,\n            instanceId: id!.instanceId,\n          }\n        : undefined;\n      this.postedMessages.push({\n        msg,\n        to: app,\n        uuid: to,\n      });\n    }\n  }\n\n  log(message: string): void {\n    this.cw.log(message);\n  }\n\n  /**\n   * USED FOR TESTING\n   */\n  getInstanceUUID(appId: AppIdentifier): InstanceID {\n    this.setInstanceDetails(appId.instanceId!, {\n      appId: appId.appId,\n      instanceId: appId.instanceId!,\n      state: State.Connected,\n    });\n    return appId.instanceId!;\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/test/world/index.ts",
    "content": "import { QuickPickleWorld, QuickPickleWorldInterface } from 'quickpickle';\nimport { TestServerContext } from '../support/TestServerContext.js';\nimport { DefaultFDC3Server } from '../../src/BasicFDC3Server.js';\nimport { BasicDirectory } from '../../src/directory/BasicDirectory.js';\n\nexport interface CustomWorldInterface extends QuickPickleWorldInterface {\n  props: Record<string, any>;\n  sc: TestServerContext;\n  server: DefaultFDC3Server;\n  log: (message: string) => void;\n}\n\nexport class CustomWorld extends QuickPickleWorld implements CustomWorldInterface {\n  props: Record<string, any> = {};\n  sc: TestServerContext = new TestServerContext(this);\n  server: DefaultFDC3Server = new DefaultFDC3Server(this.sc, new BasicDirectory([]), [], false);\n\n  log(message: string): void {\n    console.log(message);\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/tsconfig.json",
    "content": "{\n    \"extends\": \"../../../tsconfig.root.json\",\n    \"compilerOptions\": {\n        \"rootDirs\": [\n            \"src\",\n            \"test\",\n            \"generated\"\n        ],\n        \"outDir\": \"dist\",\n    },\n    \"include\": [\n        \"src\",\n        \"generated\",\n    ],\n    \"exclude\": [\n        \"test/**\",\n        \"dist/**\"\n    ],\n    \"references\": [\n        {\n            \"path\": \"../../../packages/fdc3-standard\"\n        },\n        {\n            \"path\": \"../../../packages/testing\"\n        },\n        {\n            \"path\": \"../../../packages/fdc3-schema\"\n        },\n        {\n            \"path\": \"../../../packages/fdc3-context\"\n        },\n    ]\n}"
  },
  {
    "path": "toolbox/fdc3-for-web/fdc3-web-impl/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\nimport { quickpickle } from 'quickpickle';\n\nexport default defineConfig({\n  plugins: [\n    quickpickle({\n      stepTimeout: 15000,\n    }),\n  ],\n  test: {\n    include: ['test/features/**/*.feature'],\n    setupFiles: ['test/steps.ts'],\n    testTimeout: 30000,\n    reporters: ['default', 'junit'],\n    outputFile: 'test-results.xml',\n    coverage: {\n      enabled: true,\n      provider: 'v8',\n      reporter: ['text', 'lcov', 'json'],\n      reportsDirectory: './coverage',\n      include: ['src/**/*.ts'],\n      exclude: ['src/**/*.d.ts', 'src/**/*.test.ts', 'src/**/*.spec.ts'],\n    },\n  },\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/channel_selector.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Channel selector</title>\n    <script type=\"module\" src=\"./src/channel_selector.ts\"></script>\n\n    <style>\n      .glyph {\n        font-size: 12px;\n        padding: 2px 6px;\n        border-radius: 50%;\n        border-width: 1.5px;\n        border-style: solid;\n        font-weight: bold;\n      }\n      \n      #list {\n        background-color: white;\n        margin: 10px;\n        padding: 20px;\n        border-radius: 10px;\n        box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;\n        font-family: sans-serif;\n        display: none;\n        position: fixed;\n        bottom: 4px;\n        right: 4px;\n\n        & > div {\n          font-size: 18px;\n          height: 24px;\n          border-radius: 16px;\n          padding: 0 4px;\n\n          &:hover,\n          &:focus {\n            background-color: #ccc;\n            cursor: pointer;\n          }\n        }\n        .name {\n          margin-left: 8px;\n          position: relative;\n          top: 2px;\n        }\n      }\n      #tokens {\n        display: none;\n        cursor: pointer;\n      }\n\n      body[data-expanded=\"true\"] #list {\n        display: block;\n      }\n      \n      body[data-expanded=\"false\"] #tokens {\n        display: block;\n      }\n\n      .logo path {\n        stroke: white;\n        stroke-width: 10;\n        paint-order: fill;\n      }\n\n      #logo {\n        filter: drop-shadow(rgba(0, 0, 0, 0.4) 0px 0px 3px)\n      }\n    </style>\n  </head>\n  <body data-expanded=\"false\">\n    <div id=\"list\"></div>\n\n    <div id=\"tokens\">\n      <svg class=\"logo\" version=\"1.1\" id=\"logo\" xmlns=\"http://www.w3.org/2000/svg\" x=\"0px\" y=\"0px\" viewBox=\"-10 -10 450 505\">\n        <g>\n          <path class=\"st0_tUmL\" d=\"M428.27,363.7v-234L239.55,238.65c0.11,0.99,0.58,1.85,0.58,2.87c0,11.73-7.91,21.26-18.57,24.5v217.03 L428.27,363.7L428.27,363.7z\"></path>\n          <path class=\"st1_dMUi\" d=\"M234.38,225.9l186.09-107.44v-0.58L214.13,0L7.8,117.89v0.58L193.89,225.9c4.75-6.15,11.86-10.38,20.24-10.38 C222.52,215.52,229.63,219.75,234.38,225.9L234.38,225.9z\"></path>\n          <path class=\"st2_WNwV\" d=\"M188.72,238.65L0,129.69v234l206.71,119.34V266.02c-10.67-3.24-18.57-12.77-18.57-24.5 C188.14,240.5,188.6,239.64,188.72,238.65L188.72,238.65z\"></path>\n        </g>\n      </svg>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/eslint.config.mjs",
    "content": "import globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  { languageOptions: { globals: globals.browser } },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n];\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/intent_resolver.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Channel selector</title>\n    <script type=\"module\" src=\"./src/intent_resolver.ts\"></script>\n    <style>\n      .list {\n        background-color: #efefef;\n        display: flex;\n        flex-direction: column;\n        gap: 2px;\n        height: fit-content;\n        overflow-y: auto;\n        scrollbar-width: thin;\n        scrollbar-color: #ace;\n        border-radius: 8px;\n        width: fit-content;\n        bottom: 4px;\n        right: 0;\n\n        & > div {\n          font-size: 18px;\n          border-radius: 16px;\n          height: 22px;\n          padding: 0 8px;\n\n          &:hover,\n          &:focus {\n            background-color: #ccc;\n            cursor: pointer;\n          }\n\n          img {\n            width: 18px;\n            max-height: 18px;\n            margin-right: 4px;\n            position: relative;\n            top: 2px;\n          }\n        }\n      }\n\n      h1 {\n        margin-top: 8px;\n        margin-bottom: 0;\n      }\n\n      .frontmatter {\n        margin: 8px 0;\n      }\n\n      [data-visible=\"false\"] {\n        display: none;\n      }\n\n      [role=\"tablist\"] {\n        display: flex;\n        gap: 4px;\n        width: fit-content;\n        border-radius: 4px;\n        padding: 4px;\n        margin-left: auto;\n        margin-right: auto;\n        margin-top: 8px;\n        margin-bottom: 8px;\n      }\n\n      [role=\"tab\"] {\n        border-radius: 4px;\n        padding: 4px 8px;\n        cursor: pointer;\n        background: #0086bf44;\n        color: #0086bf;\n\n        &:hover {\n          color: #fff;\n        }\n\n        &[aria-selected=\"true\"] {\n          background: #0086bf;\n          color: #fff;\n        }\n      }\n\n      .button-row {\n        display: flex;\n        justify-content: center;\n        margin-top: 8px;\n      }\n\n      .tablist {\n        display: flex;\n        justify-content: left;\n        margin-top: 8px;\n      }\n\n      #cancel {\n        border-radius: 4px;\n        text-align: center;\n      }\n\n      .container {\n        display: flex;\n        flex-direction: column;\n        background-color: white;\n        margin: 10px;\n        padding: 20px;\n        border-radius: 10px;\n        box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;\n        font-family: sans-serif;\n      }\n\n      dialog {\n        border: none;\n        background: transparent;\n      }\n    </style>\n  </head>\n\n  <body data-visible=\"false\">\n    <dialog>\n      <div class=\"container\">\n        <h1>Intent Resolver</h1>\n  \n        <div class=\"frontmatter\">\n          Resolve intent for:\n          <select id=\"displayIntent\"></select>\n          <br />\n        </div>\n  \n        <div class=\"tablist\" role=\"tablist\">\n          <div role=\"tab\" tabindex=\"0\" aria-selected=\"true\" data-list-ref=\"new-list\">New Apps</div>\n          <div role=\"tab\" tabindex=\"0\" aria-selected=\"false\" data-list-ref=\"open-list\">Open Apps</div>\n        </div>\n  \n        <div id=\"new-list\" class=\"list\" data-visible=\"true\"></div>\n  \n        <div id=\"open-list\" class=\"list\" data-visible=\"false\"></div>\n  \n        <div class=\"button-row\">\n          <button id=\"cancel\">Cancel</button>\n        </div>\n      </div>\n    </dialog>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/package.json",
    "content": "{\n  \"name\": \"fdc3-for-web-reference-ui\",\n  \"private\": true,\n  \"version\": \"2.2.2\",\n  \"license\": \"Apache-2.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc && vite build --base=/toolbox/fdc3-reference-ui/\",\n    \"clean\": \"npx rimraf dist\",\n    \"preview\": \"vite preview\",\n    \"lint\": \"eslint src/\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.19.0\",\n    \"@types/color\": \"^4.2.0\",\n    \"color\": \"^4.2.3\",\n    \"eslint\": \"^9.32.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"globals\": \"^15.14.0\",\n    \"typescript\": \"^5.6.3\",\n    \"typescript-eslint\": \"^8.17.0\",\n    \"vite\": \"^6.4.2\"\n  },\n  \"dependencies\": {\n    \"@finos/fdc3\": \"2.2.2\"\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/src/channel_selector.ts",
    "content": "import {\n  Channel,\n  Fdc3UserInterfaceChannelSelected,\n  Fdc3UserInterfaceHello,\n  Fdc3UserInterfaceRestyle,\n  isFdc3UserInterfaceChannels,\n  isFdc3UserInterfaceHandshake,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\nimport { selectHighestContrast } from './contrast.js';\n\nconst fillChannels = (data: Channel[], selected: string | null, messageClickedChannel: (s: string | null) => void) => {\n  const list = document.getElementById('list')!;\n  list.innerHTML = '';\n\n  data.forEach(({ id, displayMetadata }) => {\n    const node = document.createElement('div');\n    node.setAttribute('tabIndex', '0');\n\n    const span = document.createElement('span');\n    span.classList.add('glyph');\n\n    if (displayMetadata?.color) {\n      span.style.color = selectHighestContrast(displayMetadata.color, 'white', 'black');\n      span.style.backgroundColor = displayMetadata.color;\n      span.style.borderColor = displayMetadata.color;\n    }\n    span.textContent = displayMetadata?.glyph ?? '';\n    node.appendChild(span);\n\n    if (displayMetadata?.name) {\n      const span2 = document.createElement('span');\n      span2.classList.add('name');\n      span2.textContent = displayMetadata.name;\n      node.appendChild(span2);\n    }\n\n    list.appendChild(node);\n    node.addEventListener('click', () => {\n      messageClickedChannel(id);\n    });\n\n    if (id === selected) {\n      node.setAttribute('aria-selected', 'true');\n      node.style.backgroundColor = '#bbb';\n    }\n  });\n\n  //add an element for leaving all channels\n  const node = document.createElement('div');\n  node.setAttribute('tabIndex', '0');\n\n  const span = document.createElement('span');\n  span.classList.add('glyph');\n  span.textContent = 'X';\n  node.appendChild(span);\n\n  const span2 = document.createElement('span');\n  span2.classList.add('name');\n  span2.textContent = 'none';\n  node.appendChild(span2);\n\n  list.appendChild(node);\n  node.addEventListener('click', () => {\n    messageClickedChannel(null);\n  });\n\n  if (selected === null) {\n    node.setAttribute('aria-selected', 'true');\n    node.style.backgroundColor = '#bbb';\n  }\n};\n\nwindow.addEventListener('load', () => {\n  const parent = window.parent;\n  const logo = document.getElementById('logo')!;\n\n  const mc = new MessageChannel();\n  const myPort = mc.port1;\n\n  myPort.addEventListener('message', ({ data }) => {\n    console.debug('Received message: ', data);\n\n    if (isFdc3UserInterfaceHandshake(data)) {\n      collapse();\n    } else if (isFdc3UserInterfaceChannels(data)) {\n      logo.removeEventListener('click', expand);\n      const { userChannels, selected } = data.payload;\n      fillChannels(userChannels, selected, channelStr => {\n        const message: Fdc3UserInterfaceChannelSelected = {\n          type: 'Fdc3UserInterfaceChannelSelected',\n          payload: {\n            selected: channelStr || null,\n          },\n        };\n        myPort.postMessage(message);\n        console.log('Channel Selected: ', message);\n        collapse();\n      });\n\n      const selectedChannel = userChannels.find(c => c.id === selected);\n      logo.style.fill = selectedChannel?.displayMetadata?.color ?? 'white';\n      console.log('Adding click event listener');\n      logo.addEventListener('click', expand);\n    }\n  });\n  myPort.start();\n\n  const helloMessage: Fdc3UserInterfaceHello = {\n    type: 'Fdc3UserInterfaceHello',\n    payload: {\n      implementationDetails: 'FDC3 Reference Channel Selector UI',\n      initialCSS: {\n        width: `${8 * 6}px`,\n        height: `${8 * 8}px`,\n        right: '2px',\n        bottom: '8px',\n        zIndex: '1000',\n        'z-index': '1000',\n        position: 'fixed',\n      },\n    },\n  };\n  // nosemgrep\n  parent.postMessage(helloMessage, '*', [mc.port2]);\n\n  const expand = () => {\n    document.body.setAttribute('data-expanded', 'true');\n    const restyleMessage: Fdc3UserInterfaceRestyle = {\n      type: 'Fdc3UserInterfaceRestyle',\n      payload: {\n        updatedCSS: {\n          width: `100%`,\n          height: `100%`,\n          top: '0',\n          left: '0',\n          zIndex: '1000',\n          'z-index': '1000',\n          position: 'fixed',\n        },\n      },\n    };\n    myPort.postMessage(restyleMessage);\n  };\n\n  const collapse = () => {\n    const restyleMessage: Fdc3UserInterfaceRestyle = {\n      type: 'Fdc3UserInterfaceRestyle',\n      payload: {\n        updatedCSS: {\n          width: `${8 * 6}px`,\n          height: `${8 * 8}px`,\n          right: '8px',\n          bottom: '2px',\n          zIndex: '1000',\n          'z-index': '1000',\n          position: 'fixed',\n        },\n      },\n    };\n    myPort.postMessage(restyleMessage);\n\n    // If you immediately change to the logo, before the iframe has a chance to finish restyling,\n    // you see a flicker of a giant, colored logo.\n    // Here, we wait a negligible amount of time, and hope that the restyling has finished. This avoids the flicker.\n    // It's not a *good* idea, it's just the best available, since we don't know when the restyle finishes.\n    setTimeout(() => {\n      document.body.setAttribute('data-expanded', 'false');\n    }, 15);\n  };\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/src/contrast.ts",
    "content": "import Color from 'color';\n\nexport function selectHighestContrast(bgColorCSS: string, ...candidates: string[]) {\n  const bgColor = Color(bgColorCSS);\n  const contrasts: number[] = candidates.map(candidate => {\n    return bgColor.contrast(Color(candidate));\n  });\n  let bestCandidate = candidates[0],\n    highestContrast = contrasts[0];\n  for (let i = 1; i < contrasts.length; i++) {\n    if (contrasts[i] > highestContrast) {\n      bestCandidate = candidates[i];\n      highestContrast = contrasts[i];\n    }\n  }\n  return bestCandidate;\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/src/intent_resolver.ts",
    "content": "import { Icon } from '@finos/fdc3';\nimport { AppIntent } from '@finos/fdc3';\nimport {\n  Fdc3UserInterfaceHello,\n  Fdc3UserInterfaceResolve,\n  Fdc3UserInterfaceResolveAction,\n  Fdc3UserInterfaceRestyle,\n  isFdc3UserInterfaceResolve,\n} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes.js';\n\nconst setup = (\n  data: Fdc3UserInterfaceResolve['payload'],\n  callback: (payload: Fdc3UserInterfaceResolveAction['payload']) => void\n) => {\n  document.body.setAttribute('data-visible', 'true');\n  document.querySelector('dialog')?.showModal();\n\n  const intentSelect = document.getElementById('displayIntent') as HTMLSelectElement;\n\n  const justIntents = data.appIntents.map(({ intent }) => intent);\n  const doneIntents = new Set();\n\n  justIntents.forEach(({ name, displayName }) => {\n    if (doneIntents.has(name)) {\n      return;\n    }\n    doneIntents.add(name);\n    const option = document.createElement('option');\n    option.textContent = displayName as string;\n    option.value = name;\n    intentSelect.appendChild(option);\n  });\n\n  intentSelect.addEventListener('change', e => {\n    if (e.target) {\n      const option = e.target as HTMLOptionElement;\n      fillList(\n        data.appIntents.filter(ai => ai.intent.name == option.value),\n        option.value,\n        callback\n      );\n    }\n  });\n\n  fillList(\n    data.appIntents.filter(ai => ai.intent.name == intentSelect.value),\n    intentSelect.value,\n    callback\n  );\n\n  const tabs = Array.from(document.querySelectorAll(\"[role='tab']\"));\n  tabs.forEach(tab => {\n    tab.addEventListener('click', () => {\n      // Remove selected state from every tab\n      tabs.forEach(t => {\n        t.setAttribute('aria-selected', 'false');\n      });\n      // Hide lists\n      Array.from(document.querySelectorAll('.list')).forEach(elem => {\n        elem.setAttribute('data-visible', 'false');\n      });\n\n      tab.setAttribute('aria-selected', 'true');\n      const listRef = tab.getAttribute('data-list-ref')!;\n      document.getElementById(listRef)!.setAttribute('data-visible', 'true');\n    });\n  });\n\n  document.getElementById('cancel')?.addEventListener('click', () => {\n    callback({\n      action: 'cancel',\n    });\n  });\n};\n\nfunction createIcon(icons: Icon[] | undefined): HTMLElement {\n  const img = document.createElement('img');\n  if (icons && icons.length > 0) {\n    img.src = icons[0].src;\n  } else {\n    img.style.opacity = '0';\n  }\n\n  return img;\n}\n\nconst fillList = (\n  ai: AppIntent[],\n  intent: string,\n  callback: (payload: Fdc3UserInterfaceResolveAction['payload']) => void\n) => {\n  const allApps = ai.flatMap(a => a.apps);\n  const openApps = allApps.filter(a => a.instanceId);\n  const newApps = allApps.filter(a => !a.instanceId);\n\n  // first, populate the \"New Apps\" tab\n  const newList = document.getElementById('new-list') as HTMLDivElement;\n\n  newList.innerHTML = '';\n  newApps.forEach(({ appId, title, name, icons }) => {\n    const node = document.createElement('div');\n    node.setAttribute('tabIndex', '0');\n    node.setAttribute('data-appId', appId);\n\n    const span = document.createElement('span');\n    span.textContent = title ?? name ?? appId;\n\n    const img = createIcon(icons);\n\n    node.appendChild(img);\n    node.appendChild(span);\n\n    node.addEventListener('click', () => {\n      callback({\n        action: 'click',\n        intent,\n        appIdentifier: {\n          appId,\n        },\n      });\n    });\n\n    node.addEventListener('hover', () => {\n      callback({\n        action: 'hover',\n        intent,\n        appIdentifier: {\n          appId,\n        },\n      });\n    });\n\n    newList.appendChild(node);\n  });\n\n  // then, populate the \"Open Apps\" tab\n  const openList = document.getElementById('open-list')!;\n  openList.innerHTML = '';\n\n  openApps.forEach(({ appId, title, icons, instanceId }) => {\n    const node = document.createElement('div');\n    node.setAttribute('tabIndex', '0');\n    node.setAttribute('data-appId', appId);\n\n    const span = document.createElement('span');\n    span.textContent = title ?? appId;\n\n    const img = createIcon(icons);\n\n    node.appendChild(img);\n    node.appendChild(span);\n\n    node.addEventListener('click', () => {\n      callback({\n        action: 'click',\n        intent,\n        appIdentifier: {\n          appId,\n          instanceId,\n        },\n      });\n    });\n\n    node.addEventListener('hover', () => {\n      callback({\n        action: 'hover',\n        intent,\n        appIdentifier: {\n          appId,\n          instanceId,\n        },\n      });\n    });\n\n    openList.appendChild(node);\n  });\n};\n\nwindow.addEventListener('load', () => {\n  const parent = window.parent;\n\n  const mc = new MessageChannel();\n  const myPort = mc.port1;\n\n  myPort.addEventListener('message', ({ data }) => {\n    console.debug('Received message: ', data);\n    if (isFdc3UserInterfaceResolve(data)) {\n      const restyleMessage: Fdc3UserInterfaceRestyle = {\n        type: 'Fdc3UserInterfaceRestyle',\n        payload: {\n          updatedCSS: {\n            width: '100%',\n            height: '100%',\n            top: '0',\n            left: '0',\n            position: 'fixed',\n            display: 'block',\n          },\n        },\n      };\n      myPort.postMessage(restyleMessage);\n\n      setup(data.payload, payload => {\n        document.querySelector('dialog')?.close();\n        const resolveAction: Fdc3UserInterfaceResolveAction = {\n          type: 'Fdc3UserInterfaceResolveAction',\n          payload,\n        };\n        myPort.postMessage(resolveAction);\n\n        const restyleMessage: Fdc3UserInterfaceRestyle = {\n          type: 'Fdc3UserInterfaceRestyle',\n          payload: {\n            updatedCSS: {\n              width: '0',\n              height: '0',\n              display: 'none',\n            },\n          },\n        };\n\n        myPort.postMessage(restyleMessage);\n      });\n    }\n  });\n  myPort.start();\n\n  const helloMessage: Fdc3UserInterfaceHello = {\n    type: 'Fdc3UserInterfaceHello',\n    payload: {\n      implementationDetails: '',\n      initialCSS: {\n        width: '0',\n        height: '0',\n      },\n    },\n  };\n  // nosemgrep\n  parent.postMessage(helloMessage, '*', [mc.port2]);\n});\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "toolbox/fdc3-for-web/reference-ui/vite.config.ts",
    "content": "import { defineConfig } from 'vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  server: { port: 4002 },\n  build: {\n    outDir: 'dist',\n    rollupOptions: {\n      input: {\n        channelSelector: 'channel_selector.html',\n        intentResolver: 'intent_resolver.html',\n      },\n    },\n  },\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\n.eslintcache\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "toolbox/fdc3-workbench/NOTICE",
    "content": "FDC3 Workbench - Fintech Open Source Foundation (https://www.finos.org/)\nCopyright 2021-2023 Finsemble, inc. info@finsemble.com\nCopyright 2021-2023 Contributors to the FDC3 standards project\n"
  },
  {
    "path": "toolbox/fdc3-workbench/README.md",
    "content": "# <a href='http://fdc3.finos.org'><img src='https://fdc3.finos.org/img/fdc3-logo-2019-color.png' height='150' alt='FDC3 Logo' aria-label='fdc3.finos.org' /></a>\n\n# FDC3 Workbench\nWhen developing interoperability for your application with other apps on a Financial services desktop, using the [FDC3 standard](https://fdc3.finos.org/docs/fdc3-intro), the first step is often to develop a test harness or workbench tool with which to exchange messaging. The FDC3 Workbench is designed to provide that tooling so that you can focus on implementing FDC3 support in your application.\n\n_Created and contributed to [FDC3](http://fdc3.finos.org) by [Finsemble, Inc.](https://finsemble.com/) in 2021._\n\n## Getting Started\n\n1. Clone the repository\n\n`git clone https://github.com/finos/FDC3.git`\n\n2. Install dependencies\n\n`cd toolbox/fdc3-workbench & npm run install`\n\n3. Start the development server\n\n`npm run dev`\n\n4. Add the URL http://localhost:3000 to your FDC3-enabled container or desktop agent and ensure it has access to the `window.fdc3` object.\n\n## Packages\n\nCore:\n- [Create React App](https://github.com/facebook/create-react-app) - with TypeScript\n- [MATERIAL-UI](https://material-ui.com) - v4\n- [MobX](https://mobx.js.org/README.html) - state management\n\nAlso using Eslint, Husky and Prettier please configure your IDE to work properly with code style rules.\n\nMinor:\n- [JsonEditor](https://github.com/josdejong/jsoneditor) - lib to add json editor field with json schema validation\n- [nanoid](https://www.npmjs.com/package/nanoid) - A tiny, secure, URL-friendly, unique string ID generator for JavaScript.\n\n## Known Issues\n\n- The following console error may appear periodically: `Warning: findDOMNode is deprecated in StrictMode.`, this is a [well-known issue in material-ui](https://github.com/mui-org/material-ui/issues/13394) and will be fixed in v5, which (at the time of writing) is currently in beta.\n"
  },
  {
    "path": "toolbox/fdc3-workbench/eslint.config.mjs",
    "content": "import react from 'eslint-plugin-react';\nimport _import from 'eslint-plugin-import';\nimport { fixupPluginRules } from '@eslint/compat';\nimport globals from 'globals';\nimport pluginJs from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n  {\n    languageOptions: {\n      parserOptions: {\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  { files: ['**/*.{js,mjs,cjs,ts}'] },\n  {\n    ignores: [\n      '**/.github/',\n      '**/build/',\n      '**/dist/',\n      '**/node_modules/',\n      '**/*.d.ts',\n      '**/*.md',\n      '**/yarn.lock',\n      '**/package.json',\n    ],\n  },\n  pluginJs.configs.recommended,\n  ...tseslint.configs.recommended,\n  eslintConfigPrettier,\n  {\n    plugins: {\n      react,\n      import: fixupPluginRules(_import),\n    },\n\n    languageOptions: {\n      globals: {\n        ...globals.browser,\n        ...globals.commonjs,\n        fdc3: 'readonly',\n      },\n\n      parserOptions: {\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n    },\n\n    settings: {\n      react: {\n        version: 'detect',\n      },\n    },\n\n    rules: {\n      'react/jsx-uses-vars': 2,\n      'class-methods-use-this': 0,\n      'no-plusplus': 0,\n      'no-undef': 2,\n      'prefer-arrow-callback': 1,\n\n      'prefer-destructuring': [\n        'warn',\n        {\n          object: true,\n          array: false,\n        },\n      ],\n\n      'quote-props': ['warn', 'as-needed'],\n      'lines-between-class-members': 1,\n      '@typescript-eslint/no-unused-vars': 1,\n      'prefer-template': 1,\n      'arrow-parens': 1,\n      'no-extra-semi': 1,\n      'no-shadow': 1,\n      'import/first': 1,\n      '@typescript-eslint/no-use-before-define': 1,\n      'no-redeclare': 1,\n\n      'arrow-body-style': [\n        'warn',\n        'as-needed',\n        {\n          requireReturnForObjectLiteral: true,\n        },\n      ],\n\n      'one-var-declaration-per-line': ['warn', 'always'],\n      'no-mixed-operators': 1,\n      'no-multiple-empty-lines': 1,\n      'no-multi-spaces': 1,\n      'default-case': 1,\n      'no-unneeded-ternary': 1,\n      'operator-assignment': ['warn', 'never'],\n\n      'object-property-newline': [\n        'warn',\n        {\n          allowAllPropertiesOnSameLine: true,\n        },\n      ],\n\n      'new-cap': 1,\n      'no-case-declarations': 1,\n      'react/prop-types': 0,\n      'react/no-string-refs': 0,\n    },\n  },\n];\n"
  },
  {
    "path": "toolbox/fdc3-workbench/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"/favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <meta\n      name=\"description\"\n      content=\"FDC3 workbench application, designed to help develop and test FDC3 integrations\"\n    />\n    <link rel=\"apple-touch-icon\" href=\"/fdc3-icon-192.png\" />\n    <link rel=\"manifest\" href=\"/manifest.json\" />\n    <title>FDC3 Workbench</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "toolbox/fdc3-workbench/package.json",
    "content": "{\n  \"name\": \"fdc3-workbench\",\n  \"version\": \"2.2.2\",\n  \"private\": true,\n  \"homepage\": \"https://fdc3.finos.org\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/finos/FDC3.git\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"start\": \"vite\",\n    \"preview\": \"vite preview\",\n    \"build\": \"tsc && vite build\",\n    \"lint\": \" eslint src/\",\n    \"lint:fix\": \"eslint --fix src/**/*.{ts,tsx} && prettier --write src/**/*.{ts,tsx}\"\n  },\n  \"eslintConfig\": {\n    \"extends\": [\n      \"react-app\"\n    ]\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"devDependencies\": {\n    \"@apidevtools/json-schema-ref-parser\": \"11.7.2\",\n    \"buffer\": \"^6.0.3\",\n    \"path-browserify\": \"^1.0.1\",\n    \"@eslint/compat\": \"^1.2.5\",\n    \"@eslint/js\": \"^9.19.0\",\n    \"@finos/fdc3\": \"2.2.2\",\n    \"@emotion/react\": \"^11.11.4\",\n    \"@emotion/styled\": \"^11.11.5\",\n    \"@fontsource/roboto\": \"5.1.0\",\n    \"@fontsource/source-code-pro\": \"5.1.0\",\n    \"@mui/icons-material\": \"^5.15.20\",\n    \"@mui/material\": \"^5.15.20\",\n    \"@mui/lab\": \"^5.0.0-alpha.170\",\n    \"@types/jsoneditor\": \"^8.6.1\",\n    \"@types/react-dom\": \"18.3.1\",\n    \"@vitejs/plugin-legacy\": \"^6.0.2\",\n    \"@vitejs/plugin-react\": \"^4.3.2\",\n    \"eslint\": \"^9.32.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-import\": \"^2.31.0\",\n    \"eslint-plugin-react\": \"^7.37.1\",\n    \"fdc3-1.2\": \"npm:@finos/fdc3@1.2.x\",\n    \"globals\": \"^15.14.0\",\n    \"jsoneditor\": \"^9.10.5\",\n    \"lint-staged\": \"^15.2.10\",\n    \"mobx\": \"^6.13.3\",\n    \"mobx-react\": \"^7.6.0\",\n    \"nanoid\": \"^3.3.7\",\n    \"normalize.css\": \"^8.0.1\",\n    \"pretty-quick\": \"^4.0.0\",\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\",\n    \"terser\": \"^5.34.1\",\n    \"typescript\": \"^5.6.3\",\n    \"typescript-eslint\": \"^8.17.0\",\n    \"uuid\": \"^9.0.1\",\n    \"vite\": \"^6.4.2\",\n    \"web-vitals\": \"^1.1.2\"\n  }\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/public/manifest.json",
    "content": "{\n  \"short_name\": \"FDC3 Workbench\",\n  \"name\": \"FDC3 Workbench\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n      \"sizes\": \"64x64 32x32 24x24 16x16\",\n      \"type\": \"image/x-icon\"\n    },\n    {\n      \"src\": \"fdc3-icon-256.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"256x256\"\n    },\n    {\n      \"src\": \"fdc3-icon-192.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"192x192\"\n    }\n  ],\n  \"start_url\": \".\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/public/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/App.css",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nhtml {\n  font-size: 15px;\n  height: 100%;\n}\n\nbody {\n  background-color: #f7f7f7;\n  font-size: 14px;\n  font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;\n  height: 100%;\n}\n\n#root {\n  height: 100%;\n}\n\n#providerInfo {\n  border-collapse: collapse;\n}\n\n#providerInfo th {\n  border-right: 1px solid white;\n  padding: 5px;\n  text-align: right;\n  text-transform: uppercase;\n  margin: 0px;\n  font-weight: normal;\n}\n\n#providerInfo td {\n  padding-left: 5px;\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/App.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useEffect, useState } from 'react';\nimport { ThemeProvider, createTheme } from '@mui/material/styles';\nimport { Grid, Paper, Tabs, Tab, Typography, Link, Snackbar, Alert, SnackbarCloseReason } from '@mui/material';\nimport { observer } from 'mobx-react';\nimport 'normalize.css';\nimport '@fontsource/roboto';\nimport '@fontsource/source-code-pro';\nimport { TabPanel } from './components/common/TabPanel.js';\nimport { Header } from './components/Header.js';\nimport { Channels } from './components/Channels.js';\nimport { Workbench } from './components/Workbench/Workbench.js';\nimport { ContextCreate } from './components/ContextCreate.js';\nimport { Intents } from './components/Intents.js';\nimport { AppChannels } from './components/AppChannels.js';\nimport snackbarStore from './store/SnackbarStore.js';\nimport './App.css' with { type: 'css' };\nimport { getWorkbenchAgent } from './utility/Fdc3Api.js';\n\nconst mainTheme = createTheme({\n  palette: {\n    primary: {\n      light: '#005d85',\n      main: '#0086bf',\n      dark: '#339ecb',\n      contrastText: '#fff',\n    },\n    secondary: {\n      light: '#ff7961',\n      main: '#f44336',\n      dark: '#ba000d',\n      contrastText: '#fff',\n    },\n  },\n  components: {\n    MuiLink: {\n      defaultProps: {\n        underline: 'hover',\n      },\n    },\n    MuiTableCell: {\n      defaultProps: {\n        padding: 'normal',\n      },\n      styleOverrides: {\n        root: {\n          padding: '1px',\n        },\n      },\n    },\n  },\n});\n\nmainTheme.typography.h4 = {\n  fontFamily: 'Source Code Pro',\n  fontSize: '20px',\n  color: '#0086bf',\n  paddingLeft: '4px',\n  paddingBottom: '11px',\n};\n\nmainTheme.typography.h5 = {\n  fontSize: '16px',\n};\n\nmainTheme.typography.body1 = {\n  fontSize: '1rem',\n  fontFamily: 'Roboto, Helvetica, Arial, sans-serif',\n  fontWeight: 400,\n  lineHeight: 1.5,\n  letterSpacing: '0.00938em',\n  marginBlockStart: '10px',\n  marginBlockEnd: '10px',\n};\n\nconst classes = {\n  root: {\n    flexGrow: 1,\n  },\n  header: {\n    mb: 2,\n  },\n  body: {\n    height: '100%',\n  },\n  paper: {\n    mt: 2,\n    p: 2,\n    height: '100%',\n    '&:first-of-type': {\n      mt: 0,\n    },\n  },\n  tabs: {\n    borderBottomColor: '#acb2c0',\n    borderBottomStyle: 'solid',\n    borderBottomWidth: '1px',\n    minHeight: '28px',\n    \"& [aria-selected='true']\": {\n      backgroundColor: 'rgba(0, 134, 191, 0.21)',\n    },\n  },\n  indicator: {\n    backgroundColor: '#00bbe1',\n  },\n  footer: {\n    fontSize: '10px',\n    fontStyle: 'italic',\n    color: '#5b606f',\n    flexDirection: 'row',\n    justifyContent: 'center',\n    m: 2,\n    '& *:first-of-type': {\n      paddingTop: '27px',\n    },\n  },\n  link: {\n    color: '#5b606f',\n    fontWeight: 'bold',\n    '&:hover': {\n      color: '#5b606f',\n    },\n  },\n  workbench: {\n    mt: { xs: '30px', md: 0 },\n  },\n} as const;\n\nconst openAPIDocs = (event: React.MouseEvent<HTMLElement>) => {\n  event.preventDefault();\n  window.open('https://fdc3.finos.org/docs/api/overview', 'FDC3APIDocs');\n  return false;\n};\n\nconst openSpecAccessDocs = (event: React.MouseEvent<HTMLElement>) => {\n  event.preventDefault();\n  window.open('https://fdc3.finos.org/docs/api/spec#api-access', 'FDC3APIDocs');\n  return false;\n};\n\nconst openSupportedPlatformsDocs = (event: React.MouseEvent<HTMLElement>) => {\n  event.preventDefault();\n  window.open('https://fdc3.finos.org/docs/supported-platforms', 'FDC3APIDocs');\n  return false;\n};\n\nexport const App = observer(() => {\n  const [fdc3Available, setFdc3Available] = useState(false);\n  const [openSnackbar, setOpenSnackbar] = useState(false);\n  const [tabIndex, setTabIndex] = useState(0);\n  const [contextName, setContextName] = useState('');\n\n  const handleTabChange = (event: React.ChangeEvent<object> | null, newIndex: number, name: string = '') => {\n    setContextName(name);\n    setTabIndex(newIndex);\n  };\n\n  const handleClose = (event?: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) => {\n    if (reason === 'clickaway') {\n      return;\n    }\n\n    setOpenSnackbar(false);\n    setTimeout(() => snackbarStore.clearSnackbarData(), 500);\n  };\n\n  //check if the FDC3 API is available so we know whether to render\n  useEffect(() => {\n    (async () => {\n      try {\n        await getWorkbenchAgent();\n        setFdc3Available(true);\n      } catch (e) {\n        console.warn('No FDC3 desktop agent was found', e);\n      }\n    })();\n  }, []);\n\n  useEffect(() => {\n    setOpenSnackbar(!!snackbarStore.snackbarData);\n  }, [snackbarStore.snackbarData]);\n\n  return (\n    <ThemeProvider theme={mainTheme}>\n      <Grid sx={classes.root} container>\n        <Grid sx={classes.header} container item xs={12}>\n          <Header fdc3Available={fdc3Available} />\n        </Grid>\n        {fdc3Available ? (\n          <Grid sx={classes.body} container spacing={2} item xs={12} style={{ marginLeft: '0px' }}>\n            <Grid item xs={12} md={8} style={{ flex: 1 }}>\n              <Paper sx={classes.paper}>\n                <Tabs\n                  value={tabIndex}\n                  indicatorColor=\"primary\"\n                  onChange={handleTabChange}\n                  variant=\"scrollable\"\n                  scrollButtons=\"auto\"\n                  sx={{\n                    ...classes.tabs,\n                    '& .MuiTabs-indicator': classes.indicator,\n                  }}\n                >\n                  <Tab label=\"Contexts\" />\n                  <Tab label=\"Intents\" />\n                  <Tab label=\"User Channels\" />\n                  <Tab label=\"App Channels\" />\n                </Tabs>\n                <TabPanel value={tabIndex} index={0}>\n                  <ContextCreate contextName={contextName} />\n                </TabPanel>\n                <TabPanel value={tabIndex} index={1}>\n                  <Intents handleTabChange={handleTabChange} />\n                </TabPanel>\n                <TabPanel value={tabIndex} index={2}>\n                  <Channels handleTabChange={handleTabChange} />\n                </TabPanel>\n                <TabPanel value={tabIndex} index={3}>\n                  <AppChannels handleTabChange={handleTabChange} />\n                </TabPanel>\n              </Paper>\n            </Grid>\n\n            <Grid item xs={12} md={4} sx={classes.workbench}>\n              <Paper sx={classes.paper}>\n                <Workbench />\n              </Paper>\n            </Grid>\n          </Grid>\n        ) : (\n          <Grid sx={classes.body} container spacing={2} item xs={12} style={{ marginLeft: '0px' }}>\n            <Grid container direction=\"column\" justifyContent=\"center\" alignItems=\"center\" spacing={2} item xs={12}>\n              <Paper sx={classes.paper}>\n                <Typography variant=\"h4\">FDC3 API not detected!</Typography>\n                <Typography variant=\"body1\">An FDC3 desktop agent implementation was not found.</Typography>\n                <Typography variant=\"body1\">\n                  For web applications to be FDC3-enabled, they need to run in the context of an agent that makes the\n                  FDC3 API available to the application. This desktop agent is also responsible for launching and\n                  coordinating applications. It could be a browser extension, web app, or full-fledged desktop container\n                  framework.\n                </Typography>\n                <Typography variant=\"body1\">\n                  See the FDC3 standard documentation for details on{' '}\n                  <Link\n                    sx={classes.link}\n                    href=\"https://fdc3.finos.org/docs/supported-platforms\"\n                    onClick={openSupportedPlatformsDocs}\n                  >\n                    supported platforms\n                  </Link>{' '}\n                  and{' '}\n                  <Link\n                    sx={classes.link}\n                    href=\"https://fdc3.finos.org/docs/api/spec#api-access\"\n                    onClick={openSpecAccessDocs}\n                  >\n                    accessing the FDC3 API\n                  </Link>\n                  .\n                </Typography>\n              </Paper>\n            </Grid>\n          </Grid>\n        )}\n\n        <Grid container item xs={12} sx={classes.footer}>\n          <Typography variant=\"body1\">\n            Learn more about the{' '}\n            <Link sx={classes.link} href=\"https://fdc3.finos.org/docs/api/overview\" onClick={openAPIDocs}>\n              FDC3 Standard and APIs\n            </Link>{' '}\n            | Proud member of the{' '}\n            <Link sx={classes.link} href=\"https://www.finos.org/\">\n              Fintech Open Source Foundation\n            </Link>{' '}\n            | Copyright © 2021-2023 Finsemble, inc. &amp; Contributors to the FDC3 standards project\n          </Typography>\n        </Grid>\n      </Grid>\n\n      <Snackbar key={snackbarStore.snackbarData?.id} open={openSnackbar} autoHideDuration={4000} onClose={handleClose}>\n        <Alert elevation={6} variant=\"filled\" onClose={() => handleClose()} severity={snackbarStore.snackbarData?.type}>\n          {snackbarStore.snackbarData?.message}\n        </Alert>\n      </Snackbar>\n    </ThemeProvider>\n  );\n});\n\nexport default App;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/AppChannels.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { FormEvent, useState } from 'react';\nimport { Button, Typography, Grid, TextField, Box } from '@mui/material';\nimport { observer } from 'mobx-react';\nimport contextStore from '../store/ContextStore.js';\nimport appChannelStore from '../store/AppChannelStore.js';\nimport { ChannelField } from './ChannelField.js';\n\nconst classes = {\n  root: {\n    flexGrow: 1,\n  },\n  title: {\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'space-between',\n  },\n  form: {\n    display: 'flex',\n    flexWrap: 'wrap',\n    alignItems: 'center',\n    mt: 1,\n    '& > *': {\n      m: 1,\n      ml: '0px',\n    },\n  },\n  contextType: {\n    flexGrow: 1,\n    minWidth: '190px',\n  },\n  controls: {\n    '& > *:first-of-type': {\n      marginLeft: 0,\n    },\n    '& > *': {\n      mr: 1,\n    },\n    '& > *:last-child': {\n      marginRight: 0,\n    },\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px 0px 6px 0px',\n    },\n    '& > a': {\n      display: 'flex',\n      padding: '6px 0px 6px 0px',\n    },\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n  spread: {\n    flexDirection: 'row',\n    '& > *:first-of-type': {\n      paddingLeft: '0px',\n    },\n  },\n  textField: {\n    width: '100%',\n    '& input': {\n      height: '29px',\n      padding: '6px',\n    },\n  },\n  h4: {\n    fontSize: '22px',\n  },\n  h6: {\n    fontSize: '14px',\n  },\n  field: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n  border: {\n    height: '1px',\n    width: '100%',\n    backgroundColor: '#acb2c0',\n    marginTop: '24px',\n    marginBottom: '16px',\n  },\n  rightPadding: {\n    pr: 0.5,\n  },\n};\n\ninterface ListenerOptionType {\n  title: string;\n  value: string;\n  type: string | undefined;\n}\n\nexport const AppChannels = observer(\n  ({\n    handleTabChange,\n  }: {\n    handleTabChange: (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n  }) => {\n    const [currentAppChannelId, setCurrentAppChannelId] = useState<string>('');\n    const contextListenersOptionsAll: ListenerOptionType[] = contextStore.contextsList.map(({ id, template }) => {\n      return {\n        title: id,\n        value: id,\n        type: template?.type,\n      };\n    });\n    contextListenersOptionsAll.unshift({\n      title: 'All',\n      value: 'all',\n      type: 'All',\n    });\n\n    const handleGetorCreateChannel = (e: FormEvent | null = null) => {\n      e?.preventDefault();\n      if (currentAppChannelId) {\n        const foundChannel = appChannelStore.appChannelsList.find(\n          currentChannel => currentChannel.id === currentAppChannelId\n        );\n        if (!foundChannel) {\n          appChannelStore.getOrCreateChannel(currentAppChannelId);\n        }\n        setCurrentAppChannelId('');\n      }\n    };\n\n    const handleChannelChange = (event: React.ChangeEvent<{ value: unknown }>) => {\n      setCurrentAppChannelId(event.target.value as string);\n    };\n\n    return (\n      <Box sx={classes.root}>\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Get Channel</Typography>\n        </Grid>\n\n        <Box\n          component=\"form\"\n          sx={classes.form}\n          noValidate\n          autoComplete=\"off\"\n          onSubmit={e => handleGetorCreateChannel(e)}\n        >\n          <Grid container direction=\"row\" spacing={1}>\n            <Grid item sx={classes.field}>\n              <TextField\n                fullWidth\n                variant=\"outlined\"\n                label=\"Channel Name\"\n                type=\"text\"\n                size=\"small\"\n                onChange={handleChannelChange}\n                value={currentAppChannelId}\n              />\n            </Grid>\n            <Grid item sx={classes.controls}>\n              <Button\n                variant=\"contained\"\n                color=\"primary\"\n                onClick={handleGetorCreateChannel}\n                disabled={!currentAppChannelId}\n              >\n                Get or Create Channel\n              </Button>\n            </Grid>\n          </Grid>\n        </Box>\n        <Box sx={classes.border}></Box>\n        <ChannelField handleTabChange={handleTabChange} channelsList={appChannelStore.appChannelsList} />\n      </Box>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/ChannelField.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { HTMLAttributes, useEffect, useState } from 'react';\nimport { observer } from 'mobx-react';\nimport { runInAction } from 'mobx';\nimport appChannelStore, { Fdc3ChannelRecord } from '../store/AppChannelStore.js';\nimport privateChannelStore from '../store/PrivateChannelStore.js';\nimport { Button, IconButton, Tooltip, Typography, Grid, Link, Autocomplete } from '@mui/material';\nimport { createFilterOptions } from '@mui/material/Autocomplete';\nimport { ContextTemplates } from './ContextTemplates.js';\nimport { ContextType, PrivateChannel } from '../utility/Fdc3Api.js';\nimport { copyToClipboard } from './common/CopyToClipboard.js';\nimport { codeExamples } from '../fixtures/codeExamples.js';\nimport { openApiDocsLink } from '../fixtures/openApiDocs.js';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport contextStore from '../store/ContextStore.js';\nimport { TemplateTextField } from './common/TemplateTextField.js';\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';\n\ninterface ListenerOptionType {\n  title: string;\n  value: string;\n  type: string | undefined;\n}\n\ninterface FilterOptionsState<T> {\n  inputValue: string;\n  getOptionLabel: (option: T) => string;\n}\n\nconst listenerFilter = createFilterOptions<ListenerOptionType>();\n\nconst styles = {\n  topMargin: {\n    mt: 2,\n  },\n  secondMargin: {\n    mt: 1,\n  },\n  controls: {\n    '& > *:first-child': {\n      marginLeft: 0,\n    },\n    '& > *': {\n      mr: 1,\n    },\n    '& > *:last-child': {\n      marginRight: 0,\n    },\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px 0px 6px 0px',\n    },\n    '& > a': {\n      display: 'flex',\n      padding: '6px 0px 6px 0px',\n    },\n  },\n  spread: {\n    flexDirection: 'row',\n    '& > *:first-child': {\n      paddingLeft: '0px',\n    },\n  },\n  h6: {\n    fontSize: '14px',\n  },\n  field: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n  border: {\n    height: '1px',\n    width: '100%',\n    backgroundColor: '#acb2c0',\n    marginTop: '24px',\n    marginBottom: '16px',\n  },\n  rightPadding: {\n    pr: 0.5,\n  },\n};\n\ntype TabChangeHandler = (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n\nexport const ChannelField = observer(\n  ({\n    handleTabChange,\n    channelsList,\n    isPrivateChannel = false,\n    channelName,\n  }: {\n    handleTabChange: TabChangeHandler;\n    channelsList: Fdc3ChannelRecord[];\n    isPrivateChannel?: boolean;\n    channelName?: string;\n  }) => {\n    const [contextItem, setContextItem] = useState<ContextType | null>(null);\n    const [currentChannelList, setCurrentChannelList] = useState<Fdc3ChannelRecord[]>(channelsList);\n\n    const channelStore = isPrivateChannel ? privateChannelStore : appChannelStore;\n\n    const contextListenersOptionsAll: ListenerOptionType[] = contextStore.contextsList.map(({ id, template }) => {\n      return {\n        title: id,\n        value: id,\n        type: template?.type,\n      };\n    });\n    contextListenersOptionsAll.unshift({\n      title: 'All',\n      value: 'all',\n      type: 'All',\n    });\n\n    const contextListenersOptions = Array.from(\n      new Map(contextListenersOptionsAll.reverse().map(item => [item['type'], item])).values()\n    ).reverse();\n\n    const getOptionLabel = (option: ListenerOptionType | string) =>\n      typeof option === 'string' ? option : (option.type ?? option.title ?? '');\n\n    const handleAddContextListener = (channelId: string) => {\n      const foundChannel = currentChannelList.find(currentChannel => currentChannel.id === channelId);\n      if (!foundChannel) {\n        return;\n      }\n\n      if (foundChannel?.currentListener) {\n        if (channelStore.isContextListenerExists(channelId, foundChannel?.currentListener.type)) {\n          foundChannel.listenerError = 'Listener already added';\n        } else {\n          channelStore.addChannelListener(foundChannel.channel as PrivateChannel, foundChannel.currentListener.type);\n          foundChannel.listenerError = '';\n        }\n      } else {\n        foundChannel.listenerError = 'Enter context type';\n      }\n    };\n\n    const handleContextStateChange = (context: ContextType | null, channel?: string) => {\n      const foundChannel = channel\n        ? currentChannelList.find(currentChannel => currentChannel.id === channel)\n        : undefined;\n      if (foundChannel && context) {\n        setContextItem(context);\n        runInAction(() => {\n          foundChannel.context = context;\n        });\n      }\n    };\n\n    const handleBroadcast = (channel: Fdc3ChannelRecord) => {\n      if (channel.context && contextItem) {\n        channelStore.broadcast(channel.channel as PrivateChannel, contextItem);\n      }\n    };\n\n    const handleChangeAppListener =\n      (channelId: string) => (event: React.ChangeEvent<object>, newValue: ListenerOptionType | string | null) => {\n        const foundChannel = currentChannelList.find(currentChannel => currentChannel.id === channelId);\n        if (!foundChannel) {\n          return;\n        }\n\n        let newListener: ListenerOptionType | undefined;\n        const foundListener = channelStore.channelListeners?.find(\n          currentListener => currentListener.type === newValue && currentListener.channelId === channelId\n        );\n        if (foundListener) {\n          return;\n        }\n\n        if (typeof newValue === 'string') {\n          newListener = {\n            title: newValue,\n            value: newValue,\n            type: newValue,\n          };\n        } else if (newValue && typeof newValue !== 'string' && 'inputValue' in newValue) {\n          newListener = {\n            title: (newValue as ListenerOptionType & { inputValue: string }).inputValue,\n            value: (newValue as ListenerOptionType & { inputValue: string }).inputValue,\n            type: (newValue as ListenerOptionType & { inputValue: string }).inputValue,\n          };\n        } else {\n          newListener = newValue ?? undefined;\n        }\n\n        runInAction(() => {\n          foundChannel.currentListener = newListener;\n        });\n        foundChannel.listenerError = '';\n      };\n\n    const filterOptions = (options: ListenerOptionType[], params: FilterOptionsState<ListenerOptionType>) => {\n      const filtered = listenerFilter(options, params);\n      if (params.inputValue !== '') {\n        filtered.push({\n          value: params.inputValue,\n          title: `Add \"${params.inputValue}\"`,\n          type: params.inputValue,\n        });\n      }\n      return filtered;\n    };\n\n    const handleRemoveOrDisconnect = (channel: Fdc3ChannelRecord) => {\n      if (isPrivateChannel) {\n        privateChannelStore.disconnect(channel.channel as PrivateChannel);\n      } else {\n        appChannelStore.remove(channel.channel);\n      }\n      setCurrentChannelList(currentChannelList.filter(currentChannel => currentChannel.id !== channel.id));\n    };\n\n    useEffect(() => {\n      setCurrentChannelList(channelsList);\n    }, [channelsList]);\n\n    return (\n      <div style={{ marginTop: 16 }}>\n        {currentChannelList.length > 0 &&\n          currentChannelList.map(channel => {\n            const element = (\n              <Grid container key={channel.id} sx={styles.spread}>\n                <Grid item sx={styles.field}>\n                  <Typography variant=\"h5\">Channel: {channel.id}</Typography>\n                </Grid>\n                <Grid container sx={styles.topMargin}>\n                  <Grid item xs={12}>\n                    <Typography variant=\"h6\" sx={styles.h6}>\n                      Broadcast\n                    </Typography>\n                  </Grid>\n\n                  <Grid item sm={7}>\n                    <ContextTemplates\n                      handleTabChange={handleTabChange}\n                      contextStateSetter={handleContextStateChange}\n                      channel={channel.id}\n                    />\n                  </Grid>\n                  <Grid item container sx={styles.controls} sm={5} justifyContent=\"flex-end\">\n                    <Button\n                      disabled={!channel.context}\n                      variant=\"contained\"\n                      color=\"primary\"\n                      onClick={() => handleBroadcast(channel)}\n                    >\n                      Broadcast\n                    </Button>\n\n                    <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                      <IconButton\n                        size=\"small\"\n                        aria-label=\"Copy code example\"\n                        color=\"primary\"\n                        onClick={copyToClipboard(codeExamples.appChannelBroadcast, 'channelBroadcast')}\n                      >\n                        <FileCopyIcon />\n                      </IconButton>\n                    </Tooltip>\n                    <Link\n                      onClick={openApiDocsLink}\n                      target=\"FDC3APIDocs\"\n                      href=\"https://fdc3.finos.org/docs/api/ref/Channel#broadcast\"\n                    >\n                      <InfoOutlinedIcon />\n                    </Link>\n                  </Grid>\n                </Grid>\n                <Grid container sx={styles.secondMargin}>\n                  <Grid item xs={12}>\n                    <Typography variant=\"h6\" sx={styles.h6}>\n                      Add context listener\n                    </Typography>\n                  </Grid>\n                  <Grid item sm={7} sx={styles.rightPadding}>\n                    <Autocomplete\n                      size=\"small\"\n                      selectOnFocus\n                      blurOnSelect\n                      clearOnBlur\n                      handleHomeEndKeys\n                      value={channel.currentListener ?? null}\n                      onChange={handleChangeAppListener(channel.id)}\n                      filterOptions={filterOptions}\n                      options={contextListenersOptions}\n                      getOptionLabel={getOptionLabel}\n                      isOptionEqualToValue={(option: ListenerOptionType, value: ListenerOptionType) =>\n                        option.type === value.type\n                      }\n                      freeSolo={true}\n                      renderOption={(props: HTMLAttributes<HTMLLIElement>, option: ListenerOptionType) => (\n                        <li {...props}>{option.type}</li>\n                      )}\n                      renderInput={params => (\n                        <TemplateTextField\n                          label=\"CONTEXT TYPE\"\n                          placeholder=\"Enter Context Type\"\n                          variant=\"outlined\"\n                          {...params}\n                          error={!!channel.listenerError}\n                          helperText={channel.listenerError}\n                        />\n                      )}\n                      onKeyDown={event => {\n                        if (event.key === 'Enter') {\n                          event.defaultPrevented = true;\n                          handleAddContextListener(channel.id);\n                        }\n                      }}\n                    />\n                  </Grid>\n\n                  <Grid item container sx={styles.controls} sm={5} justifyContent=\"flex-end\">\n                    <Button variant=\"contained\" color=\"primary\" onClick={() => handleAddContextListener(channel.id)}>\n                      Add listener\n                    </Button>\n\n                    <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                      <IconButton\n                        size=\"small\"\n                        aria-label=\"Copy code example\"\n                        color=\"primary\"\n                        onClick={copyToClipboard(codeExamples.appChannelContextListener, 'addAppContextListener')}\n                      >\n                        <FileCopyIcon />\n                      </IconButton>\n                    </Tooltip>\n                    <Link\n                      onClick={openApiDocsLink}\n                      target=\"FDC3APIDocs\"\n                      href=\"https://fdc3.finos.org/docs/api/ref/Channel#addcontextlistener\"\n                    >\n                      <InfoOutlinedIcon />\n                    </Link>\n                  </Grid>\n                </Grid>\n                <Button\n                  variant=\"contained\"\n                  color=\"secondary\"\n                  onClick={() => handleRemoveOrDisconnect(channel)}\n                  sx={styles.secondMargin}\n                >\n                  {isPrivateChannel ? 'Disconnect' : 'Discard Channel'}\n                </Button>\n                <div style={styles.border}></div>\n              </Grid>\n            );\n\n            if (channelName) {\n              return channel.id === channelName && element;\n            } else {\n              return element;\n            }\n          })}\n      </div>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Channels.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useState } from 'react';\nimport { observer } from 'mobx-react';\nimport {\n  Typography,\n  Button,\n  FormControl,\n  InputLabel,\n  Select,\n  MenuItem,\n  FormHelperText,\n  IconButton,\n  Tooltip,\n  Grid,\n  Link,\n  SelectChangeEvent,\n} from '@mui/material';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport channelStore from '../store/ChannelStore.js';\nimport { codeExamples } from '../fixtures/codeExamples.js';\nimport { copyToClipboard } from './common/CopyToClipboard.js';\nimport { openApiDocsLink } from '../fixtures/openApiDocs.js';\nimport { ContextLinking } from './ContextLinking.js';\nimport contextStore from '../store/ContextStore.js';\nimport { ContextTemplates } from './ContextTemplates.js';\nimport { ContextType } from '../utility/Fdc3Api.js';\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';\n\nconst styles = {\n  root: {\n    flexGrow: 1,\n  },\n  form: {\n    display: 'flex',\n    flexWrap: 'wrap',\n    alignItems: 'center',\n    mt: 1,\n    '& > *': {\n      m: 1,\n    },\n    '& > *:first-of-type': {\n      marginLeft: 0,\n      paddingLeft: 0,\n    },\n    '& > * > *:first-of-type': {\n      marginLeft: 0,\n      paddingLeft: 0,\n    },\n  },\n  channelsSelect: {\n    width: '100%',\n    mr: 1,\n  },\n  controls: {\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px 0px 6px 0px',\n    },\n    '& > a': {\n      display: 'flex',\n      padding: '6px 0px 6px 0px',\n    },\n  },\n  border: {\n    height: '1px',\n    width: '100%',\n    backgroundColor: '#acb2c0',\n    marginTop: '24px',\n    marginBottom: '16px',\n  },\n  bottomAlignChildren: {\n    display: 'flex',\n    alignItems: 'end',\n  },\n  dropDown: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n} as const;\n\nexport const Channels = observer(\n  ({\n    handleTabChange,\n  }: {\n    handleTabChange: (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n  }) => {\n    const [channelId, setChannelId] = useState<string>('');\n    const [isError, setIsError] = useState<boolean>(false);\n    const [broadcastContext, setBroadcastContext] = useState<ContextType | null>(null);\n\n    const handleSelectChange = (event: SelectChangeEvent<string>) => {\n      setChannelId(event.target.value);\n      setIsError(false);\n    };\n\n    const handleJoinUserChannel = () => {\n      if (channelId) {\n        channelStore.joinUserChannel(channelId);\n        setChannelId('');\n      } else {\n        setIsError(true);\n      }\n    };\n\n    const handleLeaveUserChannel = () => {\n      channelStore.leaveUserChannel();\n    };\n\n    const handleRefreshUserChannel = () => {\n      channelStore.getCurrentUserChannel();\n    };\n\n    const handleBroadcast = () => {\n      if (broadcastContext) contextStore.broadcast(broadcastContext);\n    };\n\n    return (\n      <div style={styles.root}>\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Current channel</Typography>\n        </Grid>\n        <Grid\n          container\n          direction=\"row\"\n          justifyContent=\"space-between\"\n          sx={{ ...styles.controls, ...styles.rightAlign }}\n        >\n          <Grid item sx={styles.dropDown}>\n            <Typography variant=\"body1\">{channelStore.currentUserChannel?.id ?? 'None'}</Typography>\n          </Grid>\n          <Grid item>\n            <Grid container direction=\"row\" justifyContent=\"flex-end\" spacing={1}>\n              <Grid item sx={styles.controls}>\n                <Button variant=\"contained\" color=\"primary\" onClick={handleRefreshUserChannel}>\n                  Refresh\n                </Button>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Button variant=\"contained\" color=\"primary\" onClick={handleLeaveUserChannel}>\n                  Leave\n                </Button>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={copyToClipboard(codeExamples.getCurrentUserChannel, 'getCurrentUserChannel')}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#getcurrentchannel\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n          </Grid>\n        </Grid>\n\n        <div style={styles.border}></div>\n\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Join user channels</Typography>\n        </Grid>\n\n        <Grid\n          container\n          direction=\"row\"\n          justifyContent=\"space-between\"\n          sx={{ ...styles.controls, ...styles.rightAlign }}\n        >\n          <Grid item sx={styles.dropDown}>\n            <FormControl variant=\"outlined\" sx={styles.channelsSelect} size=\"small\" error={isError}>\n              <InputLabel id=\"channel\">Channel</InputLabel>\n              <Select\n                labelId=\"channel\"\n                id=\"channel-select\"\n                value={channelId ?? ''}\n                onChange={handleSelectChange}\n                label=\"User Channel\"\n                MenuProps={{\n                  anchorOrigin: {\n                    vertical: 'bottom',\n                    horizontal: 'left',\n                  },\n                  transformOrigin: {\n                    vertical: 'top',\n                    horizontal: 'left',\n                  },\n                }}\n              >\n                {!channelStore.userChannels.length && (\n                  <MenuItem value=\"\" disabled>\n                    No channels received\n                  </MenuItem>\n                )}\n                {channelStore.userChannels.length && <MenuItem value=\"\" style={{ height: '0', padding: '0' }} />}\n                {channelStore.userChannels.length &&\n                  channelStore.userChannels.map(({ id }) => (\n                    <MenuItem key={id} value={id}>\n                      {id}\n                    </MenuItem>\n                  ))}\n              </Select>\n              {isError && <FormHelperText>Select channel from list</FormHelperText>}\n            </FormControl>\n          </Grid>\n          <Grid item xs={12} sm={3} sx={styles.bottomAlignChildren}>\n            <Grid container direction=\"row\" justifyContent=\"flex-end\" spacing={1}>\n              <Grid item sx={styles.controls}>\n                <Button variant=\"contained\" color=\"primary\" onClick={handleJoinUserChannel}>\n                  Join\n                </Button>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={copyToClipboard(codeExamples.userChannels, 'joinUserChannel')}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#joinuserchannel\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n          </Grid>\n        </Grid>\n\n        <div style={styles.border}></div>\n\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Broadcast context</Typography>\n        </Grid>\n\n        <Grid\n          container\n          direction=\"row\"\n          justifyContent=\"space-between\"\n          sx={{ ...styles.controls, ...styles.rightAlign }}\n        >\n          <Grid item sx={styles.dropDown}>\n            <ContextTemplates handleTabChange={handleTabChange} contextStateSetter={setBroadcastContext} />\n          </Grid>\n          <Grid item sx={styles.bottomAlignChildren}>\n            <Grid container direction=\"row\" justifyContent=\"flex-end\" spacing={1}>\n              <Grid item sx={styles.controls}>\n                <Button disabled={!broadcastContext} variant=\"contained\" color=\"primary\" onClick={handleBroadcast}>\n                  Broadcast\n                </Button>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={copyToClipboard(codeExamples.broadcast, 'broadcast')}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#broadcast\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n          </Grid>\n\n          <div style={styles.border}></div>\n\n          <ContextLinking />\n        </Grid>\n      </div>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/ContextCreate.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useEffect, useState, useRef, FormEvent } from 'react';\nimport { observer } from 'mobx-react';\nimport {\n  Button,\n  Grid,\n  Typography,\n  Tooltip,\n  IconButton,\n  Table,\n  TableBody,\n  TableRow,\n  TableCell,\n  TableContainer,\n  Box,\n} from '@mui/material';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport FileCopyOutlinedIcon from '@mui/icons-material/FileCopyOutlined';\nimport DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';\nimport contextStore, { ContextItem } from '../store/ContextStore.js';\nimport systemLogStore from '../store/SystemLogStore.js';\nimport { JsonInput } from './common/JsonInput.js';\nimport { DialogModal } from './common/DialogModal.js';\nimport { TemplateTextField } from './common/TemplateTextField.js';\nimport { copyToClipboard } from './common/CopyToClipboard.js';\nimport { ContextType } from '../utility/Fdc3Api.js';\n\ninterface OptionType {\n  title: string;\n  value: string;\n}\n\nconst classes = {\n  root: {\n    flexGrow: 1,\n  },\n  form: {\n    display: 'flex',\n    flexWrap: 'wrap',\n    alignItems: 'center',\n    mt: 1,\n    '& > *': {\n      m: 1,\n    },\n    '& > *:first-of-type': {\n      marginLeft: 0,\n      paddingLeft: 0,\n    },\n    '& > * > *:first-of-type': {\n      marginLeft: 0,\n      paddingLeft: 0,\n    },\n    '& .MuiGrid-grid-xs-12': {\n      paddingLeft: 0,\n    },\n  },\n  controls: {\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px',\n      ml: 1,\n    },\n  },\n  exampleSelect: {\n    flexGrow: 1,\n    minWidth: '190px',\n  },\n  textField: {\n    width: '100%',\n  },\n  multilineField: {\n    width: '100%',\n  },\n  button: {\n    marginLeft: 'auto',\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n  border: {\n    height: '1px',\n    width: '100%',\n    backgroundColor: '#acb2c0',\n    marginTop: '24px',\n    marginBottom: '16px',\n  },\n  delete: {\n    height: '15px',\n    transform: 'scale(1.7)',\n  },\n  copy: {\n    height: '20px',\n  },\n  link: {\n    cursor: 'pointer',\n    color: 'black',\n  },\n  margins: {\n    margin: '0 5px',\n  },\n  tableContainer: {\n    maxHeight: 250,\n    '& > table': {\n      width: 'calc(100% - 4px)',\n    },\n  },\n  field: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n};\n\nconst emptyJson: ContextType = {\n  type: '',\n  id: {},\n};\n\nexport const ContextCreate = observer(({ contextName }: { contextName: string }) => {\n  const [exampleName, setExampleName] = useState<OptionType | null>({\n    title: contextName,\n    value: contextName,\n  });\n  const [duplicateName, setDuplicateName] = useState(false);\n  const [contextValue, setContextValue] = useState<ContextType | null>(emptyJson);\n  const [context, setContext] = useState<ContextItem | null>({\n    id: contextName || 'empty',\n    template: emptyJson,\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/context.schema.json'),\n  });\n  const [contextError, setContextError] = useState<string | false>(false);\n  const [open, setOpen] = useState(false);\n  const [deleteContext, setDeleteContext] = useState<{ id: string; name?: string } | null>(null);\n  const [disabled, setDisabled] = useState(true);\n  const gridRef = useRef<HTMLTableRowElement>(null);\n\n  const handleClickOpen = (id: string, name: string | undefined) => {\n    setOpen(true);\n    setDeleteContext({ id, name });\n  };\n\n  const handleClose = (value: boolean) => {\n    setOpen(value);\n  };\n\n  const handleJsonError = (errors: string[]) => {\n    setContextError(errors[0]);\n  };\n\n  const handleChangeExample = (newValue: OptionType | null) => {\n    setExampleName(newValue);\n\n    if (newValue?.value) {\n      const selectedContext = contextStore.contextsList.find(({ id }) => id === newValue?.value);\n      if (selectedContext) {\n        setContextValue(selectedContext.template);\n        setContext(selectedContext);\n      }\n    }\n\n    setContextError(false);\n  };\n\n  const found = (tempName: string, ignoreUuid?: string) =>\n    contextStore.contextsList.reduce((count, { id, uuid }) => {\n      if (id === tempName && (!ignoreUuid || ignoreUuid !== uuid)) {\n        count = count + 1;\n      }\n      return count;\n    }, 0);\n\n  const handleChangeExampleName = (newValue: OptionType) => {\n    setDisabled(false);\n    setContextError(false);\n    setExampleName(newValue);\n\n    if (context && !found(newValue.value, context.uuid)) setDuplicateName(false);\n    else if (found(newValue.value) >= 1) setDuplicateName(true);\n  };\n\n  const handleContextChange = (json: object | null) => {\n    setContextValue(json as ContextType | null);\n    setContextError(false);\n  };\n\n  const validate = () => {\n    if (!contextValue) {\n      setContextError('Context is required');\n      return false;\n    }\n\n    if (!contextValue?.type) {\n      setContextError(\"Context must have property 'type'\");\n      return false;\n    }\n\n    if (contextValue?.type === '') {\n      setContextError(\"Property 'type' can't be empty\");\n      return false;\n    }\n\n    if (!exampleName) {\n      setContextError('Template name is required');\n      return false;\n    }\n\n    return true;\n  };\n\n  const handleCreateExample = () => {\n    setExampleName(null);\n    setContext(null);\n    setContextValue(null);\n    setDisabled(true);\n  };\n\n  const handleSaveExample = (e: FormEvent | null = null) => {\n    e?.preventDefault();\n    if (disabled) {\n      return;\n    } else {\n      const isValid: boolean = validate();\n\n      if (isValid && context && exampleName) {\n        const selectedContext = contextStore.contextsList.find(({ id }) => id === context.id);\n        const currContext = {\n          id: exampleName.value,\n          schemaUrl: context.schemaUrl,\n          template: contextValue,\n        };\n\n        if (!selectedContext) contextStore.addContextItem(currContext);\n\n        contextStore.saveContextItem(currContext, context.id);\n        handleChangeExample({ title: currContext.id, value: currContext.id });\n\n        systemLogStore.addLog({\n          name: 'saveExample',\n          type: 'success',\n          value: currContext?.id,\n          variant: 'text',\n        });\n      } else {\n        systemLogStore.addLog({\n          name: 'saveExample',\n          type: 'error',\n          value: undefined,\n          variant: 'text',\n        });\n      }\n      setDisabled(true);\n    }\n  };\n\n  const handleDuplicateExample = (newValue: OptionType, count = 0) => {\n    const copyName = `${newValue.value}-copy${count > 0 ? ` (${count})` : ''}`;\n    if (newValue?.value && !found(copyName)) {\n      setExampleName({ value: copyName, title: copyName });\n      const selectedContext = contextStore.contextsList.find(({ id }) => id === newValue.value);\n\n      if (selectedContext) {\n        const newContext: ContextItem = {\n          id: copyName,\n          template: selectedContext.template,\n          schemaUrl: selectedContext.schemaUrl,\n        };\n\n        contextStore.addContextItem(newContext);\n        contextStore.saveContextItem(newContext);\n\n        setContextValue(selectedContext.template);\n        setContext(newContext);\n\n        systemLogStore.addLog({\n          name: 'saveExample',\n          type: 'success',\n          value: newContext.id,\n          variant: 'text',\n        });\n      }\n    } else if (found(copyName)) {\n      handleDuplicateExample(newValue, ++count);\n    }\n\n    setContextError(false);\n  };\n\n  const handleResetExample = () => {\n    contextStore.resetContextList();\n    handleCreateExample();\n  };\n\n  const handleDeleteExample = (contextId: string) => {\n    const selectedContext = contextStore.contextsList.find(({ id }) => id === contextId);\n    if (selectedContext) {\n      contextStore.deleteContextItem(selectedContext);\n      systemLogStore.addLog({\n        name: 'deleteExample',\n        type: 'success',\n        value: selectedContext?.id,\n        variant: 'text',\n      });\n    } else {\n      systemLogStore.addLog({\n        name: 'deleteExample',\n        type: 'error',\n        value: undefined,\n        variant: 'text',\n      });\n    }\n  };\n\n  useEffect(() => {\n    if (duplicateName) {\n      setDisabled(true);\n      setContextError('Example name already exists');\n    } else setDisabled(false);\n  }, [duplicateName, contextValue]);\n\n  useEffect(() => {\n    if (gridRef && gridRef.current) gridRef.current.scrollIntoView({ behavior: 'auto', block: 'nearest' });\n    if (context == null) {\n      const newContext: ContextItem = {\n        id: 'empty',\n        template: emptyJson,\n        schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/context.schema.json'),\n      };\n      setContext(newContext);\n      setContextValue(emptyJson);\n    }\n  }, [context]);\n\n  return (\n    <Box sx={classes.root}>\n      <DialogModal open={open} onClose={handleClose} onAgree={handleDeleteExample} selectedValue={deleteContext} />\n      <Grid container spacing={1}>\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Context examples:</Typography>\n        </Grid>\n        <Grid item xs={12}>\n          <TableContainer sx={classes.tableContainer}>\n            <Table>\n              <TableBody>\n                {contextStore.contextsList.map(({ id, template }, index) => (\n                  <TableRow\n                    hover\n                    role=\"checkbox\"\n                    tabIndex={-1}\n                    key={`row-${index}`}\n                    selected={id === exampleName?.value}\n                    ref={id === exampleName?.value ? gridRef : null}\n                  >\n                    <TableCell\n                      key={`row-${index}-column-0`}\n                      align=\"left\"\n                      onClick={() => handleChangeExample({ title: id, value: id })}\n                    >\n                      <Typography variant=\"body2\">{id}</Typography>\n                    </TableCell>\n                    <TableCell\n                      key={`row-${index}-column-1`}\n                      align=\"left\"\n                      onClick={() => handleChangeExample({ title: id, value: id })}\n                    >\n                      <Typography variant=\"caption\">{template?.type}</Typography>\n                    </TableCell>\n                    <TableCell key={`row-${index}-column-2`} align=\"right\">\n                      <Tooltip title=\"Duplicate example\" aria-label=\"Copy code\">\n                        <IconButton\n                          size=\"small\"\n                          aria-label=\"Copy code example\"\n                          color=\"primary\"\n                          onClick={() => handleDuplicateExample({ title: id, value: id })}\n                        >\n                          <FileCopyOutlinedIcon sx={classes.copy} />\n                        </IconButton>\n                      </Tooltip>\n                    </TableCell>\n                    <TableCell key={`row-${index}-column-3`} align=\"right\">\n                      <Tooltip title=\"Delete example\" aria-label=\"Delete example\">\n                        <IconButton\n                          size=\"small\"\n                          aria-label=\"Delete example\"\n                          color=\"primary\"\n                          onClick={() => handleClickOpen(id, template?.name)}\n                        >\n                          <DeleteOutlinedIcon sx={classes.delete} />\n                        </IconButton>\n                      </Tooltip>\n                    </TableCell>\n                  </TableRow>\n                ))}\n              </TableBody>\n            </Table>\n          </TableContainer>\n        </Grid>\n      </Grid>\n      <Box component=\"form\" sx={classes.form} noValidate autoComplete=\"off\">\n        <Grid container direction=\"row\" spacing={1}>\n          <Grid item sx={classes.controls}>\n            <Button sx={classes.button} variant=\"contained\" color=\"primary\" onClick={handleCreateExample}>\n              Create new example\n            </Button>\n          </Grid>\n          <Grid item sx={classes.controls}>\n            <Button sx={classes.button} variant=\"contained\" color=\"primary\" onClick={handleResetExample}>\n              Reset examples\n            </Button>\n          </Grid>\n        </Grid>\n      </Box>\n\n      <Box component=\"form\" sx={classes.form} noValidate autoComplete=\"off\" onSubmit={e => handleSaveExample(e)}>\n        <Grid container direction=\"row\" spacing={1} sx={classes.rightAlign}>\n          <Grid item xs={12} sx={{ ...classes.controls, ...classes.exampleSelect }}>\n            <Grid item xs={6} sx={classes.field}>\n              <Grid item xs={12} sx={classes.textField}>\n                <Typography variant=\"h5\">Edit example:</Typography>\n              </Grid>\n              <TemplateTextField\n                label=\"Example name\"\n                variant=\"outlined\"\n                sx={classes.textField}\n                placeholder=\"Choose Context Example\"\n                value={exampleName?.value || ''}\n                onChange={e => handleChangeExampleName({ title: e.target.value, value: e.target.value })}\n              />\n            </Grid>\n          </Grid>\n\n          <Grid item xs={12} sx={classes.controls}>\n            <JsonInput\n              json={context?.template}\n              onChange={handleContextChange}\n              onJsonError={handleJsonError}\n              schemaUrl={\n                new URL(context?.schemaUrl || 'https://fdc3.finos.org/schemas/next/context/context.schema.json')\n              }\n              error={contextError}\n            />\n          </Grid>\n\n          <Grid item>\n            <Tooltip title=\"Copy code\" aria-label=\"Copy code\">\n              <IconButton\n                size=\"small\"\n                aria-label=\"Copy code example\"\n                color=\"primary\"\n                onClick={copyToClipboard(`let context = ${JSON.stringify(contextValue, null, 2)}`, 'createContext')}\n              >\n                <FileCopyIcon />\n              </IconButton>\n            </Tooltip>\n\n            <Button\n              sx={classes.button}\n              variant=\"contained\"\n              color=\"primary\"\n              onClick={handleSaveExample}\n              disabled={disabled}\n            >\n              Save Changes\n            </Button>\n          </Grid>\n        </Grid>\n      </Box>\n    </Box>\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/ContextLinking.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { FormEvent, HTMLAttributes, useState } from 'react';\nimport { observer } from 'mobx-react';\nimport { Typography, Grid, Button, IconButton, Tooltip, Link, Autocomplete } from '@mui/material';\nimport { createFilterOptions } from '@mui/material/Autocomplete';\nimport { codeExamples } from '../fixtures/codeExamples.js';\nimport { openApiDocsLink } from '../fixtures/openApiDocs.js';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport contextStore from '../store/ContextStore.js';\nimport { TemplateTextField } from './common/TemplateTextField.js';\nimport { copyToClipboard } from './common/CopyToClipboard.js';\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';\n\n// interface copied from lib @material-ui/lab/Autocomplete\ninterface FilterOptionsState<T> {\n  inputValue: string;\n  getOptionLabel: (option: T) => string;\n}\n\ninterface ListenerOptionType {\n  title: string;\n  value: string;\n  type: string | undefined;\n}\n\ntype ListenerSetValue = (value: ListenerOptionType | null) => void;\n\ntype ListenerSetError = (error: string | false) => void;\n\nconst styles = {\n  root: {\n    flexGrow: 1,\n  },\n  controls: {\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px 0px 6px 0px',\n    },\n    '& > a': {\n      display: 'flex',\n      padding: '6px 0px 6px 0px',\n    },\n  },\n  contextListenerName: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n  bottomAlignChildren: {\n    display: 'flex',\n    alignItems: 'end',\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n};\n\nconst listenerFilter = createFilterOptions<ListenerOptionType>();\n\nexport const ContextLinking = observer(() => {\n  const [contextListener, setContextListener] = useState<ListenerOptionType | null>(null);\n  const [contextError, setContextError] = useState<string | false>(false);\n  const contextListenersOptionsAll: ListenerOptionType[] = contextStore.contextsList.map(({ id, template }) => {\n    return {\n      title: id,\n      value: id,\n      type: template?.type,\n    };\n  });\n  contextListenersOptionsAll.unshift({\n    title: 'All',\n    value: 'all',\n    type: 'All',\n  });\n\n  const contextListenersOptions = Array.from(\n    new Map(contextListenersOptionsAll.reverse().map(item => [item['type'], item])).values()\n  ).reverse();\n\n  const handleChangeListener =\n    (setValue: ListenerSetValue, setError: ListenerSetError) =>\n    (event: React.ChangeEvent<object>, newValue: ListenerOptionType | string | null) => {\n      if (typeof newValue === 'string') {\n        setValue({\n          title: newValue,\n          value: newValue,\n          type: newValue,\n        });\n      } else if (newValue && 'inputValue' in newValue) {\n        const inputVal = (newValue as ListenerOptionType & { inputValue: string }).inputValue;\n        setValue({\n          title: inputVal,\n          value: inputVal,\n          type: inputVal,\n        });\n      } else {\n        setValue(newValue);\n      }\n\n      setError(false);\n    };\n\n  const getOptionLabel = (option: ListenerOptionType) => {\n    if (option.type) {\n      return option.type;\n    }\n    return option.title;\n  };\n\n  const filterOptions = (options: ListenerOptionType[], params: FilterOptionsState<ListenerOptionType>) => {\n    const filtered = listenerFilter(options, params);\n\n    if (params.inputValue !== '') {\n      filtered.push({\n        value: params.inputValue,\n        title: `Add \"${params.inputValue}\"`,\n        type: params.inputValue,\n      });\n    }\n\n    return filtered;\n  };\n\n  const handleAddContextListener = (e: FormEvent | null = null) => {\n    e?.preventDefault();\n    if (contextListener) {\n      if (contextStore.isContextListenerExists(contextListener.type)) {\n        setContextError('Listener already added');\n      } else {\n        contextStore.addContextListener(contextListener.type);\n        setContextListener(null);\n      }\n    } else {\n      setContextError('Enter context type');\n    }\n  };\n\n  return (\n    <div style={styles.root}>\n      <Grid item xs={12}>\n        <Typography variant=\"h5\">Add context listener</Typography>\n      </Grid>\n\n      <Grid container direction=\"row\" justifyContent=\"space-between\" sx={{ ...styles.controls, ...styles.rightAlign }}>\n        <Grid item sx={styles.contextListenerName}>\n          <Autocomplete\n            id=\"context-listener\"\n            size=\"small\"\n            selectOnFocus\n            blurOnSelect\n            clearOnBlur\n            handleHomeEndKeys\n            value={contextListener}\n            onChange={handleChangeListener(setContextListener, setContextError)}\n            filterOptions={filterOptions}\n            options={contextListenersOptions}\n            getOptionLabel={getOptionLabel}\n            renderOption={(props: HTMLAttributes<HTMLLIElement>, option: ListenerOptionType) => (\n              <li {...props}>{option.type}</li>\n            )}\n            renderInput={params => (\n              <TemplateTextField\n                label=\"CONTEXT TYPE\"\n                placeholder=\"Enter Context Type\"\n                variant=\"outlined\"\n                {...params}\n                error={!!contextError}\n                helperText={contextError}\n              />\n            )}\n          />\n        </Grid>\n        <Grid item sx={styles.bottomAlignChildren}>\n          <Grid container direction=\"row\" justifyContent=\"flex-end\" spacing={1}>\n            <Grid item sx={styles.controls}>\n              <Button variant=\"contained\" color=\"primary\" onClick={handleAddContextListener}>\n                Add listener\n              </Button>\n            </Grid>\n            <Grid item sx={styles.controls}>\n              <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                <IconButton\n                  size=\"small\"\n                  aria-label=\"Copy code example\"\n                  color=\"primary\"\n                  onClick={copyToClipboard(codeExamples.contextListener, 'addContextListener')}\n                >\n                  <FileCopyIcon />\n                </IconButton>\n              </Tooltip>\n            </Grid>\n            <Grid item sx={styles.controls}>\n              <Link\n                onClick={openApiDocsLink}\n                target=\"FDC3APIDocs\"\n                href=\"https://fdc3.finos.org/docs/api/ref/Channel#addcontextlistener\"\n              >\n                <InfoOutlinedIcon />\n              </Link>\n            </Grid>\n          </Grid>\n        </Grid>\n      </Grid>\n    </div>\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/ContextTemplates.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { HTMLAttributes, useEffect, useRef, useState } from 'react';\nimport { observer } from 'mobx-react';\nimport { Grid, Autocomplete } from '@mui/material';\nimport { createFilterOptions } from '@mui/material/Autocomplete';\nimport contextStore from '../store/ContextStore.js';\nimport { ContextType } from '../utility/Fdc3Api.js';\nimport { TemplateTextField } from './common/TemplateTextField.js';\n\ninterface FilterOptionsState<T> {\n  inputValue: string;\n  getOptionLabel: (option: T) => string;\n}\n\ninterface OptionType {\n  title: string;\n  value: string;\n}\n\ntype SetValue = (value: OptionType | null) => void;\n\ntype SetError = (error: string | false) => void;\n\nconst styles = {\n  root: {\n    flexGrow: 1,\n  },\n  controls: {\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px',\n      ml: 1,\n    },\n  },\n  contextName: {\n    flexGrow: 1,\n    minWidth: '190px',\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n};\n\nconst contextFilter = createFilterOptions<OptionType>();\n\nexport const ContextTemplates = observer(\n  ({\n    handleTabChange,\n    contextStateSetter,\n    channel,\n  }: {\n    handleTabChange: (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n    contextStateSetter: (context: ContextType | null, channel?: string) => void;\n    channel?: string;\n  }) => {\n    const [context, setContext] = useState<OptionType | null>(null);\n    const [contextError, setContextError] = useState<string | false>(false);\n    const contextsOptions: OptionType[] = contextStore.contextsList.map(({ id }) => {\n      return {\n        title: id,\n        value: id,\n      };\n    });\n    const isInitialMount = useRef(true);\n\n    const handleChange =\n      (setValue: SetValue, setError: SetError) =>\n      (event: React.ChangeEvent<object>, newValue: OptionType | string | null) => {\n        if (typeof newValue !== 'string') {\n          const selectedContext = contextStore.contextsList.find(({ id }) => id === newValue?.value);\n          if (selectedContext) contextStateSetter(selectedContext.template, channel);\n        }\n\n        if (typeof newValue === 'string') {\n          setValue({\n            title: newValue,\n            value: newValue,\n          });\n        } else if (newValue && 'inputValue' in newValue) {\n          const inputVal = (newValue as OptionType & { inputValue: string }).inputValue;\n          setValue({\n            title: inputVal,\n            value: inputVal,\n          });\n        } else {\n          setValue(newValue);\n        }\n\n        setError(false);\n      };\n\n    const getOptionLabel = (option: OptionType) => option.value || option.title;\n\n    const filterOptions = (options: OptionType[], params: FilterOptionsState<OptionType>) => {\n      const filtered = contextFilter(options, params);\n\n      if (params.inputValue !== '') {\n        filtered.push({\n          value: params.inputValue,\n          title: `Add \"${params.inputValue}\"`,\n        });\n      }\n\n      return filtered;\n    };\n\n    useEffect(() => {\n      if (isInitialMount.current) {\n        isInitialMount.current = false;\n      } else {\n        const selectedContext = contextStore.contextsList.find(({ id }) => id === context?.value);\n        if (!selectedContext) handleTabChange(null, 0, context?.value);\n      }\n    }, [context]);\n\n    return (\n      <div style={styles.root}>\n        <Grid\n          container\n          direction=\"row\"\n          spacing={1}\n          justifyContent=\"space-between\"\n          sx={{ ...styles.controls, ...styles.rightAlign }}\n        >\n          <Grid item sx={styles.contextName}>\n            <Autocomplete\n              id=\"context-\"\n              size=\"small\"\n              selectOnFocus\n              blurOnSelect\n              clearOnBlur\n              handleHomeEndKeys\n              value={context}\n              onChange={handleChange(setContext, setContextError)}\n              isOptionEqualToValue={(option: OptionType, value: OptionType) => option.value === value.value}\n              filterOptions={filterOptions}\n              options={contextsOptions}\n              getOptionLabel={getOptionLabel}\n              renderOption={(props: HTMLAttributes<HTMLLIElement>, option: OptionType) => (\n                <li {...props}>{option.title}</li>\n              )}\n              renderInput={params => (\n                <TemplateTextField\n                  label=\"CONTEXT \"\n                  placeholder=\"Enter Context Type\"\n                  variant=\"outlined\"\n                  {...params}\n                  error={!!contextError}\n                  helperText={contextError}\n                />\n              )}\n            />\n          </Grid>\n        </Grid>\n      </div>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Header.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useEffect, useState } from 'react';\nimport { AppBar, Toolbar, Tooltip, Typography, Box } from '@mui/material';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport { getWorkbenchAgent, ImplementationMetadata } from '../utility/Fdc3Api.js';\n\ndeclare global {\n  interface Window {\n    fdc3Version: string;\n  }\n}\n\nconst classes = {\n  root: {\n    flexGrow: 1,\n  },\n  toolbar: {\n    backgroundColor: 'transparent',\n    p: 2,\n    px: 4,\n    pb: '0px',\n  },\n  link: {\n    color: 'common.white',\n    textDecoration: 'underline',\n    '&:hover': {\n      color: 'common.white',\n    },\n  },\n  info: {\n    marginLeft: 'auto',\n    minWidth: '200px',\n    fontSize: '12px',\n  },\n  fdc3: {},\n  headerCube: {\n    width: '325px',\n    height: '40px',\n  },\n  backgroundHeader: {\n    background: 'linear-gradient(to bottom, #0086bf, #00bbe1)',\n    height: '200px',\n    width: '100%',\n    left: '0px',\n    top: '0px',\n    position: 'absolute',\n    zIndex: -10,\n  },\n  warning: {\n    color: 'yellow',\n    fontSize: '10px',\n    transform: 'scale(1.5)',\n    marginLeft: '5px',\n  },\n  warningText: {\n    color: 'red',\n  },\n  appid: {\n    whiteSpace: 'nowrap',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    overflowWrap: 'anywhere',\n    maxWidth: '150px',\n  },\n};\n\nexport const Header = (props: { fdc3Available: boolean }) => {\n  const [appInfo, setAppInfo] = useState<{\n    fdc3Version: string;\n    provider: string;\n    providerVersion: string;\n    appMetadata: { appId: string; version: string };\n  }>();\n  const params = new URLSearchParams(window.location.search);\n  const paramVersion = params.get('fdc3Version')?.replace(/\\/$/, '') || '';\n  const [chosenVersion, setChosenVersion] = useState<string>('2.0');\n  const warningText = `Your FDC3 version (${appInfo?.fdc3Version}) doesn't match the version of the FDC3 Workbench you are using (${chosenVersion})`;\n  const supportedVersion = ['2.0', '1.2'];\n\n  useEffect(() => {\n    if (props.fdc3Available) {\n      const updateInfo = async () => {\n        let implInfo: ImplementationMetadata | null = null;\n\n        try {\n          const implInfoPromise = getWorkbenchAgent().then(agent => agent.getInfo());\n          if (paramVersion == '1.2' && (implInfoPromise as unknown as ImplementationMetadata).fdc3Version) {\n            implInfo = implInfoPromise as unknown as ImplementationMetadata;\n          } else {\n            implInfo = await implInfoPromise;\n          }\n\n          let displayInfo = {\n            fdc3Version: 'not specified',\n            provider: 'not specified',\n            providerVersion: 'not specified',\n            appMetadata: {\n              appId: 'not specified',\n              version: 'not specified',\n            },\n          };\n\n          const mergedAppMetaData = Object.assign({}, displayInfo.appMetadata, implInfo.appMetadata);\n          displayInfo = Object.assign(displayInfo, implInfo, { appMetadata: mergedAppMetaData });\n\n          setAppInfo(displayInfo);\n        } catch (e) {\n          console.error('Failed to retrieve FDC3 implementation info', e);\n        }\n\n        if (paramVersion) {\n          setChosenVersion(paramVersion);\n        } else if (implInfo?.fdc3Version && (implInfo.fdc3Version == '2.1' || implInfo.fdc3Version == '2.2')) {\n          setChosenVersion('2.0');\n        } else if (implInfo?.fdc3Version && supportedVersion.includes(implInfo.fdc3Version)) {\n          setChosenVersion(implInfo.fdc3Version);\n        } else {\n          setChosenVersion('2.0');\n        }\n\n        window.fdc3Version = chosenVersion;\n      };\n\n      updateInfo();\n    }\n  }, [props.fdc3Available, chosenVersion]);\n\n  return (\n    <Box sx={classes.root}>\n      <Box sx={classes.backgroundHeader}></Box>\n      <AppBar position=\"static\" elevation={0} style={{ backgroundColor: 'transparent' }}>\n        <Toolbar sx={classes.toolbar}>\n          <div>\n            <Typography variant=\"h3\" color=\"inherit\" sx={classes.fdc3}>\n              <Box component=\"img\" src=\"./fdc3-logo.png\" sx={classes.headerCube} />\n            </Typography>\n            <Typography color=\"inherit\">\n              version:&nbsp;\n              {supportedVersion.map((ver, index) => (\n                <span key={index}>\n                  {ver === chosenVersion ? (\n                    <span>\n                      <b>{ver == '2.0' ? '2.0+' : ver}</b>\n                    </span>\n                  ) : (\n                    <Box\n                      component=\"a\"\n                      sx={{\n                        color: 'common.white',\n                        textDecoration: 'underline',\n                        '&:hover': {\n                          color: 'common.white',\n                        },\n                      }}\n                      href={`?fdc3Version=${ver}`}\n                    >\n                      {ver == '2.0' ? '2.0+' : ver}\n                    </Box>\n                  )}\n                  {supportedVersion.length - 1 !== index && <span> | </span>}\n                </span>\n              ))}\n            </Typography>\n          </div>\n\n          <Box sx={classes.info}>\n            <table id=\"providerInfo\">\n              <tbody>\n                <tr>\n                  <th scope=\"row\">FDC3 Version</th>\n                  {appInfo?.fdc3Version ? (\n                    chosenVersion === appInfo.fdc3Version ||\n                    (chosenVersion === '2.0' && (appInfo.fdc3Version === '2.1' || appInfo.fdc3Version === '2.2')) ? (\n                      <td>{appInfo.fdc3Version}</td>\n                    ) : (\n                      <Box component=\"td\" sx={classes.warningText}>\n                        {appInfo.fdc3Version}\n                        <Tooltip title={warningText} aria-label={warningText}>\n                          <WarningIcon sx={classes.warning} />\n                        </Tooltip>\n                      </Box>\n                    )\n                  ) : (\n                    <td>unknown</td>\n                  )}\n                </tr>\n                <tr>\n                  <th scope=\"row\">Provider</th>\n                  <td>{appInfo?.provider ? appInfo.provider : 'unknown'}</td>\n                </tr>\n                <tr>\n                  <th scope=\"row\">Provider version</th>\n                  <td>{appInfo?.providerVersion ? appInfo.providerVersion : 'unknown'}</td>\n                </tr>\n                {chosenVersion != '1.2' ? (\n                  <tr>\n                    <th scope=\"row\">My AppId</th>\n                    <Box component=\"td\" sx={classes.appid}>\n                      {appInfo?.appMetadata?.appId ? appInfo.appMetadata.appId : 'unknown'}\n                    </Box>\n                  </tr>\n                ) : (\n                  ''\n                )}\n              </tbody>\n            </table>\n          </Box>\n        </Toolbar>\n      </AppBar>\n    </Box>\n  );\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/IntentResolutionField.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useEffect, useState } from 'react';\nimport { observer } from 'mobx-react';\nimport { TextField, Box } from '@mui/material';\nimport { ChannelField } from './ChannelField.js';\nimport appChannelStore, { Fdc3ChannelRecord } from '../store/AppChannelStore.js';\nimport privateChannelStore from '../store/PrivateChannelStore.js';\nimport { IntentResolution } from '../utility/Fdc3Api.js';\nimport { AppIdentifier, Channel, PrivateChannel } from '@finos/fdc3';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n    color: 'rgba(0, 0, 0, 0.6)',\n  },\n};\n\nexport const IntentResolutionField = observer(\n  ({\n    data,\n    handleTabChange,\n  }: {\n    data: IntentResolution;\n    handleTabChange: (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n  }) => {\n    const [resolutionResult, setResolutionResult] = useState<string | null>('pending...');\n    const [isChannel, setIsChannel] = useState(false);\n    const [privateChannel, setPrivateChannel] = useState(false);\n    const [channelsList, setChannelsList] = useState<Fdc3ChannelRecord[]>([]);\n    const [channelName, setChannelName] = useState<string>('');\n\n    const source = data.source as AppIdentifier;\n    const results = `appId: ${source.appId}\\ninstanceId: ${source.instanceId}`;\n\n    const displayIntentResults = async () => {\n      try {\n        if (data.getResult) {\n          const result = await data.getResult();\n\n          if (result && typeof result === 'object' && 'broadcast' in result) {\n            const channel = result as Channel;\n            setResolutionResult('');\n\n            if (channel.type === 'app') {\n              await appChannelStore.getOrCreateChannel(channel.id);\n              setChannelName(channel.id);\n              setIsChannel(true);\n              setChannelsList(appChannelStore.appChannelsList);\n            }\n\n            if (channel.type === 'private') {\n              setIsChannel(true);\n              setPrivateChannel(true);\n              setChannelsList([{ id: channel.id, channel: channel }]);\n              privateChannelStore.addChannelListener(channel as PrivateChannel, 'all');\n            }\n            setResolutionResult(null);\n          } else if (result) {\n            setResolutionResult(JSON.stringify(result, null, 2));\n          } else {\n            setResolutionResult('<void>');\n          }\n        }\n      } catch (error) {\n        if (`${error}`.includes('NoResultReturned')) setResolutionResult('<void>');\n        else setResolutionResult(`${error}`);\n        console.error(`${source.appId} returned a result error: ${error}`);\n      }\n    };\n\n    useEffect(() => {\n      displayIntentResults();\n    }, []);\n\n    return (\n      <Box>\n        <TextField\n          disabled\n          label={'Resolved By'}\n          InputLabelProps={{\n            shrink: true,\n          }}\n          contentEditable={false}\n          fullWidth\n          multiline\n          variant=\"outlined\"\n          size=\"small\"\n          value={results}\n          InputProps={{\n            sx: classes.input,\n          }}\n        />\n        {resolutionResult && (\n          <TextField\n            disabled\n            label={'Results'}\n            InputLabelProps={{\n              shrink: true,\n            }}\n            contentEditable={false}\n            fullWidth\n            multiline\n            variant=\"outlined\"\n            size=\"small\"\n            value={resolutionResult}\n            sx={classes.textField}\n            InputProps={{\n              sx: classes.input,\n            }}\n          />\n        )}\n        {isChannel && (\n          <ChannelField\n            handleTabChange={handleTabChange}\n            channelsList={channelsList}\n            isPrivateChannel={privateChannel}\n            channelName={channelName}\n          />\n        )}\n      </Box>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Intents.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { ChangeEvent, ReactElement, useEffect, useState } from 'react';\nimport {\n  AppMetadata,\n  ContextType,\n  getTargetOptions,\n  getTargetOptionsForContext,\n  getWorkbenchAgent,\n  IntentResolution,\n  IntentTargetOption,\n} from '../utility/Fdc3Api.js';\nimport { toJS } from 'mobx';\nimport {\n  Button,\n  IconButton,\n  Tooltip,\n  Typography,\n  Grid,\n  FormControl,\n  InputLabel,\n  MenuItem,\n  Select,\n  Radio,\n  TextField,\n  Switch,\n  Link,\n  ListSubheader,\n  Checkbox,\n  FormGroup,\n  FormControlLabel,\n  RadioGroup,\n  Alert,\n  ToggleButton,\n  ToggleButtonGroup,\n  Autocomplete,\n  SelectChangeEvent,\n} from '@mui/material';\nimport { createFilterOptions } from '@mui/material/Autocomplete';\nimport { observer } from 'mobx-react';\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\nimport AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';\nimport { ContextTemplates } from '../components/ContextTemplates.js';\nimport intentStore from '../store/IntentStore.js';\nimport { codeExamples } from '../fixtures/codeExamples.js';\nimport { openApiDocsLink } from '../fixtures/openApiDocs.js';\nimport { TemplateTextField } from './common/TemplateTextField.js';\nimport { copyToClipboard } from './common/CopyToClipboard.js';\nimport { IntentResolutionField } from './IntentResolutionField.js';\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';\n\n// interface copied from lib @material-ui/lab/Autocomplete\ninterface FilterOptionsState<T> {\n  inputValue: string;\n  getOptionLabel: (option: T) => string;\n}\n\ninterface ListenerOptionType {\n  title: string;\n  value: string;\n}\n\ntype ListenerSetValue = (value: ListenerOptionType | null) => void;\n\ntype ListenerSetError = (error: string | false) => void;\n\nconst styles = {\n  root: {\n    flexGrow: 1,\n  },\n  title: {\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'space-between',\n  },\n  form: {\n    display: 'flex',\n    flexWrap: 'wrap',\n    alignItems: 'center',\n    mt: 1,\n    '& > *': {\n      m: 1,\n      marginLeft: '0px',\n    },\n  },\n  controls: {\n    '& > *:first-of-type': {\n      marginLeft: 0,\n    },\n    '& > *': {\n      mr: 1,\n    },\n    '& > *:last-child': {\n      marginRight: 0,\n    },\n    '& .MuiIconButton-sizeSmall': {\n      padding: '6px 0px 6px 0px',\n    },\n    '& > a': {\n      display: 'flex',\n      padding: '6px 0px 6px 0px',\n    },\n    display: 'flex',\n    alignItems: 'center',\n  },\n  rightAlign: {\n    flexDirection: 'row',\n    justifyContent: 'flex-end',\n  },\n  spread: {\n    flexDirection: 'row',\n    '& > *:first-of-type': {\n      paddingLeft: '0px',\n    },\n  },\n  textField: {\n    width: '100%',\n    '& input': {\n      height: '29px',\n      padding: '6px',\n    },\n  },\n  h4: {\n    fontSize: '22px',\n  },\n  field: {\n    flexGrow: 1,\n    mr: 1,\n    minWidth: '190px',\n  },\n  border: {\n    height: '1px',\n    width: '100%',\n    backgroundColor: '#acb2c0',\n    marginTop: '24px',\n    marginBottom: '16px',\n  },\n  bottomMargin: {\n    mb: 1,\n  },\n  removeSidePadding: {\n    paddingLeft: 0,\n  },\n  targetSelect: {\n    width: '100%',\n    mr: 1,\n  },\n  rightPadding: {\n    pr: 0.5,\n  },\n  input: {\n    color: '#0086bf',\n    outline: '1px',\n    '&.Mui-checked': {\n      color: '#0086bf',\n    },\n  },\n  toggle: {\n    '&.Mui-selected': {\n      color: '#0086bf',\n      backgroundColor: 'rgba(0, 134, 191, 0.21)',\n    },\n  },\n  indentLeft: {\n    marginLeft: '30px',\n  },\n  caption: {\n    color: '#0086bf',\n    marginTop: '10px',\n  },\n} as const;\n\nconst filter = createFilterOptions<ListenerOptionType>();\n\nexport const Intents = observer(\n  ({\n    handleTabChange,\n  }: {\n    handleTabChange: (event: React.ChangeEvent<object> | null, newValue: number, contextName?: string) => void;\n  }) => {\n    const [intentValue, setIntentValue] = useState<ListenerOptionType | null>(null);\n    const [raiseIntentError, setRaiseIntentError] = useState<string | false>(false);\n    const [intentListener, setIntentListener] = useState<ListenerOptionType | null>(null);\n    const [intentsForContext, setIntentsForContext] = useState<ListenerOptionType[] | null>(null);\n    const [targetApp, setTargetApp] = useState<string>('None');\n    const [contextTargetApp, setContextTargetApp] = useState<string>('None');\n    const [raiseIntentContext, setRaiseIntentContext] = useState<ContextType | null>(null);\n    const [raiseIntentWithContextContext, setRaiseIntentWithContextContext] = useState<ContextType | null>(null);\n    const [intentError, setIntentError] = useState<string | false>(false);\n    const [intentResolution, setIntentResolution] = useState<IntentResolution | undefined | null>(null);\n    const [intentForContextResolution, setIntentForContextResolution] = useState<IntentResolution | undefined | null>(\n      null\n    );\n    const intentListenersOptions: ListenerOptionType[] = intentStore.intentsList;\n    const [contextFields, setContextFields] = useState<ReactElement[]>([]);\n    const [resultTypeContext, setResultTypeContext] = useState<ContextType | null>(null);\n    const [resultOverChannelContextList, setResultOverChannelContextList] = useState<Record<string, ContextType>>({});\n    const [resultOverChannelContextDelays, setResultOverChannelContextDelays] = useState<Record<string, number>>({});\n    const [sendIntentResult, setSendIntentResult] = useState<boolean | undefined>(false);\n    const [resultType, setResultType] = useState<string | null>(null);\n    const [useTargets, setUseTargets] = useState<boolean>(false);\n    const [useContextTargets, setUseContextTargets] = useState<boolean>(false);\n    const [channelType, setChannelType] = useState<string | null>('app-channel');\n    const [sendResultOverChannel, setSendResultOverChannel] = useState<boolean | undefined>(false);\n    const [currentAppChannelId, setCurrentAppChannelId] = useState<string>('');\n    const [targetOptions, setTargetOptions] = useState<ReactElement[]>([]);\n    const [targetOptionsforContext, setTargetOptionsforContext] = useState<ReactElement[]>([]);\n\n    const handleRaiseIntent = async () => {\n      setIntentResolution(null);\n      if (!intentValue) {\n        setRaiseIntentError('Enter intent name');\n      } else if (!raiseIntentContext) {\n        setRaiseIntentError('Select a context first');\n      } else {\n        if (targetApp && targetApp != 'None') {\n          try {\n            const targetObj = JSON.parse(targetApp);\n            const target = targetObj as AppMetadata;\n\n            setIntentResolution(await intentStore.raiseIntent(intentValue.value, raiseIntentContext, target));\n            setRaiseIntentError('');\n            return;\n          } catch (e) {\n            console.error('Error passing raiseIntent target option value!', contextTargetApp, e);\n            setTargetApp('None');\n          }\n        }\n        //allow failover to raise without target if we were unable to parse it\n        setIntentResolution(await intentStore.raiseIntent(intentValue.value, raiseIntentContext));\n        setRaiseIntentError('');\n      }\n    };\n\n    const handleRaiseIntentForContext = async () => {\n      setIntentForContextResolution(null);\n      if (!raiseIntentWithContextContext) {\n        return;\n      }\n      if (contextTargetApp && contextTargetApp != 'None') {\n        try {\n          const targetObj = JSON.parse(contextTargetApp);\n          const target = targetObj as AppMetadata;\n\n          setIntentForContextResolution(await intentStore.raiseIntentForContext(raiseIntentWithContextContext, target));\n          return;\n        } catch (e) {\n          console.error('Error passing raiseIntentForContext target option value!', contextTargetApp, e);\n          setContextTargetApp('None');\n        }\n      }\n      //allow failover to raise without target if we were unable to parse it\n      setIntentForContextResolution(await intentStore.raiseIntentForContext(raiseIntentWithContextContext));\n    };\n\n    const clearTargets = () => {\n      setTargetApp('');\n      setTargetOptions([]);\n    };\n\n    const clearContextTargets = () => {\n      setContextTargetApp('');\n      setUseContextTargets(false);\n      setTargetOptionsforContext([]);\n    };\n\n    const handleTargetChange = (event: SelectChangeEvent<string>) => {\n      if (event.target.value === 'None') {\n        setTargetApp('None');\n      } else {\n        setTargetApp(event.target.value);\n      }\n    };\n\n    const handleContextTargetChange = (event: SelectChangeEvent<string>) => {\n      if (event.target.value === 'None') {\n        setContextTargetApp('None');\n      } else {\n        setContextTargetApp(event.target.value);\n      }\n    };\n\n    const handleChangeListener =\n      (setValue: ListenerSetValue, setError: ListenerSetError) =>\n      (event: React.ChangeEvent<object>, newValue: ListenerOptionType | string | null) => {\n        if (typeof newValue === 'string') {\n          setValue({\n            title: newValue,\n            value: newValue,\n          });\n        } else if (newValue && 'inputValue' in newValue) {\n          const inputVal = (newValue as ListenerOptionType & { inputValue: string }).inputValue;\n          setValue({\n            title: inputVal,\n            value: inputVal,\n          });\n        } else {\n          setValue(newValue);\n        }\n\n        setError(false);\n      };\n\n    const getOptionLabel = (option: ListenerOptionType) => option.value || option.title;\n\n    const filterOptions = (options: ListenerOptionType[], params: FilterOptionsState<ListenerOptionType>) => {\n      const filtered = filter(options, params);\n\n      if (params.inputValue !== '') {\n        filtered.push({\n          value: params.inputValue,\n          title: `Add \"${params.inputValue}\"`,\n        });\n      }\n\n      return filtered;\n    };\n\n    const handleTargetMenuOpen = () => {\n      const fetchAppsAndInstances = async () => {\n        if (!intentValue) {\n          setRaiseIntentError('Enter intent name');\n        } else if (!raiseIntentContext) {\n          setRaiseIntentError('Select a context first');\n        } else {\n          const intentTargetOptions: IntentTargetOption[] = await getTargetOptions(\n            intentValue.value,\n            toJS(raiseIntentContext)\n          );\n\n          if (intentTargetOptions.length === 0) {\n            setUseTargets(false);\n            clearTargets();\n            return;\n          }\n\n          const menuItems: ReactElement[] = [];\n\n          //check if there are any target options\n          if (intentTargetOptions.length === 0) {\n            menuItems.push(\n              <MenuItem value=\"\" key=\"no-target-apps-found\" disabled>\n                No target apps found\n              </MenuItem>\n            );\n          } else {\n            menuItems.push(\n              <MenuItem key=\"none\" value=\"None\">\n                None\n              </MenuItem>\n            );\n\n            //add app targets\n            menuItems.push(<ListSubheader key={`subheading-app-targets`}>Target apps</ListSubheader>);\n            intentTargetOptions.forEach(option => {\n              const targetLabel: string = option.metadata.title ?? option.appId;\n              if (option.launchNew) {\n                menuItems.push(\n                  <MenuItem className=\"app\" key={option.appId} value={JSON.stringify(option.metadata)}>\n                    {targetLabel}\n                  </MenuItem>\n                );\n              }\n            });\n\n            //check if there are any target options\n            if (intentTargetOptions.find(value => value?.instances.length > 0)) {\n              //add app instance targets\n              menuItems.push(\n                <ListSubheader key={`subheading-app-instance-targets`}>Target app instances</ListSubheader>\n              );\n              intentTargetOptions.forEach(option => {\n                const targetLabel: string = option.metadata.title ?? option.appId;\n                option?.instances.forEach(instance => {\n                  menuItems.push(\n                    <MenuItem className=\"instance\" key={instance.instanceId} value={JSON.stringify(instance)}>\n                      {`${targetLabel} (${instance.instanceId})`}\n                    </MenuItem>\n                  );\n                });\n              });\n            }\n          }\n\n          setTargetOptions(menuItems);\n        }\n      };\n      fetchAppsAndInstances();\n    };\n\n    const handleContextTargetMenuOpen = () => {\n      const fetchIntents = async () => {\n        const menuItems: ReactElement[] = [];\n        try {\n          if (!raiseIntentWithContextContext) {\n            //no settable error at the moment... setRaiseIntentError(\"enter context name\");\n          } else {\n            const contextTargetOptions = await getTargetOptionsForContext(toJS(raiseIntentWithContextContext));\n\n            if (Object.keys(contextTargetOptions).length > 0) {\n              menuItems.push(\n                <MenuItem key=\"none\" value=\"None\">\n                  None\n                </MenuItem>\n              );\n\n              //add app targets\n              menuItems.push(<ListSubheader key={`subheading-app-targets`}>Target apps</ListSubheader>);\n              contextTargetOptions.forEach(option => {\n                const targetLabel: string = option.metadata.title ?? option.appId;\n                if (option.launchNew) {\n                  menuItems.push(\n                    <MenuItem className=\"app\" key={option.appId} value={JSON.stringify(option.metadata)}>\n                      {targetLabel}\n                    </MenuItem>\n                  );\n                }\n              });\n\n              //check if there are any target options\n              //check if there are any target options\n              if (contextTargetOptions.find(value => value.instances.length > 0)) {\n                //add app instance targets\n                menuItems.push(\n                  <ListSubheader key={`subheading-app-instance-targets`}>Target app instances</ListSubheader>\n                );\n                contextTargetOptions.forEach(option => {\n                  const targetLabel: string = option.metadata.title ?? option.appId;\n                  option?.instances.forEach(instance => {\n                    menuItems.push(\n                      <MenuItem className=\"instance\" key={instance.instanceId} value={JSON.stringify(instance)}>\n                        {`${targetLabel} (${instance.instanceId})`}\n                      </MenuItem>\n                    );\n                  });\n                });\n              }\n            }\n          }\n        } catch (e) {\n          console.log(e);\n        }\n\n        if (menuItems.length === 0) {\n          menuItems.push(\n            <MenuItem value=\"\" key=\"no-target-apps-found\" disabled>\n              No target apps found\n            </MenuItem>\n          );\n        }\n        setTargetOptionsforContext(menuItems);\n      };\n      fetchIntents();\n    };\n\n    const handleAddIntentListener = () => {\n      if (!intentListener) {\n        setIntentError('Enter intent');\n        return;\n      } else {\n        intentStore.addIntentListener(\n          intentListener.value,\n          sendIntentResult && resultType === 'context-result' ? toJS(resultTypeContext) : null,\n          sendIntentResult && resultType === 'channel-result' ? currentAppChannelId : undefined,\n          sendIntentResult && resultType === 'channel-result' ? channelType === 'private-channel' : undefined,\n          sendIntentResult && resultType === 'channel-result' ? resultOverChannelContextList : undefined,\n          sendIntentResult && resultType === 'channel-result' ? resultOverChannelContextDelays : undefined\n        );\n        setIntentListener(null);\n      }\n      setSendIntentResult(false);\n    };\n\n    const handleChannelTypeChange = (event: React.MouseEvent<HTMLElement>, nextView: string) => {\n      setChannelType(nextView);\n    };\n\n    const handleTargetToggle = (event: ChangeEvent<HTMLInputElement>, checked: boolean) => {\n      setUseTargets(checked);\n      if (!checked) {\n        clearTargets();\n      }\n    };\n\n    const handleContextTargetToggle = (event: ChangeEvent<HTMLInputElement>, checked: boolean) => {\n      setUseContextTargets(checked);\n      if (!checked) {\n        clearContextTargets();\n      }\n    };\n\n    const setChannelContextList = (context: ContextType, index: number) => {\n      setResultOverChannelContextList((curr: Record<string, ContextType>) => {\n        return { ...curr, [index]: context };\n      });\n    };\n\n    const setChannelContextDelay = (delay: string, index: number) => {\n      setResultOverChannelContextDelays((curr: Record<string, number>) => {\n        const lastDelay = curr[index - 1] || 0;\n        return { ...curr, [index]: lastDelay + Number(delay) };\n      });\n    };\n\n    const handleAddContextField = () => {\n      setContextFields(current => [\n        ...current,\n        <Grid container direction=\"row\" key={contextFields.length}>\n          <Grid item sx={styles.indentLeft}>\n            <TextField\n              variant=\"outlined\"\n              label=\"Delay (ms)\"\n              type=\"number\"\n              size=\"small\"\n              onChange={e => setChannelContextDelay(e.target.value, contextFields.length)}\n            />\n          </Grid>\n          <Grid item sx={{ ...styles.indentLeft, ...styles.field }}>\n            <ContextTemplates\n              handleTabChange={handleTabChange}\n              contextStateSetter={(context: ContextType | null) => {\n                if (context) setChannelContextList(context, contextFields.length);\n              }}\n            />\n          </Grid>\n        </Grid>,\n      ]);\n    };\n\n    useEffect(() => {\n      setIntentValue(null);\n      const fetchIntents = async () => {\n        try {\n          if (!raiseIntentContext) {\n            return;\n          }\n          setRaiseIntentError(false);\n          const appIntents = await getWorkbenchAgent().then(agent =>\n            agent.findIntentsByContext(toJS(raiseIntentContext))\n          );\n\n          setUseTargets(false);\n          clearTargets();\n\n          if (appIntents.length > 0) {\n            const options = appIntents.map(({ intent }: { intent: { name: string } }) => {\n              return {\n                title: intent.name,\n                value: intent.name,\n              };\n            });\n            console.log(`got intent options: ${JSON.stringify(options, null, 2)}`);\n            setIntentsForContext(options);\n          }\n        } catch {\n          setIntentsForContext([]);\n          setRaiseIntentError('no intents found');\n        }\n      };\n      fetchIntents();\n    }, [raiseIntentContext]);\n\n    useEffect(() => {\n      if (!intentValue) {\n        setUseTargets(false);\n        clearTargets();\n        return;\n      }\n    }, [intentValue]);\n\n    useEffect(() => {\n      clearContextTargets();\n      if (!raiseIntentWithContextContext) {\n        setUseContextTargets(false);\n        return;\n      }\n    }, [raiseIntentWithContextContext]);\n\n    useEffect(() => {\n      if (sendResultOverChannel) {\n        handleAddContextField();\n      } else {\n        setContextFields([]);\n      }\n    }, [sendResultOverChannel]);\n\n    return (\n      <div style={styles.root}>\n        <Grid item xs={12}>\n          <Typography variant=\"h5\">Raise intent</Typography>\n        </Grid>\n\n        <form style={styles.form} noValidate autoComplete=\"off\">\n          <Grid container direction=\"row\" spacing={2}>\n            <Grid container item spacing={2} justifyContent=\"flex-end\" sx={styles.spread}>\n              <Grid item sx={styles.field}>\n                <ContextTemplates handleTabChange={handleTabChange} contextStateSetter={setRaiseIntentContext} />\n                <Autocomplete\n                  sx={styles.rightPadding}\n                  id=\"raise-intent\"\n                  size=\"small\"\n                  selectOnFocus\n                  blurOnSelect\n                  clearOnBlur\n                  handleHomeEndKeys\n                  value={intentValue}\n                  onChange={handleChangeListener(setIntentValue, setRaiseIntentError)}\n                  filterOptions={filterOptions}\n                  options={intentsForContext ?? intentListenersOptions}\n                  getOptionLabel={getOptionLabel}\n                  renderInput={params => (\n                    <TemplateTextField\n                      label=\"INTENT TYPE\"\n                      placeholder=\"Enter Intent Type\"\n                      variant=\"outlined\"\n                      {...params}\n                      error={!!raiseIntentError}\n                      helperText={raiseIntentError}\n                    />\n                  )}\n                />\n                <Grid sx={styles.rightPadding}>\n                  <FormGroup>\n                    <FormControlLabel\n                      control={\n                        <Switch\n                          checked={useTargets}\n                          onChange={handleTargetToggle}\n                          color=\"primary\"\n                          disabled={!intentValue}\n                        />\n                      }\n                      label=\"Select Target\"\n                    />\n                  </FormGroup>\n\n                  {useTargets && (\n                    <FormControl variant=\"outlined\" size=\"small\" sx={styles.targetSelect}>\n                      <InputLabel id=\"intent-target-app\">Target app (optional)</InputLabel>\n                      <Select\n                        labelId=\"intent-target-app\"\n                        id=\"intent-target-app-select\"\n                        value={targetApp ?? ''}\n                        onChange={handleTargetChange}\n                        onOpen={handleTargetMenuOpen}\n                        label=\"Target App (optional)\"\n                        MenuProps={{\n                          anchorOrigin: {\n                            vertical: 'bottom',\n                            horizontal: 'left',\n                          },\n                          transformOrigin: {\n                            vertical: 'top',\n                            horizontal: 'left',\n                          },\n                        }}\n                      >\n                        {targetOptions}\n                      </Select>\n                    </FormControl>\n                  )}\n                </Grid>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Button variant=\"contained\" color=\"primary\" onClick={handleRaiseIntent} disabled={!intentValue}>\n                  Raise intent\n                </Button>\n\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={() => {\n                      const context = JSON.stringify(raiseIntentContext, null, 2);\n                      const intent = String(intentValue);\n\n                      let exampleToUse = codeExamples.raiseIntent(context, intent);\n                      if (targetApp.includes('instanceId')) {\n                        exampleToUse = codeExamples.raiseIntentInstance(context, intent);\n                      } else if (targetApp) {\n                        exampleToUse = codeExamples.raiseIntentTarget(context, intent);\n                      }\n                      copyToClipboard(exampleToUse, 'raiseIntent')();\n                    }}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#raiseintent\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n            {intentResolution?.source && (\n              <Grid container item spacing={2} justifyContent=\"flex-end\" sx={styles.spread}>\n                <Grid item sx={styles.textField}>\n                  <IntentResolutionField data={intentResolution} handleTabChange={handleTabChange} />\n                </Grid>\n                <Grid item>\n                  <Button variant=\"contained\" color=\"secondary\" onClick={() => setIntentResolution(null)}>\n                    Clear result\n                  </Button>\n                </Grid>\n              </Grid>\n            )}\n            <div style={styles.border}></div>\n\n            <Grid container item spacing={2} justifyContent=\"flex-end\" sx={styles.spread}>\n              <Grid item xs={12} sx={styles.bottomMargin}>\n                <Typography variant=\"h5\">Raise intent for context</Typography>\n              </Grid>\n              <Grid item sx={{ ...styles.field, ...styles.removeSidePadding }}>\n                <ContextTemplates\n                  handleTabChange={handleTabChange}\n                  contextStateSetter={setRaiseIntentWithContextContext}\n                />\n                <Grid sx={styles.rightPadding}>\n                  <FormGroup>\n                    <FormControlLabel\n                      control={\n                        <Switch checked={useContextTargets} color=\"primary\" onChange={handleContextTargetToggle} />\n                      }\n                      label=\"Select Target\"\n                      disabled={!raiseIntentWithContextContext}\n                    />\n                  </FormGroup>\n\n                  {useContextTargets && (\n                    <FormControl variant=\"outlined\" size=\"small\" sx={styles.targetSelect}>\n                      <InputLabel id=\"intent-context-target-app\">Target (optional)</InputLabel>\n                      <Select\n                        labelId=\"intent-context-target-app\"\n                        id=\"intent-context-target-app-select\"\n                        value={contextTargetApp ?? ''}\n                        onChange={handleContextTargetChange}\n                        onOpen={handleContextTargetMenuOpen}\n                        label=\"Target App (optional)\"\n                        MenuProps={{\n                          anchorOrigin: {\n                            vertical: 'bottom',\n                            horizontal: 'left',\n                          },\n                          transformOrigin: {\n                            vertical: 'top',\n                            horizontal: 'left',\n                          },\n                        }}\n                      >\n                        {targetOptionsforContext}\n                      </Select>\n                    </FormControl>\n                  )}\n                </Grid>\n              </Grid>\n              <Grid item sx={styles.controls}>\n                <Button\n                  disabled={!raiseIntentWithContextContext}\n                  variant=\"contained\"\n                  color=\"primary\"\n                  onClick={handleRaiseIntentForContext}\n                >\n                  Raise intent for context\n                </Button>\n\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={() => {\n                      const context = JSON.stringify(raiseIntentWithContextContext, null, 2);\n                      let exampleToUse = codeExamples.raiseIntentForContext(context);\n                      if (contextTargetApp.includes('instanceId')) {\n                        exampleToUse = codeExamples.raiseIntentForContextInstance(context);\n                      } else if (contextTargetApp) {\n                        exampleToUse = codeExamples.raiseIntentForContextTarget(context);\n                      }\n                      copyToClipboard(exampleToUse, 'raiseIntentForContext')();\n                    }}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#raiseintentforcontext\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n            {intentForContextResolution?.source && (\n              <Grid container item spacing={2} justifyContent=\"flex-end\" sx={styles.spread}>\n                <Grid item sx={styles.textField}>\n                  <IntentResolutionField data={intentForContextResolution} handleTabChange={handleTabChange} />\n                </Grid>\n                <Grid item>\n                  <Button variant=\"contained\" color=\"secondary\" onClick={() => setIntentForContextResolution(null)}>\n                    Clear result\n                  </Button>\n                </Grid>\n              </Grid>\n            )}\n            <div style={styles.border}></div>\n\n            <Grid container item spacing={2} justifyContent=\"flex-end\" sx={styles.spread}>\n              <Grid item xs={12}>\n                <Typography sx={styles.bottomMargin} variant=\"h5\">\n                  Add intent listener\n                </Typography>\n              </Grid>\n              <Grid item sx={{ ...styles.field, ...styles.removeSidePadding }}>\n                <Autocomplete\n                  id=\"intent-listener\"\n                  size=\"small\"\n                  selectOnFocus\n                  blurOnSelect\n                  clearOnBlur\n                  handleHomeEndKeys\n                  value={intentListener}\n                  onChange={handleChangeListener(setIntentListener, setIntentError)}\n                  filterOptions={filterOptions}\n                  options={intentListenersOptions}\n                  getOptionLabel={getOptionLabel}\n                  renderInput={params => (\n                    <TemplateTextField\n                      label=\"INTENT LISTENER\"\n                      placeholder=\"Enter Intent Type\"\n                      variant=\"outlined\"\n                      {...params}\n                      error={!!intentError}\n                      helperText={intentError}\n                    />\n                  )}\n                />\n              </Grid>\n\n              <Grid item sx={styles.controls}>\n                <Button\n                  variant=\"contained\"\n                  color=\"primary\"\n                  onClick={handleAddIntentListener}\n                  disabled={intentListener === null}\n                >\n                  Add listener\n                </Button>\n\n                <Tooltip title=\"Copy code example\" aria-label=\"Copy code example\">\n                  <IconButton\n                    size=\"small\"\n                    aria-label=\"Copy code example\"\n                    color=\"primary\"\n                    onClick={() => {\n                      let exampleToUse = codeExamples.intentListener;\n                      if (resultType === 'context-result') {\n                        exampleToUse = codeExamples.intentListenerWithContextResult;\n                      } else if (resultType === 'channel-result') {\n                        if (channelType === 'app-channel') {\n                          exampleToUse = codeExamples.intentListenerWithAppChannel;\n                        } else {\n                          exampleToUse = codeExamples.intentListenerWithPrivateChannel;\n                        }\n                      }\n                      copyToClipboard(exampleToUse, 'addIntentListener')();\n                    }}\n                  >\n                    <FileCopyIcon />\n                  </IconButton>\n                </Tooltip>\n\n                <Link\n                  onClick={openApiDocsLink}\n                  target=\"FDC3APIDocs\"\n                  href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#addintentlistener\"\n                >\n                  <InfoOutlinedIcon />\n                </Link>\n              </Grid>\n            </Grid>\n            {window.fdc3Version === '2.0' && (\n              <Grid item xs={12}>\n                <FormGroup>\n                  <FormControlLabel\n                    control={\n                      <Checkbox\n                        sx={styles.input}\n                        color=\"default\"\n                        checked={sendIntentResult}\n                        onChange={e => setSendIntentResult(e.target.checked)}\n                      />\n                    }\n                    label=\"Send intent result\"\n                  />\n                </FormGroup>\n              </Grid>\n            )}\n            {sendIntentResult && (\n              <Grid item xs={12} sx={styles.indentLeft}>\n                <RadioGroup name=\"intent-result-type\" value={resultType} onChange={e => setResultType(e.target.value)}>\n                  <FormControlLabel\n                    value=\"context-result\"\n                    control={<Radio sx={styles.input} />}\n                    label=\"Context result\"\n                  />\n                  {resultType === 'context-result' && (\n                    <Grid item sx={styles.indentLeft}>\n                      <ContextTemplates handleTabChange={handleTabChange} contextStateSetter={setResultTypeContext} />\n                    </Grid>\n                  )}\n                  <FormControlLabel\n                    value=\"channel-result\"\n                    control={<Radio sx={styles.input} />}\n                    label=\"Channel result\"\n                  />\n                  {resultType === 'channel-result' && (\n                    <Grid item sx={styles.indentLeft}>\n                      <ToggleButtonGroup\n                        value={channelType}\n                        exclusive\n                        onChange={handleChannelTypeChange}\n                        aria-label=\"result channel type\"\n                      >\n                        <ToggleButton sx={styles.toggle} value=\"app-channel\" aria-label=\"left aligned\">\n                          App channel\n                        </ToggleButton>\n                        <ToggleButton sx={styles.toggle} value=\"private-channel\" aria-label=\"left aligned\">\n                          Private channel\n                        </ToggleButton>\n                      </ToggleButtonGroup>\n\n                      {channelType === 'app-channel' && (\n                        <Grid item sx={styles.field}>\n                          <TextField\n                            fullWidth\n                            variant=\"outlined\"\n                            label=\"Channel Name\"\n                            type=\"text\"\n                            size=\"small\"\n                            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n                              setCurrentAppChannelId(e.target.value)\n                            }\n                            value={currentAppChannelId}\n                          />\n                        </Grid>\n                      )}\n                      <FormGroup>\n                        {channelType === 'private-channel' && (\n                          <Typography variant=\"caption\" sx={styles.caption}>\n                            Context streaming will start AFTER a context listener is added to the channel\n                          </Typography>\n                        )}\n                        <FormControlLabel\n                          control={\n                            <Checkbox\n                              sx={styles.input}\n                              color=\"default\"\n                              checked={sendResultOverChannel}\n                              onChange={e => setSendResultOverChannel(e.target.checked)}\n                            />\n                          }\n                          label=\"Send context result over channel\"\n                        />\n                      </FormGroup>\n                      {sendResultOverChannel && (\n                        <>\n                          {contextFields.map((field, index) => (\n                            <React.Fragment key={index}>{field}</React.Fragment>\n                          ))}\n                          <Grid item sx={{ ...styles.indentLeft, ...styles.controls }}>\n                            <Tooltip\n                              title=\"Add context result (delays will trigger sequentially)\"\n                              aria-label=\"Add context result (delays will trigger sequentially)\"\n                            >\n                              <IconButton\n                                size=\"small\"\n                                aria-label=\"Add context result (delays will trigger sequentially)\"\n                                color=\"primary\"\n                                onClick={handleAddContextField}\n                              >\n                                <AddCircleOutlineIcon />\n                              </IconButton>\n                            </Tooltip>\n\n                            <Link\n                              target=\"FDC3APIDocs\"\n                              href=\"https://fdc3.finos.org/docs/api/ref/DesktopAgent#addintentlistener\"\n                            >\n                              <InfoOutlinedIcon />\n                            </Link>\n                          </Grid>\n                        </>\n                      )}\n                    </Grid>\n                  )}\n                </RadioGroup>\n              </Grid>\n            )}\n            <Grid item xs={12}>\n              <Alert severity=\"info\">\n                Desktop Agents often require apps that listen for intents to include the intent in their appD record.\n                Refer to your Desktop Agent&apos;s documentation if the workbench doesn&apos;t appear in the intent\n                resolver.\n              </Alert>\n            </Grid>\n          </Grid>\n        </form>\n      </div>\n    );\n  }\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/AppChannelListeners.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport appChannelStore from '../../store/AppChannelStore.js';\nimport { AccordionList, AccordionListItem } from '../common/AccordionList.js';\nimport { TextField } from '@mui/material';\nimport { ReceivedField } from './ReceivedField.js';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n  },\n} as const;\n\nexport const AppChannelListeners = observer(() => {\n  const contextListeners: AccordionListItem[] = [];\n\n  appChannelStore.channelListeners.forEach(({ id, channelId, type, lastReceivedContext, metaData }) => {\n    const receivedContextListenerValue = lastReceivedContext ? JSON.stringify(lastReceivedContext, undefined, 4) : '';\n    const contextField = (\n      <div>\n        <TextField\n          disabled\n          label={'LAST RECEIVED CONTEXT'}\n          sx={classes.textField}\n          InputLabelProps={{\n            shrink: true,\n          }}\n          contentEditable={false}\n          fullWidth\n          multiline\n          variant=\"outlined\"\n          size=\"small\"\n          value={receivedContextListenerValue}\n          InputProps={{\n            sx: classes.input,\n          }}\n        />\n        {window.fdc3Version === '2.0' && <ReceivedField metaData={metaData} />}\n      </div>\n    );\n\n    contextListeners.push({ id, textPrimary: `${channelId}: ${type}`, afterEachElement: contextField });\n  });\n\n  const handleDeleteListener = (id: string) => {\n    appChannelStore.removeContextListener(id);\n  };\n\n  return (\n    <AccordionList\n      title=\"App Channels\"\n      icon=\"Any context already in the channel will NOT be received automatically\"\n      noItemsText=\"No App Channel Listeners\"\n      listItems={contextListeners}\n      onDelete={handleDeleteListener}\n    />\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/ContextListeners.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport contextStore from '../../store/ContextStore.js';\nimport { AccordionList, AccordionListItem } from '../common/AccordionList.js';\nimport { TextField } from '@mui/material';\nimport { ReceivedField } from './ReceivedField.js';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n  },\n} as const;\n\nexport const ContextListeners = observer(() => {\n  const contextListeners: AccordionListItem[] = contextStore.contextListeners.map(\n    ({ id, type, lastReceivedContext, metaData }) => {\n      const receivedContextListenerValue = lastReceivedContext ? JSON.stringify(lastReceivedContext, undefined, 4) : '';\n\n      const contextField = (\n        <div>\n          <TextField\n            disabled\n            label={'LAST RECEIVED CONTEXT'}\n            sx={classes.textField}\n            InputLabelProps={{\n              shrink: true,\n            }}\n            contentEditable={false}\n            fullWidth\n            multiline\n            variant=\"outlined\"\n            size=\"small\"\n            value={receivedContextListenerValue}\n            InputProps={{\n              sx: classes.input,\n            }}\n          />\n          {window.fdc3Version === '2.0' && <ReceivedField metaData={metaData} />}\n        </div>\n      );\n\n      return { id, textPrimary: `${type}`, afterEachElement: contextField };\n    }\n  );\n\n  const handleDeleteListener = (id: string) => {\n    contextStore.removeContextListener(id);\n  };\n\n  return (\n    <AccordionList\n      title=\"User Channels\"\n      icon=\"Any context already in the channel will be received automatically\"\n      noItemsText=\"No User Channel Listeners\"\n      listItems={contextListeners}\n      onDelete={handleDeleteListener}\n    />\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/CurrentContext.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport { TextField } from '@mui/material';\nimport { AccordionContent } from '../common/AccordionContent.js';\nimport contextStore from '../../store/ContextStore.js';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: (theme: { palette: { text: { primary: string } } }) => {\n    return {\n      fontSize: '14px',\n      color: theme.palette.text.primary,\n    };\n  },\n} as const;\n\nexport const CurrentContext = observer(() => {\n  const context = JSON.stringify(contextStore.currentContext, undefined, 4);\n\n  return (\n    <AccordionContent title=\"Context\">\n      <TextField\n        disabled\n        sx={classes.textField}\n        id=\"context-id\"\n        contentEditable={false}\n        fullWidth\n        multiline\n        variant=\"outlined\"\n        size=\"small\"\n        value={context}\n        InputProps={{\n          sx: classes.input,\n        }}\n      />\n    </AccordionContent>\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/IntentListeners.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport intentStore from '../../store/IntentStore.js';\nimport { AccordionList, AccordionListItem } from '../common/AccordionList.js';\nimport { TextField } from '@mui/material';\nimport { ReceivedField } from './ReceivedField.js';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n    color: 'rgba(0, 0, 0, 0.6)',\n  },\n} as const;\n\nexport const IntentListeners = observer(() => {\n  const intentListeners: AccordionListItem[] = intentStore.intentListeners.map(\n    ({ id, type, lastReceivedContext, metaData }) => {\n      const receivedContextListenerValue = lastReceivedContext ? JSON.stringify(lastReceivedContext, undefined, 4) : '';\n\n      const contextField = (\n        <div>\n          <TextField\n            disabled\n            label={'LAST RECEIVED CONTEXT'}\n            sx={classes.textField}\n            InputLabelProps={{\n              shrink: true,\n            }}\n            contentEditable={false}\n            fullWidth\n            multiline\n            variant=\"outlined\"\n            size=\"small\"\n            value={receivedContextListenerValue}\n            InputProps={{\n              sx: classes.input,\n            }}\n          />\n          {window.fdc3Version === '2.0' && <ReceivedField metaData={metaData} />}\n        </div>\n      );\n\n      return { id, textPrimary: `${type}`, afterEachElement: contextField };\n    }\n  );\n\n  const handleDeleteListener = (id: string) => {\n    intentStore.removeIntentListener(id);\n  };\n\n  return (\n    <AccordionList\n      title=\"Intents\"\n      noItemsText=\"No Intent Listeners\"\n      listItems={intentListeners}\n      onDelete={handleDeleteListener}\n    />\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/PrivateChannelListeners.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport privateChannelStore from '../../store/PrivateChannelStore.js';\nimport { AccordionList, AccordionListItem } from '../common/AccordionList.js';\nimport { TextField } from '@mui/material';\nimport { ReceivedField } from './ReceivedField.js';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n  },\n} as const;\n\nexport const PrivateChannelListeners = observer(() => {\n  const contextListeners: AccordionListItem[] = [];\n\n  privateChannelStore.channelListeners.forEach(({ id, channelId, type, lastReceivedContext, metaData }) => {\n    const receivedContextListenerValue = lastReceivedContext ? JSON.stringify(lastReceivedContext, undefined, 4) : '';\n    const contextField = (\n      <div>\n        <TextField\n          disabled\n          label={'LAST RECEIVED CONTEXT'}\n          sx={classes.textField}\n          InputLabelProps={{\n            shrink: true,\n          }}\n          contentEditable={false}\n          fullWidth\n          multiline\n          variant=\"outlined\"\n          size=\"small\"\n          value={receivedContextListenerValue}\n          InputProps={{\n            sx: classes.input,\n          }}\n        />\n        {window.fdc3Version === '2.0' && <ReceivedField metaData={metaData} />}\n      </div>\n    );\n\n    contextListeners.push({ id, textPrimary: `Channel Id: ${channelId}: ${type}`, afterEachElement: contextField });\n  });\n\n  const handleDeleteListener = (id: string) => {\n    privateChannelStore.removeContextListener(id);\n  };\n\n  return (\n    <AccordionList\n      title=\"Private Channels\"\n      icon=\"Any context already in the channel will NOT be received automatically\"\n      noItemsText=\"No Private Channel Listeners\"\n      listItems={contextListeners}\n      onDelete={handleDeleteListener}\n    />\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/ReceivedField.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport { TextField } from '@mui/material';\n\nimport { ContextMetadata } from '@finos/fdc3-standard';\n\nconst classes = {\n  textField: {\n    mt: 2,\n    width: '100%',\n  },\n  input: {\n    fontSize: '14px',\n  },\n} as const;\n\nexport const ReceivedField = observer(({ metaData }: { metaData: ContextMetadata | undefined }) => {\n  const formattedData = !metaData?.source\n    ? 'METADATA NOT PROVIDED'\n    : `appId: ${metaData.source.appId}\\ninstanceId: ${metaData.source.instanceId}`;\n\n  return (\n    <TextField\n      disabled\n      label={'RECEIVED FROM'}\n      sx={classes.textField}\n      InputLabelProps={{\n        shrink: true,\n      }}\n      contentEditable={false}\n      fullWidth\n      multiline\n      variant=\"outlined\"\n      size=\"small\"\n      value={formattedData}\n      InputProps={{\n        sx: classes.input,\n      }}\n    />\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/SystemLog.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { observer } from 'mobx-react';\nimport { List } from '@mui/material';\nimport systemLogStore from '../../store/SystemLogStore.js';\nimport { SystemLogItem } from './SystemLogItem.js';\n\nconst classes = {\n  root: {\n    width: '100%',\n  },\n} as const;\n\nexport const SystemLog = observer(() => (\n  <List component=\"nav\" sx={classes.root} aria-label=\"mailbox folders\">\n    {systemLogStore.logList.map(logItem => (\n      <SystemLogItem key={logItem.id} logItem={logItem} />\n    ))}\n  </List>\n));\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/SystemLogItem.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { ListItem, TextField, Typography } from '@mui/material';\nimport { LogItem } from '../../store/SystemLogStore.js';\nimport { SxProps, Theme } from '@mui/material/styles';\n\ninterface SystemLogItemProps {\n  logItem: LogItem;\n}\n\nconst classes = {\n  root: {\n    flexDirection: 'column',\n    justifyContent: 'flex-start',\n    alignItems: 'flex-start',\n    py: 3,\n    px: 0,\n    '&:first-of-type': {\n      borderTop: '1px solid rgba(0, 0, 0, 0.12)',\n    },\n  },\n  textField: {\n    width: '100%',\n  },\n  input: (theme: Theme) => {\n    return {\n      fontSize: '14px',\n      color: theme.palette.text.primary,\n    };\n  },\n} as const;\n\nconst getMessageSx = (logItem: LogItem): SxProps<Theme> => {\n  return {\n    color: theme => theme.palette[logItem.type].dark,\n  };\n};\n\nexport const SystemLogItem: React.FC<SystemLogItemProps> = (props: SystemLogItemProps) => {\n  const { logItem } = props;\n\n  return (\n    <ListItem sx={classes.root} divider>\n      <Typography sx={getMessageSx(logItem)} variant=\"body1\">\n        {logItem.message}\n      </Typography>\n\n      {logItem.variant === 'code' && (\n        <TextField\n          disabled\n          sx={classes.textField}\n          id={logItem.id}\n          contentEditable={false}\n          fullWidth\n          multiline\n          variant=\"outlined\"\n          size=\"small\"\n          value={logItem.body}\n          InputProps={{\n            sx: classes.input,\n          }}\n        />\n      )}\n\n      {logItem.variant === 'text' && logItem.body && (\n        <Typography variant=\"body1\">\n          {logItem.type === 'error' && 'ERROR:'}\n          {logItem.type === 'warning' && 'WARNING:'}\n          {logItem.type === 'info' && 'INFO:'}\n          {logItem.type === 'success' && 'SUCCESS:'}\n\n          {logItem.body}\n        </Typography>\n      )}\n    </ListItem>\n  );\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/Workbench/Workbench.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useState } from 'react';\nimport { observer } from 'mobx-react';\nimport { GlobalStyles, Tooltip } from '@mui/material';\nimport InfoIcon from '@mui/icons-material/Info';\nimport { Tabs, Tab } from '@mui/material';\nimport { TabPanel } from '../common/TabPanel.js';\nimport { ContextListeners } from './ContextListeners.js';\nimport { IntentListeners } from './IntentListeners.js';\nimport { AppChannelListeners } from './AppChannelListeners.js';\nimport { SystemLog } from './SystemLog.js';\nimport { PrivateChannelListeners } from './PrivateChannelListeners.js';\n\nconst classes = {\n  root: {\n    flexGrow: 1,\n  },\n  paper: () => {\n    return {\n      mt: 2,\n      p: 2,\n      '&:first-of-type': {\n        mt: 0,\n      },\n    };\n  },\n  systemLog: {\n    maxHeight: '1000px',\n    overflowY: 'scroll',\n  },\n  indicator: {\n    backgroundColor: '#00bbe1',\n  },\n  tabs: {\n    borderBottomColor: '#acb2c0',\n    borderBottomStyle: 'solid',\n    borderBottomWidth: '1px',\n    minHeight: '28px',\n  },\n  icon: {\n    mb: '3px',\n    fontSize: '15px',\n    mr: '3px',\n  },\n} as const;\n\nconst globalStyles = {\n  '.MuiTab-wrapper': {\n    flexDirection: 'row !important',\n  },\n};\n\nconst a11yProps = (index: number) => {\n  return {\n    id: `scrollable-auto-tab-${index}`,\n    'aria-controls': `scrollable-auto-tabpanel-${index}`,\n  };\n};\n\nexport const Workbench = observer(() => {\n  const [tabValue, setTabValue] = useState<number>(0);\n\n  const handleTabChange = (event: React.ChangeEvent<object>, newValue: number) => {\n    setTabValue(newValue);\n  };\n\n  return (\n    <div>\n      <GlobalStyles styles={globalStyles} />\n      <Tabs\n        value={tabValue}\n        onChange={handleTabChange}\n        indicatorColor=\"primary\"\n        variant=\"scrollable\"\n        scrollButtons=\"auto\"\n        sx={{\n          '& .MuiTabs-indicator': classes.indicator,\n          ...classes.tabs,\n        }}\n      >\n        <Tab\n          label=\"Listeners\"\n          {...a11yProps(0)}\n          style={{ display: 'flex', alignItems: 'center' }}\n          icon={\n            <Tooltip\n              title=\"Context received will be displayed here, but you will not receive your own messages back\"\n              aria-label=\"Context received will be displayed here, but you will not receive your own messages back\"\n            >\n              <InfoIcon sx={classes.icon} />\n            </Tooltip>\n          }\n        />\n        <Tab label=\"System Log\" {...a11yProps(1)} />\n      </Tabs>\n\n      <TabPanel value={tabValue} index={0}>\n        <ContextListeners />\n        <IntentListeners />\n        <AppChannelListeners />\n        <PrivateChannelListeners />\n      </TabPanel>\n\n      <div style={{ maxHeight: '1000px', overflowY: 'scroll' }}>\n        <TabPanel value={tabValue} index={1}>\n          <SystemLog />\n        </TabPanel>\n      </div>\n    </div>\n  );\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/AccordionContent.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { Theme } from '@mui/material/styles';\nimport { Accordion, AccordionDetails, AccordionSummary, Typography, Tooltip } from '@mui/material';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport InfoIcon from '@mui/icons-material/Info';\n\nexport interface AccordionContentProps {\n  title: string;\n  children: React.ReactNode;\n  icon?: string;\n}\n\nconst classes = {\n  accordion: (theme: Theme) => {\n    return {\n      margin: theme.spacing(1, 0, 0, 0),\n      boxShadow: 'none',\n      '&::before': {\n        display: 'none',\n      },\n      '&.Mui-expanded': {\n        margin: theme.spacing(1, 0, 0, 0),\n      },\n    };\n  },\n  accordionSummary: {\n    border: 'none',\n    padding: 0,\n    minHeight: 'initial',\n    '&.Mui-expanded': {\n      minHeight: 'initial',\n    },\n    '& .MuiAccordionSummary-content': {\n      margin: '0 12px 0 0',\n      '&.Mui-expanded': {\n        margin: '0 12px 0 0',\n      },\n    },\n    '& .MuiAccordionSummary-expandIcon': {\n      padding: '6px',\n    },\n  },\n  accordionDetails: {\n    paddingTop: 0,\n    paddingLeft: 0,\n    flexDirection: 'column',\n  },\n  accordionTitle: {\n    color: '#0086bf',\n    fontSize: '16px',\n  },\n  expand_icon: {\n    color: '#0086bf',\n  },\n  icon: {\n    marginBottom: '-1px !important',\n    fontSize: '15px',\n    marginLeft: '5px',\n  },\n} as const;\n\nexport const AccordionContent: React.FC<AccordionContentProps> = ({ icon, title, children }: AccordionContentProps) => (\n  <Accordion sx={classes.accordion} defaultExpanded>\n    <AccordionSummary\n      sx={classes.accordionSummary}\n      expandIcon={<ExpandMoreIcon sx={classes.expand_icon} />}\n      aria-label=\"Expand\"\n      aria-controls=\"additional-actions1-content\"\n      id=\"additional-actions1-header\"\n    >\n      <Typography variant=\"h5\" sx={classes.accordionTitle}>\n        {title}\n        {icon && (\n          <Tooltip title={icon} aria-label={icon}>\n            <InfoIcon sx={classes.icon} />\n          </Tooltip>\n        )}\n      </Typography>\n    </AccordionSummary>\n\n    <AccordionDetails sx={classes.accordionDetails}>{children}</AccordionDetails>\n  </Accordion>\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/AccordionList.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { List, ListItem, ListItemText, Typography, ListItemSecondaryAction, IconButton } from '@mui/material';\nimport { Theme } from '@mui/material/styles';\nimport { AccordionContent } from './AccordionContent.js';\nimport DeleteIcon from '@mui/icons-material/Delete';\n\nexport interface AccordionListItem {\n  id: string;\n  textPrimary: string;\n  afterEachElement?: React.ReactNode;\n}\n\nexport interface AccordionListProps {\n  title: string;\n  icon?: string;\n  listItems: AccordionListItem[];\n  noItemsText: string;\n  onDelete?: (id: string) => void;\n}\n\nconst classes = {\n  list: {\n    padding: 0,\n    width: '100%',\n  },\n  listItem: (theme: Theme) => {\n    return {\n      padding: 0,\n      '&.MuiListItem-secondaryAction': {\n        paddingRight: theme.spacing(6),\n      },\n    };\n  },\n  listAction: {\n    top: '2px',\n    transform: 'none',\n  },\n} as const;\n\nexport const AccordionList: React.FC<AccordionListProps> = ({\n  title,\n  icon,\n  listItems,\n  noItemsText,\n  onDelete,\n}: AccordionListProps) => {\n  const handleDelete = (id: string) => () => {\n    if (onDelete) {\n      onDelete(id);\n    }\n  };\n\n  return (\n    <AccordionContent title={title} icon={icon}>\n      {!listItems.length && <Typography variant=\"body1\">{noItemsText}</Typography>}\n      {!!listItems.length && (\n        <List sx={classes.list}>\n          {listItems.map(({ id, textPrimary, afterEachElement }) => (\n            <ListItem key={id} sx={classes.listItem} disableGutters>\n              <ListItemText disableTypography primary={textPrimary} secondary={afterEachElement} />\n              <ListItemSecondaryAction sx={classes.listAction}>\n                {onDelete && (\n                  <IconButton size=\"small\" edge=\"end\" aria-label=\"delete\" onClick={handleDelete(id)}>\n                    <DeleteIcon />\n                  </IconButton>\n                )}\n              </ListItemSecondaryAction>\n            </ListItem>\n          ))}\n        </List>\n      )}\n    </AccordionContent>\n  );\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/CopyToClipboard.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { runInAction } from 'mobx';\nimport systemLogStore from '../../store/SystemLogStore.js';\n\nexport const copyToClipboard = (text: string, name: string) => () => {\n  navigator.clipboard.writeText(text);\n  runInAction(() => {\n    systemLogStore.addLog({\n      name: 'copyToClipboard',\n      type: 'info',\n      value: name,\n      variant: 'text',\n    });\n  });\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/DialogModal.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport * as React from 'react';\nimport { Button, DialogTitle, DialogActions, Dialog } from '@mui/material';\n\ninterface DialogModalProps {\n  open: boolean;\n  onClose: (value: boolean) => void;\n  onAgree: (value: string) => void;\n  selectedValue: { id: string; name?: string } | null;\n}\n\nexport function DialogModal(props: DialogModalProps) {\n  const { onClose, onAgree, open, selectedValue } = props;\n\n  const handleClose = () => {\n    onClose(false);\n  };\n\n  const handleAgree = () => {\n    onAgree(selectedValue?.id || '');\n    onClose(false);\n  };\n\n  return (\n    <Dialog\n      open={open}\n      onClose={handleClose}\n      aria-labelledby=\"alert-dialog-title\"\n      aria-describedby=\"alert-dialog-description\"\n    >\n      <DialogTitle id=\"alert-dialog-title\">\n        {`Delete context example: ${selectedValue?.name || selectedValue?.id}`}\n      </DialogTitle>\n      <DialogActions>\n        <Button onClick={handleClose}>Disagree</Button>\n        <Button onClick={handleAgree} autoFocus>\n          Agree\n        </Button>\n      </DialogActions>\n    </Dialog>\n  );\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/JsonInput.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport JSONEditor, { JSONEditorOptions, ParseError, SchemaValidationError } from 'jsoneditor';\nimport 'jsoneditor/dist/jsoneditor.css';\nimport $RefParser from '@apidevtools/json-schema-ref-parser';\nimport { Theme } from '@mui/material/styles';\nimport { Box } from '@mui/material';\n\ninterface JsonInputProps {\n  json?: object | null;\n  schemaUrl?: URL | null;\n  schema?: object | null;\n  onJsonError?: (errors: Array<string>) => void;\n  readOnly?: boolean;\n  onChange: (value: object | null) => void;\n  error?: string | false;\n}\n\nconst classes = {\n  root: (theme: Theme) => {\n    return {\n      position: 'relative',\n      flexGrow: 1,\n      padding: theme.spacing(1),\n      border: `1px solid #0086bf`,\n      borderRadius: theme.shape.borderRadius,\n      '& .jsoneditor': {\n        border: 'none',\n      },\n      '& .ace-jsoneditor .ace_gutter': {\n        backgroundColor: 'transparent',\n      },\n      '& .ace-jsoneditor .ace_gutter-active-line': {\n        backgroundColor: theme.palette.grey['200'],\n      },\n      '& .ace-jsoneditor .ace_marker-layer .ace_active-line': {\n        backgroundColor: theme.palette.grey['200'],\n      },\n    };\n  },\n  jsonInput: {\n    height: '270px',\n  },\n  errorText: (theme: Theme) => {\n    return {\n      bottom: '-8px',\n      padding: theme.spacing(0, 0.5),\n      fontSize: '0.75rem',\n      position: 'absolute',\n      backgroundColor: '#fff',\n      color: theme.palette.error.main,\n    };\n  },\n} as const;\n\nexport const JsonInput: React.FC<JsonInputProps> = (props: JsonInputProps) => {\n  const [jsoneditor, setJsoneditor] = useState<JSONEditor>();\n  const container = useRef<HTMLDivElement>(null);\n  const initialSettings: JSONEditorOptions = {\n    mode: 'code',\n    mainMenuBar: false,\n    statusBar: false,\n    indentation: 2,\n    onChangeText: (text: string) => {\n      if (text === '') {\n        props.onChange(null);\n      } else {\n        try {\n          props.onChange(JSON.parse(text));\n          // eslint-disable-next-line no-empty, @typescript-eslint/no-unused-vars\n        } catch (e) {}\n      }\n    },\n    onValidationError: (error: readonly (SchemaValidationError | ParseError)[]) => {\n      if (props.onJsonError) {\n        if (error.length > 0) {\n          const errorMsg: string = error[0].type === 'error' ? 'Bad json format' : \"Json doesn't match the schema\";\n          props.onJsonError([errorMsg]);\n        } else {\n          props.onJsonError([]);\n        }\n      }\n    },\n  };\n\n  useEffect(() => {\n    (async () => {\n      const options: JSONEditorOptions = { ...initialSettings };\n\n      if (container.current) {\n        if (props.schema) {\n          try {\n            options.schema = await $RefParser.dereference(props.schema, {\n              dereference: {\n                circular: true,\n              },\n            });\n          } catch (err) {\n            console.error(err);\n          }\n        }\n\n        if (props.schemaUrl) {\n          try {\n            options.schema = await $RefParser.dereference(props.schemaUrl.href, {\n              dereference: {\n                circular: true,\n              },\n            });\n          } catch (err) {\n            console.error(err);\n          }\n        }\n\n        const editor = new JSONEditor(container.current, options, props.json);\n\n        setJsoneditor(editor);\n      }\n    })();\n\n    return jsoneditor?.destroy;\n  }, []);\n\n  useEffect(() => {\n    if (props.schema) {\n      jsoneditor?.setSchema(props.schema);\n    }\n  }, [props.schema]);\n\n  useEffect(() => {\n    (async () => {\n      if (props.schemaUrl) {\n        try {\n          const schema = await $RefParser.dereference(props.schemaUrl.href, {\n            dereference: {\n              circular: true,\n            },\n          });\n\n          jsoneditor?.setSchema(schema);\n        } catch (err) {\n          console.error(err);\n        }\n      }\n    })();\n  }, [props.schemaUrl]);\n\n  useEffect(() => {\n    if (jsoneditor && (props.json || props.json === null)) {\n      if (props.json === null) {\n        jsoneditor.set({});\n      } else {\n        jsoneditor.set(props.json);\n      }\n    }\n  }, [props.json, jsoneditor]);\n\n  return (\n    <Box sx={classes.root} tabIndex={0}>\n      <Box sx={classes.jsonInput} ref={container} />\n      {!!props.error && <Box sx={classes.errorText}>{props.error}</Box>}\n    </Box>\n  );\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/TabPanel.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport React from 'react';\nimport { Theme } from '@mui/material/styles';\nimport { Box } from '@mui/material';\n\ninterface TabPanelProps {\n  children?: React.ReactNode;\n  index: number;\n  value: number;\n}\n\nconst classes = {\n  tabPanel: (theme: Theme) => {\n    return {\n      padding: theme.spacing(2),\n    };\n  },\n} as const;\n\nexport const TabPanel: React.FC<TabPanelProps> = (props: TabPanelProps) => {\n  const { children, value, index, ...other } = props;\n\n  return (\n    <div\n      role=\"tabpanel\"\n      hidden={value !== index}\n      id={`scrollable-auto-tabpanel-${index}`}\n      aria-labelledby={`scrollable-auto-tab-${index}`}\n      {...other}\n    >\n      {value === index && <Box sx={classes.tabPanel}>{children}</Box>}\n    </div>\n  );\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/components/common/TemplateTextField.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { styled } from '@mui/material/styles';\nimport { TextField } from '@mui/material';\n\nexport const TemplateTextField = styled(TextField)({\n  '& label.Mui-focused': {\n    color: '#0086bf',\n  },\n  '& .MuiInput-underline:after': {\n    borderBottomColor: '#0086bf',\n  },\n  '& .MuiOutlinedInput-root': {\n    '& fieldset': {\n      borderColor: '#0086bf',\n    },\n    '&:hover fieldset': {\n      borderColor: '#0086bf',\n    },\n    '&.Mui-focused fieldset': {\n      borderColor: '#0086bf',\n    },\n  },\n});\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/fixtures/codeExamples.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nexport const codeExamples = {\n  userChannels: `// get all user channels\nconst channels = await fdc3.getUserChannels();\n\n// create UI to pick from the user channels\n\n// join the channel on selection\nfdc3.joinUserChannel(selectedChannel.id);`,\n\n  getCurrentUserChannel: `// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n\n//leave the current channel\\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context`,\n\n  broadcast: `const instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);`,\n\n  appChannelBroadcast: `const instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nappChannel.broadcast(instrument);`,\n\n  raiseIntent: (context: string, intent: string) =>\n    `//Raise an intent with a specified context\nlet context = ${context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'}; \nfdc3.raiseIntent(\"${intent !== 'null' ? intent : 'ViewChart'}\", context);`,\n\n  raiseIntentTarget: (context: string, intent: string) =>\n    `//Raise an intent with a specified context\nlet context = ${context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'};\n//Find appId in promise result\nlet intent = await fdc3.findIntentsByContext(context);\nlet appId = intent[0].apps[0].appId;\nfdc3.raiseIntent(\"${intent !== 'null' ? intent : 'ViewChart'}\", context, {appId});`,\n\n  raiseIntentInstance: (context: string, intent: string) =>\n    `//Raise an intent with a specified context\nlet context = ${context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'};\n//Find appId in promise result\nlet intent = await fdc3.findIntentsByContext(context);\nlet appId = intent[0].apps[0].appId;\n//Find instanceId is promise resultlet intances = await fdc3.findInstances({appId});\nlet instanceId = instances[0].instanceId;\nfdc3.raiseIntent(\"${intent !== 'null' ? intent : 'ViewChart'}\", context, {appId, instanceId});`,\n\n  contextListener: `// any context\nconst listener = fdc3.addContextListener(null, context => {\n    //add context handling code here\n});\n\n// listener for a specific type\nconst contactListener = fdc3.addContextListener('fdc3.contact', contact => {\n    //add context handling code here\n});`,\n\n  appChannelContextListener: `// any context\nconst listener = appChannel.addContextListener(null, context => {\n    //add context handling code here\n});\n\n// listener for a specific type\nconst contactListener = appChannel.addContextListener('fdc3.contact', contact => {\n    //add context handling code here\n});`,\n\n  intentListener: `const listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n});`,\n\n  intentListenerWithContextResult: `const instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nconst listener = fdc3.addIntentListener('StartChat', context => {\n    // start chat has been requested by another application\n    return instrument;\n});`,\n\n  intentListenerWithAppChannel: `const listener = fdc3.addIntentListener('StartChat', context => {\n    // start chat has been requested by another application\n\tconst channel = await appChannelStore.getOrCreateChannel(channelName);\n\treturn channel;\n});`,\n\n  intentListenerWithPrivateChannel: `const listener = fdc3.addIntentListener('StartChat', context => {\n\t// start chat has been requested by another application\n\tconst channel = await fdc3.createPrivateChannel();\n\treturn channel;\n});`,\n\n  raiseIntentForContext: (context: string) =>\n    `let context = ${\n      context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'\n    };\n\nconst intentResolution = await fdc3.raiseIntentForContext(context);`,\n\n  raiseIntentForContextTarget: (context: string) =>\n    `let context = ${context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'};\n\n//Find appId in promise result\nlet intent = await fdc3.findIntentsByContext(context);\nlet appId = intent[0].apps[0].appId;\nconst intentResolution = await fdc3.raiseIntentForContext(context, {appId});`,\n\n  raiseIntentForContextInstance: (context: string) =>\n    `let context = ${context !== 'null' ? context : '{type: \"fdc3.instrument\", name: \"Tesla, inc.\", id: {ticker: \"TSLA\"}}'};\n\n//Find appId in promise result\nlet intent = await fdc3.findIntentsByContext(context);\nlet appId = intent[0].apps[0].appId;\n\n//Find instanceId is promise result\nlet intances = await fdc3.findInstances({appId});\nlet instanceId = instances[0].instanceId;\nconst intentResolution = await fdc3.raiseIntentForContext(context, {appId, instanceId});`,\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/fixtures/contexts.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { ContextItem } from '../store/ContextStore.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport const contexts: ContextItem[] = [\n  {\n    uuid: uuidv4(),\n    id: 'Chart example',\n    template: {\n      type: 'fdc3.chart',\n      instruments: [\n        {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'AAPL',\n          },\n        },\n        {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'GOOG',\n          },\n        },\n      ],\n      range: {\n        type: 'fdc3.timeRange',\n        startTime: '2020-09-01T08:00:00.000Z',\n        endTime: '2020-10-31T08:00:00.000Z',\n      },\n      style: 'line',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/chart.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Chat Initialization example',\n    template: {\n      type: 'fdc3.chat.initSettings',\n      chatName: 'Chat ABCD',\n      members: {\n        type: 'fdc3.contactList',\n        contacts: [\n          {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n              email: 'jane@mail.com',\n            },\n          },\n          {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n              email: 'john@mail.com',\n            },\n          },\n        ],\n      },\n      options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true,\n      },\n      message: {\n        type: 'fdc3.message',\n        text: {\n          'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot',\n        },\n        entities: {\n          0: {\n            type: 'fdc3.fileAttachment',\n            data: {\n              name: 'myImage.png',\n              dataUri:\n                'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII',\n            },\n          },\n        },\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/chatInitSettings.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Chat Message example',\n    template: {\n      type: 'fdc3.chat.message',\n      chatRoom: {\n        type: 'fdc3.chat.room',\n        providerName: 'Symphony',\n        id: {\n          streamId: 'j75xqXy25NBOdacUI3FNBH',\n        },\n      },\n      message: {\n        type: 'fdc3.message',\n        text: {\n          'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot',\n        },\n        entities: {\n          0: {\n            type: 'fdc3.fileAttachment',\n            data: {\n              name: 'myImage.png',\n              dataUri:\n                'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII',\n            },\n          },\n        },\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/chatMessage.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Chat room example',\n    template: {\n      type: 'fdc3.chat.room',\n      providerName: 'Symphony',\n      id: {\n        streamId: 'j75xqXy25NBOdacUI3FNBH',\n      },\n      url: 'http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA',\n      name: 'My new room',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/chatRoom.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Chat search example',\n    template: {\n      type: 'fdc3.chat.searchCriteria',\n      criteria: [\n        {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'AAPL',\n          },\n        },\n        {\n          type: 'fdc3.contact',\n          name: 'Jane Doe',\n          id: {\n            email: 'jane.doe@mail.com',\n          },\n        },\n        {\n          type: 'fdc3.organization',\n          name: 'Symphony',\n        },\n        '#OrderID45788422',\n      ],\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/chatSearchCriteria.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Contact example',\n    template: {\n      type: 'fdc3.contact',\n      name: 'Jane Doe',\n      id: {\n        email: 'jane.doe@mail.com',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/contact.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'ContactList example',\n    template: {\n      type: 'fdc3.contactList',\n      contacts: [\n        {\n          type: 'fdc3.contact',\n          name: 'Jane Doe',\n          id: {\n            email: 'jane.doe@mail.com',\n          },\n        },\n        {\n          type: 'fdc3.contact',\n          name: 'John Doe',\n          id: {\n            email: 'john.doe@mail.com',\n          },\n        },\n      ],\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/contactList.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Country example',\n    template: {\n      type: 'fdc3.country',\n      name: 'Sweden',\n      id: {\n        ISOALPHA3: 'SWE',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/country.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Currency example',\n    template: {\n      type: 'fdc3.currency',\n      name: 'US Dollar',\n      id: {\n        CURRENCY_ISOCODE: 'USD',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/currency.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Email example',\n    template: {\n      type: 'fdc3.email',\n      recipients: {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n          email: 'jane.doe@example.com',\n        },\n      },\n      subject: 'The information you requested',\n      textBody: 'Blah, blah, blah ...',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/email.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Instrument example - MSFT',\n    template: {\n      type: 'fdc3.instrument',\n      name: 'Microsoft',\n      id: {\n        ticker: 'MSFT',\n        RIC: 'MSFT.OQ',\n        ISIN: 'US5949181045',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/instrument.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Instrument example - AAPL',\n    template: {\n      type: 'fdc3.instrument',\n      name: 'Apple',\n      id: {\n        ticker: 'AAPL',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/instrument.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'InstrumentList example',\n    template: {\n      type: 'fdc3.instrumentList',\n      instruments: [\n        {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'AAPL',\n          },\n        },\n        {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'MSFT',\n          },\n        },\n      ],\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/instrumentList.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Interaction example',\n    template: {\n      type: 'fdc3.interaction',\n      participants: {\n        type: 'fdc3.contactList',\n        contacts: [\n          {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n              email: 'jane.doe@mail.com',\n            },\n          },\n          {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n              email: 'john.doe@mail.com',\n            },\n          },\n        ],\n      },\n      interactionType: 'Instant Message',\n      timeRange: {\n        type: 'fdc3.timeRange',\n        startTime: '2022-02-10T15:12:00Z',\n      },\n      description:\n        'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n      initiator: {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n          email: 'jane.doe@mail.com',\n        },\n      },\n      origin: 'Outlook',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/interaction.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Nothing example',\n    template: {\n      type: 'fdc3.nothing',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/nothing.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Order example',\n    template: {\n      type: 'fdc3.order',\n      name: '...',\n      id: {\n        myOMS: '12345',\n      },\n      details: {\n        product: {\n          type: 'fdc3.product',\n          id: {\n            productId: 'ABC123',\n          },\n          instrument: {\n            type: 'fdc3.instrument',\n            id: {\n              ticker: 'MSFT',\n            },\n          },\n        },\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/order.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Organization example',\n    template: {\n      type: 'fdc3.organization',\n      name: 'Cargill, Incorporated',\n      id: {\n        LEI: 'QXZYQNMR4JZ5RIRN4T31',\n        FDS_ID: '00161G-E',\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/organization.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Position example',\n    template: {\n      type: 'fdc3.position',\n      instrument: {\n        type: 'fdc3.instrument',\n        id: {\n          ticker: 'AAPL',\n        },\n      },\n      holding: 2000000,\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/position.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Portfolio example',\n    template: {\n      type: 'fdc3.portfolio',\n      positions: [\n        {\n          type: 'fdc3.position',\n          instrument: {\n            type: 'fdc3.instrument',\n            id: {\n              ticker: 'AAPL',\n            },\n          },\n          holding: 2000000,\n        },\n        {\n          type: 'fdc3.position',\n          instrument: {\n            type: 'fdc3.instrument',\n            id: {\n              ticker: 'MSFT',\n            },\n          },\n          holding: 1500000,\n        },\n        {\n          type: 'fdc3.position',\n          instrument: {\n            type: 'fdc3.instrument',\n            id: {\n              ticker: 'IBM',\n            },\n          },\n          holding: 3000000,\n        },\n      ],\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/portfolio.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Product example',\n    template: {\n      type: 'fdc3.product',\n      id: {\n        productId: 'ABC123',\n      },\n      instrument: {\n        type: 'fdc3.instrument',\n        id: {\n          ticker: 'MSFT',\n        },\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/product.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Trade example',\n    template: {\n      type: 'fdc3.trade',\n      name: '...',\n      id: {\n        myEMS: '12345',\n      },\n      product: {\n        type: 'fdc3.product',\n        id: {\n          productId: 'ABC123',\n        },\n        instrument: {\n          type: 'fdc3.instrument',\n          id: {\n            ticker: 'MSFT',\n          },\n        },\n      },\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/trade.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Transaction result example',\n    template: {\n      type: 'fdc3.transactionResult',\n      status: 'Updated',\n      context: {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n          email: 'jane.doe@mail.com',\n        },\n      },\n      message: \"record with id 'jane.doe@mail.com' was updated\",\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/transactionresult.schema.json'),\n  },\n  {\n    uuid: uuidv4(),\n    id: 'Valuation example',\n    template: {\n      type: 'fdc3.valuation',\n      value: 500.0,\n      price: 5.0,\n      CURRENCY_ISOCODE: 'USD',\n      expiryTime: '2022-05-13T16:16:24+01:00',\n    },\n    schemaUrl: new URL('https://fdc3.finos.org/schemas/next/context/valuation.schema.json'),\n  },\n];\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/fixtures/intentTypes.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nexport const intentTypes: Array<{ title: string; value: string }> = [\n  {\n    title: 'CreateInteraction',\n    value: 'CreateInteraction',\n  },\n  {\n    title: 'CreateOrUpdateProfile',\n    value: 'CreateOrUpdateProfile',\n  },\n  {\n    title: 'SendChatMessage',\n    value: 'SendChatMessage',\n  },\n  {\n    title: 'StartCall',\n    value: 'StartCall',\n  },\n  {\n    title: 'StartChat',\n    value: 'StartChat',\n  },\n  {\n    title: 'StartEmail',\n    value: 'StartEmail',\n  },\n  {\n    title: 'ViewAnalysis',\n    value: 'ViewAnalysis',\n  },\n  {\n    title: 'ViewChart',\n    value: 'ViewChart',\n  },\n  {\n    title: 'ViewChat',\n    value: 'ViewChat',\n  },\n  {\n    title: 'ViewContact',\n    value: 'ViewContact',\n  },\n  {\n    title: 'ViewHoldings',\n    value: 'ViewHoldings',\n  },\n  {\n    title: 'ViewInstrument',\n    value: 'ViewInstrument',\n  },\n  {\n    title: 'ViewInteractions',\n    value: 'ViewInteractions',\n  },\n  {\n    title: 'ViewMessages',\n    value: 'ViewMessages',\n  },\n  {\n    title: 'ViewNews',\n    value: 'ViewNews',\n  },\n  {\n    title: 'ViewOrders',\n    value: 'ViewOrders',\n  },\n  {\n    title: 'ViewProfile',\n    value: 'ViewProfile',\n  },\n  {\n    title: 'ViewQuote',\n    value: 'ViewQuote',\n  },\n  {\n    title: 'ViewResearch',\n    value: 'ViewResearch',\n  },\n];\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/fixtures/logMessages.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { logMessagesName, logMessagesType } from '../store/SystemLogStore.js';\n\ntype LogMessages = Record<logMessagesName, Partial<Record<logMessagesType, string>>>;\n\nexport const getLogMessage = (name: logMessagesName, type: logMessagesType, value: string = ''): string => {\n  const logMessages: LogMessages = {\n    getFdc3: {\n      error: `The FDC3 API is not ready${value ? ` (${value})` : ''}`,\n    },\n    getChannels: {\n      success: `Retrieved User channels`,\n      error: `Failed to retrieve User channels`,\n    },\n    getCurrentChannel: {\n      success: `Retrieved current channel [${value}]`,\n      error: `Failed to retrieve current channel`,\n    },\n    joinUserChannel: {\n      success: `Joined the [${value}] channel`,\n      error: `Failed to join the [${value}] channel`,\n    },\n    leaveChannel: {\n      success: `Left the [${value}] channel`,\n      error: `Failed to leave the [${value}] channel`,\n      warning: `Not currently joined to a channel`,\n    },\n    broadcast: {\n      success: 'Broadcast context',\n      error: 'Failed to broadcast context:',\n    },\n    appBroadcast: {\n      success: `Broadcast context to channel [${value}]: `,\n      error: `Failed to broadcast context to channel [${value}]:`,\n    },\n    raiseIntent: {\n      success: `Raised intent [${value}]`,\n      error: `Failed to raise intent [${value}]`,\n    },\n    raiseIntentForContext: {\n      success: `Raised intent for context`,\n      error: `Failed to raise intent for context`,\n    },\n    addContextListener: {\n      success: `A context listener for '[${value}]' has been added`,\n      error: `Failed to add a context listener for '[${value}]'`,\n    },\n    removeContextListener: {\n      success: `A context listener for '[${value}]' has been removed`,\n      error: `Failed to remove a context listener for '[${value}]'`,\n    },\n    removeAppChannelContextListener: {\n      success: `${value}`,\n      error: `${value}`,\n    },\n    addIntentListener: {\n      success: `An intent listener for '[${value}]' has been added`,\n      error: `Failed to add an intent listener for '[${value}]'`,\n    },\n    removeIntentListener: {\n      success: `An intent listener for '[${value}]' has been removed`,\n      error: `Failed to remove an intent listener for '[${value}]'`,\n    },\n    receivedContextListener: {\n      info: `Received context via '[${value}]' listener`,\n      error: `Failed to receive context from '[${value}]' listener`,\n    },\n    receivedAppContextListener: {\n      info: `${value}`,\n      error: `${value}`,\n    },\n    addAppContextListener: {\n      info: `${value}`,\n      error: `${value}`,\n    },\n    receivedIntentListener: {\n      info: `Received context via '[${value}]' listener.`,\n      error: `Failed to receive context from '[${value}]' listener.`,\n    },\n    saveExample: {\n      success: `Saved context example for '[${value}]'.`,\n      error: `Failed to save context example.`,\n    },\n    deleteExample: {\n      success: `Deleted context example for '[${value}]'.`,\n      error: `Failed to delete context example.`,\n    },\n    copyToClipboard: {\n      info: `${value} code snippet copied to clipboard`,\n      error: `Failed to copy code ${value} snippet to clipboard.`,\n    },\n    getOrCreateChannel: {\n      success: `Retrieved or created current app channel [${value}]`,\n      error: `Failed to retrieve or create app channel ${value}.`,\n    },\n    createPrivateChannel: {\n      success: `Created current private channel [${value}]`,\n      error: `Failed to create private channel ${value}.`,\n    },\n    pcAddContextListener: {\n      success: `${value}`,\n      error: `${value}`,\n    },\n    pcOnUnsubscribe: {\n      success: `${value}`,\n      error: `${value}`,\n    },\n    pcOnDisconnect: {\n      success: `${value}`,\n      error: `${value}`,\n    },\n  };\n\n  return logMessages[name][type] ?? (value != '' ? `${value}` : `Undefined log message ${name}.${type}`);\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/fixtures/openApiDocs.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport React from 'react';\n\nexport const openApiDocsLink = (event: React.MouseEvent<HTMLElement>) => {\n  event.preventDefault();\n  const href = event?.currentTarget?.getAttribute('href');\n  if (href) {\n    window.open(href, 'FDC3APIDocs');\n  }\n  return false;\n};\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/index.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\nimport { Buffer } from 'buffer';\nglobalThis.Buffer = Buffer;\n\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App.js';\n\n//make sure URL ends with trailing / for resolution of image paths\nif (!window.location.href.endsWith('/')) {\n  window.location.href = `${window.location.href}/`;\n}\n\nReactDOM.render(\n  <React.StrictMode>\n    <App />\n  </React.StrictMode>,\n  document.getElementById('root')\n);\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/AppChannelStore.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action, runInAction, toJS } from 'mobx';\nimport { ContextType, Fdc3Listener, getWorkbenchAgent } from '../utility/Fdc3Api.js';\nimport systemLogStore from './SystemLogStore.js';\nimport { nanoid } from 'nanoid';\nimport { Channel, ContextMetadata } from '@finos/fdc3';\n\ninterface ListenerOptionType {\n  title: string;\n  value: string;\n  type: string | undefined;\n}\n\nexport interface Fdc3ChannelRecord {\n  id: string;\n  channel: Channel;\n  currentListener?: ListenerOptionType | null;\n  broadcastError?: string;\n  context?: ContextType | null;\n  listenerError?: string;\n}\nclass AppChannelStore {\n  appChannelsList: Fdc3ChannelRecord[] = [];\n\n  currentAppChannel: Fdc3ChannelRecord | null = null;\n\n  channelListeners: Fdc3Listener[] = [];\n\n  constructor() {\n    makeObservable(this, {\n      appChannelsList: observable,\n      currentAppChannel: observable,\n      channelListeners: observable,\n      getOrCreateChannel: action,\n      leaveChannel: action,\n      broadcast: action,\n    });\n  }\n\n  async getOrCreateChannel(channelId: string) {\n    try {\n      const currentAppChannelObj = await getWorkbenchAgent().then(agent => agent.getOrCreateChannel(channelId));\n      if (currentAppChannelObj) {\n        const record = {\n          id: channelId,\n          channel: currentAppChannelObj,\n        };\n        this.currentAppChannel = record;\n        const foundChannel = this.appChannelsList.find(channel => channel.id === channelId);\n        if (!foundChannel) {\n          runInAction(() => {\n            this.appChannelsList.push(record);\n          });\n        }\n      }\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'getOrCreateChannel',\n          type: currentAppChannelObj ? 'success' : 'error',\n          value: currentAppChannelObj ? currentAppChannelObj?.id : channelId,\n          variant: 'text',\n        });\n      });\n      return currentAppChannelObj;\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'getOrCreateChannel',\n        type: 'error',\n        value: channelId,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n      return;\n    }\n  }\n\n  isContextListenerExists(channelId: string, type: string | undefined) {\n    return !!this.channelListeners?.find(listener => listener.type === type && listener.channelId === channelId);\n  }\n\n  isAppChannelExists(channelId: string) {\n    return !!this.appChannelsList.find(channel => channel.id === channelId);\n  }\n\n  async broadcast(channel: Channel, context: ContextType) {\n    const channelId = channel.id;\n    if (!context) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'warning',\n        value: `You must set a context before you can broadcast it to channel: ${channelId}`,\n        variant: 'text',\n      });\n    }\n\n    //check that we're on a channel\n    const currentChannel = this.appChannelsList.find(chan => chan.id === channelId);\n\n    if (!currentChannel) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'warning',\n        value: 'You are not currently joined to a channel (no-op)',\n        variant: 'text',\n      });\n      return;\n    }\n\n    try {\n      await currentChannel.channel.broadcast(toJS(context));\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'success',\n        body: JSON.stringify(context, null, 4),\n        variant: 'code',\n        value: channelId,\n      });\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'error',\n        body: JSON.stringify(e, null, 4),\n        variant: 'code',\n        value: channelId,\n      });\n    }\n  }\n\n  async leaveChannel() {\n    try {\n      const agent = await getWorkbenchAgent();\n      //check that we're on a channel\n      let currentChannel = await agent.getCurrentChannel();\n      if (!currentChannel) {\n        systemLogStore.addLog({\n          name: 'leaveChannel',\n          type: 'warning',\n          value: '',\n          variant: 'text',\n        });\n      } else {\n        await agent.leaveCurrentChannel();\n        currentChannel = await agent.getCurrentChannel();\n        const isSuccess = currentChannel === null;\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'leaveChannel',\n            type: isSuccess ? 'success' : 'error',\n            value: this.currentAppChannel?.id,\n            variant: 'text',\n          });\n\n          if (isSuccess) {\n            this.currentAppChannel = null;\n          }\n        });\n      }\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'leaveChannel',\n        type: 'error',\n        value: this.currentAppChannel?.id,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async addChannelListener(currChannel: Channel, newListener: string | undefined) {\n    const channelId = currChannel.id;\n    try {\n      const currentChannel = this.appChannelsList.find(channel => channel.id === channelId);\n      const foundListener = this.channelListeners.find(\n        currentListener => currentListener.type === newListener && currentListener.channelId === channelId\n      );\n\n      if (!foundListener && currentChannel && newListener !== undefined) {\n        const listenerId = nanoid();\n        const contactListener = await currentChannel.channel.addContextListener(\n          newListener?.toLowerCase() === 'all' ? null : newListener,\n          (context, metaData?: ContextMetadata) => {\n            const currentListener = this.channelListeners.find(\n              listener => listener.type === newListener && listener.channelId === channelId\n            );\n\n            runInAction(() => {\n              if (currentListener) {\n                currentListener.lastReceivedContext = context;\n                currentListener.metaData = metaData;\n              }\n            });\n\n            systemLogStore.addLog({\n              name: 'receivedAppContextListener',\n              type: 'info',\n              value: `Channel [${channelId}] Received context via '[${newListener}]' listener`,\n              variant: 'code',\n              body: JSON.stringify(context, null, 4),\n            });\n          }\n        );\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'addAppContextListener',\n            type: 'success',\n            value: `A context listener for '[${newListener}]' has been added on channel [${channelId}]`,\n            variant: 'text',\n          });\n          this.channelListeners.push({ id: listenerId, type: newListener, listener: contactListener, channelId });\n        });\n      }\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'addAppContextListener',\n        type: 'error',\n        value: `Failed to add a context listener for '[${newListener}]' on channel [${channelId}]`,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  removeContextListener(id: string) {\n    const listenerIndex = this.channelListeners?.findIndex(listener => listener.id === id);\n    const listener = this.channelListeners[listenerIndex];\n    if (listenerIndex !== -1) {\n      try {\n        this.channelListeners[listenerIndex].listener.unsubscribe();\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'removeAppChannelContextListener',\n            type: 'success',\n            value: `A context listener for '[${listener.type}]' for channel [${listener.channelId}] has been removed`,\n            variant: 'text',\n          });\n          this.channelListeners.splice(listenerIndex, 1);\n        });\n      } catch (e) {\n        systemLogStore.addLog({\n          name: 'removeAppChannelContextListener',\n          type: 'error',\n          value: `Failed to remove a context listener for '[${listener.type}]' on channel [${listener.channelId}]`,\n          variant: 'code',\n          body: JSON.stringify(e, null, 4),\n        });\n      }\n    }\n  }\n\n  remove(channel: Channel) {\n    this.channelListeners.forEach(listener => this.removeContextListener(listener.id));\n    runInAction(() => {\n      this.appChannelsList = this.appChannelsList.filter(chan => chan.id !== channel.id);\n    });\n  }\n}\n\nconst appChannelStore = new AppChannelStore();\n\nexport default appChannelStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/ChannelStore.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action, runInAction } from 'mobx';\nimport systemLogStore from './SystemLogStore.js';\nimport { Channel } from '@finos/fdc3';\nimport { getWorkbenchAgent } from '../utility/Fdc3Api.js';\n\nclass ChannelStore {\n  userChannels: Channel[] = [];\n\n  currentUserChannel: Channel | null = null;\n\n  constructor() {\n    makeObservable(this, {\n      userChannels: observable,\n      currentUserChannel: observable,\n      getUserChannels: action,\n      joinUserChannel: action,\n      leaveUserChannel: action,\n      getCurrentUserChannel: action,\n    });\n\n    this.getUserChannels();\n  }\n\n  async getCurrentUserChannel() {\n    const agent = await getWorkbenchAgent();\n    try {\n      const userChannel = await agent.getCurrentChannel();\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'getCurrentChannel',\n          type: 'success',\n          value: userChannel ? userChannel.id : 'none',\n          variant: 'text',\n        });\n        this.currentUserChannel = userChannel;\n      });\n    } catch (e) {\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'getCurrentChannel',\n          type: 'error',\n          body: (e as Error).message ?? (e as string),\n          variant: 'text',\n        });\n      });\n    }\n  }\n\n  async getUserChannels() {\n    const agent = await getWorkbenchAgent();\n    //defer retrieving channels until fdc3 API is ready\n    try {\n      //backwards compatibility for FDC3 < 2.0\n      //  don't destructure DA implementations in case their context is not bound\n      let userChannels: Channel[];\n      if (agent.getUserChannels) {\n        userChannels = await agent.getUserChannels();\n      } else {\n        userChannels = await agent.getSystemChannels();\n      }\n      const currentUserChannel = await agent.getCurrentChannel();\n\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'getChannels',\n          type: 'success',\n        });\n        this.userChannels = userChannels;\n        this.currentUserChannel = currentUserChannel;\n      });\n    } catch (e) {\n      console.error('Failed to retrieve user channels: ', e);\n      systemLogStore.addLog({\n        name: 'getChannels',\n        type: 'error',\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async joinUserChannel(channelId: string) {\n    const agent = await getWorkbenchAgent();\n    try {\n      //backwards compatibility for 1.2\n      if (agent.joinUserChannel) {\n        await agent.joinUserChannel(channelId);\n      } else {\n        await agent.joinChannel(channelId);\n      }\n\n      const currentUserChannel = await agent.getCurrentChannel();\n      const isSuccess = currentUserChannel !== null;\n\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'joinUserChannel',\n          type: isSuccess ? 'success' : 'error',\n          value: isSuccess ? currentUserChannel?.id : channelId,\n          variant: 'text',\n        });\n        this.currentUserChannel = currentUserChannel;\n      });\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'joinUserChannel',\n        type: 'error',\n        value: channelId,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async leaveUserChannel() {\n    const agent = await getWorkbenchAgent();\n    try {\n      //check that we're on a channel\n      let currentUserChannel = await agent.getCurrentChannel();\n      if (!currentUserChannel) {\n        systemLogStore.addLog({\n          name: 'leaveChannel',\n          type: 'warning',\n          value: '',\n          variant: 'text',\n        });\n      } else {\n        await agent.leaveCurrentChannel();\n        currentUserChannel = await agent.getCurrentChannel();\n        const isSuccess = currentUserChannel === null;\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'leaveChannel',\n            type: isSuccess ? 'success' : 'error',\n            value: this.currentUserChannel?.id,\n            variant: 'text',\n          });\n\n          if (isSuccess) {\n            this.currentUserChannel = null;\n          }\n        });\n      }\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'leaveChannel',\n        type: 'error',\n        value: this.currentUserChannel?.id,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n}\n\nconst channelStore = new ChannelStore();\n\nexport default channelStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/ContextStore.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, runInAction, action, toJS } from 'mobx';\nimport { ContextType, Fdc3Listener, getWorkbenchAgent } from '../utility/Fdc3Api.js';\nimport { nanoid } from 'nanoid';\nimport { contexts } from '../fixtures/contexts.js';\nimport systemLogStore from './SystemLogStore.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport { ContextMetadata } from '@finos/fdc3-standard';\n\nexport type ContextItem = {\n  id: string;\n  uuid?: string; //used to determine if a duplicate id is for the same object or not\n  template: ContextType | null;\n  schemaUrl?: URL;\n};\n\nclass ContextStore {\n  contextsList: ContextItem[] = contexts;\n\n  currentContext: ContextType | null = null;\n\n  contextListeners: Fdc3Listener[] = [];\n\n  constructor() {\n    makeObservable(this, {\n      contextsList: observable,\n      currentContext: observable,\n      contextListeners: observable,\n      setContext: action,\n      deleteContextItem: action,\n      broadcast: action,\n      addContextItem: action,\n      saveContextItem: action,\n      addContextListener: action,\n      removeContextListener: action,\n    });\n    const localStorageContextList = localStorage.getItem('contextList');\n    let usingDefaultContexts = true;\n    try {\n      if (localStorageContextList) {\n        const parsedListFromStorage = JSON.parse(localStorageContextList);\n        if (Array.isArray(parsedListFromStorage)) {\n          this.contextsList = parsedListFromStorage;\n          usingDefaultContexts = false;\n        }\n      }\n    } catch (err) {\n      console.error('Failed to parse context list from localstorage', err);\n    }\n    if (usingDefaultContexts) {\n      this.updateLocalStorage(contexts);\n    }\n  }\n\n  addContextItem(contextItem: ContextItem) {\n    contextItem.uuid = uuidv4();\n    this.contextsList.push(contextItem);\n    this.contextsList.sort((a, b) => a.id.localeCompare(b.id));\n    this.updateLocalStorage(this.contextsList);\n  }\n\n  saveContextItem(contextItem: ContextItem, selectedId?: string) {\n    const context = this.contextsList.find(({ id }) => id === selectedId || id === contextItem.id);\n    if (context) {\n      (Object.keys(contextItem) as (keyof ContextItem)[]).forEach(key => {\n        (context as Record<string, unknown>)[key] = contextItem[key];\n      });\n    }\n    this.updateLocalStorage(this.contextsList);\n  }\n\n  setContext(context: ContextType) {\n    this.currentContext = context;\n  }\n\n  deleteContextItem(contextItem: ContextItem) {\n    this.contextsList = this.contextsList.filter(c => c != contextItem);\n    this.updateLocalStorage(this.contextsList);\n  }\n\n  resetContextList() {\n    this.contextsList = contexts;\n    this.updateLocalStorage(this.contextsList);\n  }\n\n  updateLocalStorage(data: object) {\n    localStorage.setItem('contextList', JSON.stringify(data));\n  }\n\n  async broadcast(context: ContextType) {\n    const agent = await getWorkbenchAgent();\n\n    if (!context) {\n      systemLogStore.addLog({\n        name: 'broadcast',\n        type: 'warning',\n        value: 'You must set a context before you can broadcast it',\n        variant: 'text',\n      });\n      return;\n    } else {\n      //check that we're on a channel\n      const currentChannel = await agent.getCurrentChannel();\n      if (!currentChannel) {\n        systemLogStore.addLog({\n          name: 'broadcast',\n          type: 'warning',\n          value: 'You are not currently joined to a channel (no-op)',\n          variant: 'text',\n        });\n      } else {\n        try {\n          await agent.broadcast(toJS(context));\n          systemLogStore.addLog({\n            name: 'broadcast',\n            type: 'success',\n            body: JSON.stringify(context, null, 4),\n            variant: 'code',\n          });\n        } catch (e) {\n          systemLogStore.addLog({\n            name: 'broadcast',\n            type: 'error',\n            body: JSON.stringify(e, null, 4),\n            variant: 'code',\n          });\n        }\n      }\n    }\n  }\n\n  async addContextListener(contextType: string | null | undefined) {\n    try {\n      if (typeof contextType === 'string') {\n        const listenerId = nanoid();\n\n        const agent = await getWorkbenchAgent();\n\n        //pre-populate listener in store to avoid races\n        this.contextListeners.push({ id: listenerId, type: contextType, listener: { unsubscribe: () => {} } });\n\n        const contextListener = await agent.addContextListener(\n          contextType.toLowerCase() === 'all' ? null : contextType,\n          (context: ContextType, metaData?: ContextMetadata) => {\n            const currentListener = this.contextListeners.find(({ id }) => id === listenerId);\n\n            runInAction(() => {\n              if (currentListener) {\n                currentListener.lastReceivedContext = context;\n                currentListener.metaData = metaData;\n              } else {\n                console.error('Did not find contextListener in store to update!');\n              }\n            });\n\n            systemLogStore.addLog({\n              name: 'receivedContextListener',\n              type: 'info',\n              value: contextType,\n              variant: 'code',\n              body: JSON.stringify(context, null, 4),\n            });\n          }\n        );\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'addContextListener',\n            type: 'success',\n            value: contextType,\n            variant: 'text',\n          });\n\n          //populate unsubscribe function with actual listener\n          const currentListener = this.contextListeners.find(({ id }) => id === listenerId);\n          if (currentListener) {\n            currentListener.listener = contextListener;\n          } else {\n            console.error(\n              'ContextStore could not find this listener due to a race, you will not be able to unsubscribe it correctly'\n            );\n          }\n        });\n      } else {\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'addContextListener',\n            type: 'error',\n            value: contextType ?? 'null',\n            variant: 'code',\n          });\n        });\n      }\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'addContextListener',\n        type: 'error',\n        value: contextType ?? 'null',\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async removeContextListener(id: string) {\n    const listenerIndex = this.contextListeners.findIndex(listener => listener.id === id);\n\n    if (listenerIndex !== -1) {\n      try {\n        (await this.contextListeners[listenerIndex].listener).unsubscribe();\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'removeContextListener',\n            type: 'success',\n            value: this.contextListeners[listenerIndex].type,\n            variant: 'text',\n          });\n          this.contextListeners.splice(listenerIndex, 1);\n        });\n      } catch (e) {\n        systemLogStore.addLog({\n          name: 'removeContextListener',\n          type: 'error',\n          value: this.contextListeners[listenerIndex].type,\n          variant: 'code',\n          body: JSON.stringify(e, null, 4),\n        });\n      }\n    }\n  }\n\n  isContextListenerExists(type: string | undefined) {\n    return !!this.contextListeners.find(listener => listener.type === type);\n  }\n}\n\nconst contextStore = new ContextStore();\n\nexport default contextStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/IntentStore.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action, runInAction, toJS } from 'mobx';\nimport {\n  ContextType,\n  IntentResolution,\n  Fdc3Listener,\n  AppMetadata,\n  PrivateChannel,\n  getWorkbenchAgent,\n} from '../utility/Fdc3Api.js';\nimport { nanoid } from 'nanoid';\nimport { intentTypes } from '../fixtures/intentTypes.js';\nimport systemLogStore from './SystemLogStore.js';\nimport appChannelStore from './AppChannelStore.js';\nimport privateChannelStore from './PrivateChannelStore.js';\nimport { Channel, IntentResult } from '@finos/fdc3';\nimport { ContextMetadata } from '@finos/fdc3-standard';\n\ntype IntentItem = { title: string; value: string };\n\nclass IntentStore {\n  intentsList: IntentItem[] = intentTypes;\n\n  intentListeners: Fdc3Listener[] = [];\n\n  constructor() {\n    makeObservable(this, {\n      intentsList: observable,\n      intentListeners: observable,\n      raiseIntent: action,\n      addIntentListener: action,\n      removeIntentListener: action,\n      raiseIntentForContext: action,\n    });\n  }\n\n  async addIntentListener(\n    intent: string,\n    resultContext?: ContextType | null,\n    channelName?: string | null,\n    isPrivate?: boolean,\n    channelContexts?: Record<string, ContextType>,\n    channelContextDelay?: Record<string, number>\n  ) {\n    try {\n      const listenerId = nanoid();\n\n      const agent = await getWorkbenchAgent();\n\n      const intentListener = await agent.addIntentListener(\n        intent,\n        async (context: ContextType, metaData?: ContextMetadata): Promise<IntentResult> => {\n          const currentListener = this.intentListeners.find(({ id }) => id === listenerId);\n          let channel: Channel | undefined;\n\n          //app channel\n          if (channelName && !isPrivate) {\n            channel = await appChannelStore.getOrCreateChannel(channelName);\n          }\n\n          //private channel\n          if (isPrivate && !channelName) {\n            channel = await privateChannelStore.createPrivateChannel();\n            privateChannelStore.addChannelListener(<PrivateChannel>channel, 'all');\n\n            privateChannelStore.onDisconnect(<PrivateChannel>channel);\n            privateChannelStore.onUnsubscribe(<PrivateChannel>channel);\n            privateChannelStore.onAddContextListener(<PrivateChannel>channel, channelContexts, channelContextDelay);\n          }\n\n          if (!isPrivate && channel) {\n            if (channelContexts && Object.keys(channelContexts).length !== 0) {\n              Object.keys(channelContexts).forEach(key => {\n                const broadcast = setTimeout(async () => {\n                  appChannelStore.broadcast(<Channel>channel, channelContexts[key]);\n                  clearTimeout(broadcast);\n                }, channelContextDelay?.[key] ?? 0);\n              });\n            } else {\n              await channel.broadcast(context);\n            }\n          }\n\n          runInAction(() => {\n            if (currentListener) {\n              currentListener.lastReceivedContext = context;\n              currentListener.metaData = metaData;\n            }\n          });\n\n          systemLogStore.addLog({\n            name: 'receivedIntentListener',\n            type: 'info',\n            value: intent,\n            variant: 'code',\n            body: JSON.stringify(context, null, 4),\n          });\n\n          const result: IntentResult = channel || (resultContext ?? undefined);\n\n          return result;\n        }\n      );\n\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'addIntentListener',\n          type: 'success',\n          value: intent,\n          variant: 'text',\n        });\n        this.intentListeners.push({ id: listenerId, type: intent, listener: intentListener });\n      });\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'addIntentListener',\n        type: 'error',\n        value: intent,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async removeIntentListener(id: string) {\n    const listenerIndex = this.intentListeners.findIndex(listener => listener.id === id);\n\n    if (listenerIndex !== -1) {\n      try {\n        (await this.intentListeners[listenerIndex].listener).unsubscribe();\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'removeIntentListener',\n            type: 'success',\n            value: this.intentListeners[listenerIndex].type,\n            variant: 'text',\n          });\n          this.intentListeners.splice(listenerIndex, 1);\n        });\n      } catch (e) {\n        systemLogStore.addLog({\n          name: 'removeIntentListener',\n          type: 'error',\n          value: this.intentListeners[listenerIndex].type,\n          variant: 'code',\n          body: JSON.stringify(e, null, 4),\n        });\n      }\n    }\n  }\n\n  async raiseIntent(intent: string, context: ContextType, app?: AppMetadata) {\n    const agent = await getWorkbenchAgent();\n\n    if (!context) {\n      systemLogStore.addLog({\n        name: 'raiseIntent',\n        type: 'error',\n        value: intent,\n      });\n      return;\n    }\n\n    try {\n      let resolution: IntentResolution;\n\n      if (app) {\n        resolution = await agent.raiseIntent(intent, toJS(context), app);\n      } else {\n        resolution = await agent.raiseIntent(intent, toJS(context));\n      }\n\n      systemLogStore.addLog({\n        name: 'raiseIntent',\n        type: 'success',\n        value: intent,\n        variant: 'code',\n        body: JSON.stringify(resolution, null, 4),\n      });\n\n      return resolution;\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'raiseIntent',\n        type: 'error',\n        value: intent,\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  async raiseIntentForContext(context: ContextType, app?: AppMetadata) {\n    const agent = await getWorkbenchAgent();\n\n    if (!context) {\n      systemLogStore.addLog({\n        name: 'raiseIntentForContext',\n        type: 'error',\n      });\n      return;\n    }\n\n    try {\n      let resolution: IntentResolution;\n\n      if (app) {\n        resolution = await agent.raiseIntentForContext(toJS(context), app);\n      } else {\n        resolution = await agent.raiseIntentForContext(toJS(context));\n      }\n      systemLogStore.addLog({\n        name: 'raiseIntentForContext',\n        type: 'success',\n      });\n\n      return resolution;\n    } catch (e) {\n      console.log(e);\n      systemLogStore.addLog({\n        name: 'raiseIntentForContext',\n        type: 'error',\n      });\n    }\n  }\n}\n\nconst intentStore = new IntentStore();\n\nexport default intentStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/PrivateChannelStore.tsx",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action, runInAction, toJS } from 'mobx';\nimport { ContextType, Fdc3Listener, PrivateChannel } from '../utility/Fdc3Api.js';\nimport systemLogStore from './SystemLogStore.js';\nimport { nanoid } from 'nanoid';\nimport { getWorkbenchAgent } from '../utility/Fdc3Api.js';\nimport { ContextMetadata } from '@finos/fdc3-standard';\n// interface ListenerOptionType {\n// \ttitle: string;\n// \tvalue: string;\n// \ttype: string | undefined;\n// }\n\nclass PrivateChannelStore {\n  privateChannelsList: PrivateChannel[] = [];\n\n  currentPrivateChannel: PrivateChannel | null = null;\n\n  channelListeners: Fdc3Listener[] = [];\n\n  constructor() {\n    makeObservable(this, {\n      privateChannelsList: observable,\n      currentPrivateChannel: observable,\n      channelListeners: observable,\n      createPrivateChannel: action,\n      broadcast: action,\n      onAddContextListener: action,\n      onDisconnect: action,\n      onUnsubscribe: action,\n      disconnect: action,\n    });\n  }\n\n  async createPrivateChannel() {\n    try {\n      const currentPrivateChannel: PrivateChannel = await getWorkbenchAgent().then(agent =>\n        agent.createPrivateChannel()\n      );\n      const isSuccess = currentPrivateChannel !== null;\n      if (isSuccess) {\n        this.privateChannelsList.push(currentPrivateChannel);\n      }\n\n      runInAction(() => {\n        systemLogStore.addLog({\n          name: 'createPrivateChannel',\n          type: isSuccess ? 'success' : 'error',\n          value: currentPrivateChannel.id,\n          variant: 'text',\n        });\n      });\n\n      return currentPrivateChannel;\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'createPrivateChannel',\n        type: 'error',\n        value: '',\n        variant: 'code',\n        body: JSON.stringify(e, null, 4),\n      });\n    }\n  }\n\n  isContextListenerExists(channelId: string, type: string | undefined) {\n    return !!this.channelListeners?.find(listener => listener.type === type && listener.channelId === channelId);\n  }\n\n  isPrivateChannelExists(channelId: string) {\n    return !!this.privateChannelsList.find(channel => channel.id === channelId);\n  }\n\n  async broadcast(channel: PrivateChannel, context: ContextType) {\n    const channelId = channel.id;\n    if (!context) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'warning',\n        value: `You must set a context before you can broadcast it to channel: ${channelId}`,\n        variant: 'text',\n      });\n    }\n\n    if (!channel) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'warning',\n        value: 'You are not currently joined to a channel (no-op)',\n        variant: 'text',\n      });\n      return;\n    }\n\n    try {\n      await channel.broadcast(toJS(context));\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'success',\n        body: JSON.stringify(context, null, 4),\n        variant: 'code',\n        value: channelId,\n      });\n    } catch (e) {\n      systemLogStore.addLog({\n        name: 'appBroadcast',\n        type: 'error',\n        body: JSON.stringify(e, null, 4),\n        variant: 'code',\n        value: channelId,\n      });\n    }\n  }\n\n  async addChannelListener(currentChannel: PrivateChannel, newListener: string | undefined) {\n    const channelId = currentChannel.id;\n    try {\n      const foundListener = this.channelListeners.find(\n        currentListener => currentListener.type === newListener && currentListener.channelId === channelId\n      );\n      if (!foundListener && currentChannel && newListener !== undefined) {\n        const listenerId = nanoid();\n        const contactListener = await currentChannel.addContextListener(\n          newListener?.toLowerCase() === 'all' ? null : newListener,\n          (context, metaData?: ContextMetadata) => {\n            const currentListener = this.channelListeners.find(\n              listener => listener.type === newListener && listener.channelId === channelId\n            );\n\n            runInAction(() => {\n              if (currentListener) {\n                currentListener.lastReceivedContext = context;\n                currentListener.metaData = metaData;\n              }\n            });\n\n            systemLogStore.addLog({\n              name: 'receivedAppContextListener',\n              type: 'info',\n              value: `Channel [${channelId}] Received context via '[${newListener}]' listener`,\n              variant: 'code',\n              body: JSON.stringify(context, null, 4),\n            });\n          }\n        );\n\n        runInAction(() => {\n          this.channelListeners.push({\n            id: listenerId,\n            type: newListener,\n            listener: contactListener,\n            channelId,\n          });\n        });\n      }\n    } catch {\n      /* empty */\n    }\n  }\n\n  removeContextListener(id: string) {\n    const listenerIndex = this.channelListeners?.findIndex(listener => listener.id === id);\n    const listener = this.channelListeners[listenerIndex];\n    if (listenerIndex !== -1) {\n      try {\n        this.channelListeners[listenerIndex].listener.unsubscribe();\n\n        runInAction(() => {\n          systemLogStore.addLog({\n            name: 'removeAppChannelContextListener',\n            type: 'success',\n            value: `A context listener for '[${listener.type}]' for channel [${listener.channelId}] has been removed`,\n            variant: 'text',\n          });\n          this.channelListeners.splice(listenerIndex, 1);\n        });\n      } catch (e) {\n        systemLogStore.addLog({\n          name: 'removeAppChannelContextListener',\n          type: 'error',\n          value: `Failed to remove a context listener for '[${listener.type}]' on channel [${listener.channelId}]`,\n          variant: 'code',\n          body: JSON.stringify(e, null, 4),\n        });\n      }\n    }\n  }\n\n  onAddContextListener(\n    channel: PrivateChannel,\n    channelContexts?: Record<string, ContextType>,\n    channelContextDelay?: Record<string, number>\n  ) {\n    channel.onAddContextListener(() => {\n      try {\n        systemLogStore.addLog({\n          name: 'pcAddContextListener',\n          type: 'success',\n          value: `A context listener for '[all]' has been added on channel [${channel.id}]`,\n        });\n\n        if (channelContexts && Object.keys(channelContexts).length !== 0) {\n          Object.keys(channelContexts).forEach(key => {\n            const broadcast = setTimeout(async () => {\n              this.broadcast(channel, channelContexts[key]);\n              clearTimeout(broadcast);\n            }, channelContextDelay?.[key] ?? 0);\n          });\n        }\n      } catch {\n        systemLogStore.addLog({\n          name: 'pcAddContextListener',\n          type: 'error',\n          value: `Failed to add a context listener for '[all]' on channel [${channel.id}]`,\n        });\n      }\n    });\n  }\n\n  onUnsubscribe(channel: PrivateChannel) {\n    channel.onUnsubscribe(() => {\n      try {\n        systemLogStore.addLog({\n          name: 'pcOnUnsubscribe',\n          type: 'success',\n          value: `Sucessfully unsubscribed from listener '[all]' for channel [${channel.id}]`,\n        });\n      } catch {\n        systemLogStore.addLog({\n          name: 'pcOnUnsubscribe',\n          type: 'error',\n          value: `Could not unsubscribed listener '[all]' from channel [${channel.id}]`,\n        });\n      }\n    });\n  }\n\n  onDisconnect(channel: PrivateChannel) {\n    channel.onDisconnect(() => {\n      try {\n        this.channelListeners.forEach(listener => {\n          this.removeContextListener(listener.id);\n        });\n        this.privateChannelsList = this.privateChannelsList.filter(chan => chan.id !== channel.id);\n        systemLogStore.addLog({\n          name: 'pcOnDisconnect',\n          type: 'success',\n          value: `Sucessfully disconntected from channel [${channel.id}]`,\n        });\n      } catch {\n        systemLogStore.addLog({\n          name: 'pcOnDisconnect',\n          type: 'error',\n          value: `Unable to disconnect from channel [${channel.id}]`,\n        });\n      }\n    });\n  }\n\n  disconnect(channel: PrivateChannel) {\n    this.channelListeners.forEach(listener => {\n      this.removeContextListener(listener.id);\n    });\n    this.privateChannelsList = this.privateChannelsList.filter(chan => chan.id !== channel.id);\n    channel.disconnect();\n  }\n}\n\nconst privateChannelStore = new PrivateChannelStore();\n\nexport default privateChannelStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/SnackbarStore.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action } from 'mobx';\nimport { AlertColor } from '@mui/material/Alert';\nimport { nanoid } from 'nanoid';\n\ninterface SnackbarData {\n  message: string;\n  type: AlertColor;\n}\n\ninterface SnackbarItem extends SnackbarData {\n  id: string;\n}\n\nclass SnackbarStore {\n  snackbarData: SnackbarItem | null = null;\n\n  constructor() {\n    makeObservable(this, {\n      snackbarData: observable,\n      setSnackbar: action,\n      clearSnackbarData: action,\n    });\n  }\n\n  setSnackbar(data: SnackbarData) {\n    this.snackbarData = { ...data, id: nanoid() };\n  }\n\n  clearSnackbarData() {\n    this.snackbarData = null;\n  }\n}\n\nconst snackbarStore = new SnackbarStore();\n\nexport default snackbarStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/store/SystemLogStore.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport { makeObservable, observable, action } from 'mobx';\nimport { nanoid } from 'nanoid';\nimport { getLogMessage } from '../fixtures/logMessages.js';\nimport snackbarStore from './SnackbarStore.js';\n\nexport type logMessagesName =\n  | 'getFdc3'\n  | 'getChannels'\n  | 'getCurrentChannel'\n  | 'joinUserChannel'\n  | 'leaveChannel'\n  | 'broadcast'\n  | 'appBroadcast'\n  | 'raiseIntent'\n  | 'raiseIntentForContext'\n  | 'addContextListener'\n  | 'removeContextListener'\n  | 'addIntentListener'\n  | 'removeIntentListener'\n  | 'receivedContextListener'\n  | 'receivedIntentListener'\n  | 'deleteExample'\n  | 'saveExample'\n  | 'copyToClipboard'\n  | 'getOrCreateChannel'\n  | 'createPrivateChannel'\n  | 'receivedAppContextListener'\n  | 'addAppContextListener'\n  | 'removeAppChannelContextListener'\n  | 'pcAddContextListener'\n  | 'pcOnUnsubscribe'\n  | 'pcOnDisconnect';\n\nexport type logMessagesType = 'error' | 'success' | 'warning' | 'info';\n\nexport interface LogItem {\n  id: string;\n  name: logMessagesName;\n  type: logMessagesType;\n  message: string;\n  body?: string;\n  variant?: 'code' | 'text';\n}\n\ninterface LogItemCreator extends Omit<LogItem, 'message' | 'id'> {\n  value?: string;\n}\n\nclass SystemLogStore {\n  logList: LogItem[] = [];\n\n  constructor() {\n    makeObservable(this, {\n      logList: observable,\n      addLog: action,\n    });\n  }\n\n  addLog({ name, type, value, body, variant }: LogItemCreator) {\n    const message = getLogMessage(name, type, value);\n    snackbarStore.setSnackbar({\n      message: message,\n      type: type,\n    });\n\n    this.logList.push({ id: nanoid(), name, type, message, body, variant: variant ?? 'text' });\n  }\n}\n\nconst systemLogStore = new SystemLogStore();\n\nexport default systemLogStore;\n"
  },
  {
    "path": "toolbox/fdc3-workbench/src/utility/Fdc3Api.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport * as fdc3_2 from '@finos/fdc3';\nimport * as fdc3_1 from 'fdc3-1.2';\n\ninterface fdc3_1IntentResolution extends fdc3_1.IntentResolution {\n  getResult?: () => Promise<fdc3_2.IntentResult>;\n  resultContext?: fdc3_2.Context;\n}\ninterface fdc3_2IntentResolution extends fdc3_2.IntentResolution {\n  resultContext?: fdc3_2.Context;\n}\n\ninterface fdc3_1ImplementationMetadata extends fdc3_1.ImplementationMetadata {\n  appMetadata?: fdc3_2.AppMetadata;\n}\n\ninterface fdc3_2ImplementationMetadata extends fdc3_2.ImplementationMetadata {\n  appMetadata: fdc3_2.AppMetadata;\n}\n\nexport type ContextType = {\n  type: string;\n  id?: {\n    [key: string]: string;\n  };\n  name?: string;\n  [x: string]: unknown;\n};\n\nexport interface Fdc3Listener {\n  id: string;\n  channelId?: string;\n  type: string | undefined;\n  listener: fdc3_1.Listener | fdc3_2.Listener;\n  lastReceivedContext?: ContextType | null;\n  metaData?: fdc3_2.ContextMetadata;\n}\n\nexport type IntentResolution = fdc3_1IntentResolution | fdc3_2IntentResolution;\n\nexport type TargetApp = fdc3_1.TargetApp;\n\nexport type ImplementationMetadata = fdc3_1ImplementationMetadata | fdc3_2ImplementationMetadata;\n\nexport type AppMetadata = fdc3_2.AppMetadata;\n//  & {\n// \tinstanceId?: string;\n// };\n\nexport type AppIntent = fdc3_1.AppIntent | fdc3_2.AppIntent;\n\nexport type Context = fdc3_1.Context | fdc3_2.Context;\n\n// export type AppIdentifier = fdc3_1.AppMetadata | fdc3_2.AppIdentifier;\n\nexport type PrivateChannel = fdc3_2.PrivateChannel;\n\nexport type IntentTargetOption = {\n  appId: string;\n  metadata: AppMetadata;\n  instances: fdc3_2.AppMetadata[];\n  launchNew: boolean;\n};\n\nexport type ContextTargetOption = { intent: string; targetOptions: IntentTargetOption[] };\n\nexport function getWorkbenchAgent(): Promise<fdc3_2.DesktopAgent> {\n  return fdc3_2.getAgent({\n    dontSetWindowFdc3: false,\n  });\n}\n\nexport async function getTargetOptions(intent: string, context: ContextType): Promise<IntentTargetOption[]> {\n  const agent = await getWorkbenchAgent();\n\n  const appIntent = await agent.findIntent(intent, context);\n  if (!appIntent?.apps) {\n    return [];\n  }\n\n  const groupedApps: IntentTargetOption[] = [];\n\n  if (window.fdc3Version === '2.0') {\n    (appIntent as fdc3_2.AppIntent).apps.forEach(currentApp => {\n      const foundApp = groupedApps.find(app => app.appId === currentApp.appId);\n      if (!foundApp) {\n        //separate out the instanceId if present\n        // eslint-disable-next-line @typescript-eslint/no-unused-vars\n        const { instanceId: _, ...metadata } = currentApp;\n        const option: IntentTargetOption = {\n          appId: currentApp.appId,\n          metadata: metadata,\n          instances: [],\n          launchNew: false,\n        };\n        if (currentApp.instanceId) {\n          option.instances.push(currentApp);\n        } else {\n          option.launchNew = true;\n        }\n        groupedApps.push(option);\n      } else {\n        if (currentApp.instanceId) {\n          foundApp.instances.push(currentApp);\n        } else {\n          foundApp.launchNew = true;\n        }\n      }\n    });\n  } else {\n    //no instances in FDC3 < 2\n    (appIntent as fdc3_1.AppIntent).apps.forEach(currentApp => {\n      //deduplicate results in case a 2.0 implementation returned instances\n      const foundApp = groupedApps.find(app => app.appId === currentApp.appId);\n      if (!foundApp) {\n        groupedApps.push({\n          appId: currentApp.appId ?? currentApp.name,\n          metadata: currentApp as fdc3_2.AppMetadata, //hack to avoid type error\n          instances: [],\n          launchNew: true,\n        });\n      }\n    });\n  }\n\n  return groupedApps;\n}\n\nexport async function getTargetOptionsForContext(context: ContextType): Promise<IntentTargetOption[]> {\n  const agent = await getWorkbenchAgent();\n\n  const appIntents = await agent.findIntentsByContext(context);\n  if (appIntents.length === 0) {\n    return [];\n  }\n\n  //We only return apps to target which means we need to deduplicate where they are returned more than once\n  const groupedApps: IntentTargetOption[] = [];\n\n  if (window.fdc3Version === '2.0') {\n    (appIntents as fdc3_2.AppIntent[]).forEach(currentIntent => {\n      currentIntent.apps.forEach(currentApp => {\n        const foundApp = groupedApps.find(app => app.appId === currentApp.appId);\n        if (!foundApp) {\n          //separate out the instanceId if present\n          // eslint-disable-next-line @typescript-eslint/no-unused-vars\n          const { instanceId: _, ...metadata } = currentApp;\n          const option: IntentTargetOption = {\n            appId: currentApp.appId,\n            metadata: metadata,\n            instances: [],\n            launchNew: false,\n          };\n          if (currentApp.instanceId) {\n            option.instances.push(currentApp);\n          } else {\n            option.launchNew = true;\n          }\n          groupedApps.push(option);\n        } else {\n          if (currentApp.instanceId) {\n            //deduplicate instances\n            const foundInstance = foundApp.instances.find(instance => instance.instanceId === currentApp.instanceId);\n            if (!foundInstance) {\n              foundApp.instances.push(currentApp);\n            }\n          } else {\n            foundApp.launchNew = true;\n          }\n        }\n      });\n    });\n  } else {\n    (appIntents as fdc3_1.AppIntent[]).forEach(currentIntent => {\n      currentIntent.apps.forEach(currentApp => {\n        //deduplicate in case a 2.0 implementation returned some instances\n        const foundApp = groupedApps.find(app => app.appId === currentApp.appId);\n        if (!foundApp) {\n          groupedApps.push({\n            appId: currentApp.appId ?? currentApp.name,\n            metadata: currentApp as fdc3_2.AppMetadata, //hack to avoid type error\n            instances: [],\n            launchNew: true,\n          });\n        }\n      });\n    });\n  }\n\n  return groupedApps;\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"esnext\",\n\t\t\"useDefineForClassFields\": true,\n\t\t\"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n\t\t\"allowJs\": false,\n\t\t\"skipLibCheck\": true,\n\t\t\"esModuleInterop\": false,\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"strict\": true,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"noFallthroughCasesInSwitch\": true,\n\t\t\"module\": \"esnext\",\n\t\t\"moduleResolution\": \"node\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"isolatedModules\": true,\n\t\t\"noEmit\": true,\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"types\": [\"node\", \"vite/client\"]\n\t},\n\t\"include\": [\"src\"],\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"./tsconfig.node.json\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../../packages/fdc3\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/tsconfig.node.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"composite\": true,\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"Node\",\n\t\t\"allowSyntheticDefaultImports\": true\n\t},\n\t\"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "toolbox/fdc3-workbench/vite.config.ts",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\nimport legacy from '@vitejs/plugin-legacy';\nimport react from '@vitejs/plugin-react';\nimport { defineConfig } from 'vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  base: '/toolbox/fdc3-workbench/',\n  build: {\n    outDir: 'build',\n  },\n  define: {\n    'process.env.NODE_DEBUG': 'false',\n    'process.env': 'import.meta.env',\n    'global.process': 'globalThis.process',\n  },\n  resolve: {\n    alias: {\n      buffer: 'buffer',\n      path: 'path-browserify',\n    },\n  },\n  plugins: [\n    react(),\n    legacy({\n      targets: ['defaults', 'not IE 11'],\n    }),\n  ],\n  server: { port: 4001 },\n});\n"
  },
  {
    "path": "tsconfig.root.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Basic Options */\n    \"esModuleInterop\": true,\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"allowSyntheticDefaultImports\": true,\n    \"resolveJsonModule\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"sourceMap\": false,\n    /* output setting */\n    \"lib\": [\n      \"es2021\",\n      \"DOM\"\n    ],\n    \"target\": \"ESNext\",\n    \"composite\": true,\n    /* Linting */\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"strict\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noImplicitAny\": true,\n    \"noImplicitThis\": true,\n    \"noImplicitReturns\": true,\n    /* From Coverage Work */\n    \"skipLibCheck\": true,\n    /* From Distribution Work */\n    \"declarationMap\": false\n  }\n}"
  },
  {
    "path": "website/.nvmrc",
    "content": "20.*\n"
  },
  {
    "path": "website/README.md",
    "content": "# FDC3 website readme\n\nThe FDC3 website is not an integrated part of the FDC3 mono-repo (i.e. its not in `workspaces` element of the main repo's package.json) as it is built separately by netlify. Hence, to build and run the website locally run:\n\n```bash\ncd website\nnpm install\nnpm run build\n```\n\nPlease note that this will *also* build the mono-repo projects via the `prebuild` and `parent-build` scripts as the modules are needed to build UIs (fdc3-workbench and fdc3-reference-ui) hosted within the site.\n\n## Releasing new versions of the Standard\n\nTo create a new version of the website, a number of NPM scripts need to be run that will create the version and update certain content within it (as automatically as possible). There are then a number of additional manual steps to run.\n\n1. Enter the website directory and make sure the site has been built:\n\n    ```bash\n    cd website\n    npm install\n    npm run build\n    ```\n\n2. Then run the versioning script - this should work cross-platform, but can be brittle...\n    - edit *website/package.json* and replace the version number in the `version` script to the version number you wish to create:\n        `version\": \"cross-env-shell VERSION=2.1 ...`\n    - Run it:\n\n        ```bash\n        npm run version\n        ```\n\n    - Check the reported version number is as expected and that the scripts ran without errors.\n\n3. Check that the version script has done what it needs to:\n    - The new website version should exist in *website/versioned_docs*\n        - Links to schema files should have been updated to the versioned links, e.g. check *website/versioned_docs/version-2.1/context/ref/Context.md* has a link like <https://fdc3.finos.org/schemas/2.1/context/context.schema.json> (where '2.1' would be 'next' in the pre-draft)\n        - The overview docs (often called spec.md) should have had '(next)' in their titles replaced with the version, e.g. '(2.1)', e.g. check *website/versioned_docs/version-2.1/api/spec.md*\n    - A new set of schemas should exist in *website/static/schemas*\n        - Check all schema files/folders got copied, including *api/*, *context/*, *bridging/*, *bridgingAsyncAPI/* and the *appd* files.\n        - Check that their `$id` fields were updated to match their new URLs, e.g. *website/static/schemas/2.1/context/context.schema.json* should have an `$id` that looks like: `\"$id\": \"https://fdc3.finos.org/schemas/2.1/context/context.schema.json\"` (where '2.1' would be 'next' in the pre-draft)\n        - Check that the appD schema's `version` field has been updated, i.e. *website/static/schemas/2.1/appd.schema.json* should have `\"version\": \"2.1\",` (where '2.1' would be 'next' in the pre-draft)\n\n4. Make a number of additional manual changes:\n    - Edit the titles of *website/versioned_docs/version-VERSION/fdc3-intro.md* and *website/versioned_docs/version-VERSION/fdc3-standard.md* to remove '(pre-draft')\n    - Edit the titles of *docs/fdc3-intro.md* and *docs/fdc3-standard.md* to use the next planned version number\n    - Edit the last Standard version's abstract to update its status and dates, e.g. *website/versioned_docs/version-2.0/fdc3-standard.md*\n    - Edit the new Standard version's abstract to update its status and dates, e.g. *website/versioned_docs/version-2.1/fdc3-standard.md*\n\n5. Edit CHANGELOG.md to mark the unreleased changes as the new version and create a new unreleased section for the next version.\n    - Note that the title of the release section usually includes a compare link for the previous version. These are based on tags - the tag needed will not exist yet, but is created in a later step. It should be fine to set it to what the tag name will be.\n\n6. If creating a new NPM module version at the same time, then\n    - See instructions in the the README.md at the root of the repo\n\n7. Test your changes locally by running the site:\n\n    ```bash\n    cd website\n    npm run build\n    npm run start\n    ```\n\n    Check the output of build for broken links in markdown files and correct them. Please note that links to files in the /website/static dir should be prefixed with \"pathname://\" to exempt them from SPA routing (they will be treated like external links and opened in a new window)\n\n8. Create a PR and send out details for other maintainers to review and test.\n\n9. Merge the PR - website and NPM module will be deployed automatically.\n\n10. Goto <https://github.com/finos/FDC3/releases> and create a new release and tag for the new version.\n    - Copy the change log into the release description.\n"
  },
  {
    "path": "website/core/Showcase.js",
    "content": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst React = require('react');\nconst PropTypes = require('prop-types');\n\nconst UserLink = ({infoLink, image, caption}) => (\n    <a href={infoLink} key={infoLink}>\n        <img src={image} alt={caption} title={caption} />\n    </a>\n);\n\nUserLink.propTypes = {\n  infoLink: PropTypes.string.isRequired,\n  image: PropTypes.string.isRequired,\n  caption: PropTypes.string.isRequired,\n};\n\nconst Showcase = ({users}) => (\n  <div className=\"showcase\">\n    {users.map(user => (\n      <UserLink key={user.infoLink} {...user} />\n    ))}\n  </div>\n);\n\nShowcase.propTypes = {\n  users: PropTypes.array.isRequired,\n};\n\nexport default Showcase"
  },
  {
    "path": "website/data/community.json",
    "content": "[\n  {\n    \"//content guidelines\": \"Please provide details for your community entry as an object below, according to the following content guidelines. The FDC3 maintainers reserve the right to reject any entry that does not meet these content guidelines.\",\n    \"//title\": \"The title for your entry, up to 65 characters\",\n    \"//publisher\": \"The name of your organisation, up to 100 characters\",\n    \"//image\": \"Please provide a PNG or SVG image for your entry, these may be added to the website/static/img/users folder in the FDC3 repo\",\n    \"//infolink\": \"(optional) provide a URL to get more info about your entry\",\n    \"//docslink\": \"(optional) provide a URL to the documentation for your app or platform\",\n    \"//type\": \"Select a type for your entry from the following: platform-provider, application-provider, solution-provider, adopter, tools-and-training, demos, other\",\n    \"//badges\": \"Set one or more badges for your entry as objects with a 'text' property with one of the following values:\",\n    \"//badges1\": \"Open Source: Indicates that the project source code is available to download and modify, under an Apache 2.0 or similar license.\",\n    \"//badges2\": \"FDC3 1.2 Supported: Indicates that this product advertises compatibility with the FDC3 1.2 Standard.\",\n    \"//badges3\": \"FDC3 2.0 Supported: Indicates that this product advertises compatibility with the FDC3 2.0 Standard.\",\n    \"//badges4\": \"FDC3 1.2 Compliant: This badge is applied to desktop agents that have passed the FINOS FDC3 1.2 Conformance testing process.\",\n    \"//badges5\": \"FDC3 2.0 Compliant: This badge is applied to desktop agents that have passed the FINOS FDC3 2.0 Conformance testing process.\",\n    \"//conformance\": \"Indicate that a desktop agent has passed a FINOS FDC3 Conformance testing process - see other entries for examples of how to set this.\",\n    \"//description\": \"A description to be displayed by your entry. Please limit to 100 words and avoid the use of superlatives (e.g. easiest, best, most powerful etc.) or other descriptive content that may be disputed by other community members.\"\n  },\n  {\n    \"title\": \"Introduction to FDC3 (LFEL1000)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/LFEL1000.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"<p>This <strong>FREE</strong> entry-level course is designed for business technologists who are looking to adopt application interoperability within their technology landscape and for developers who want to build interoperable applications using the FDC3 Standard.</p>\"\n  },\n  {\n    \"title\": \"Developing Solutions with FDC3 (LFD237)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/LFD237.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/training/developing-solutions-with-fdc3-lfd237/\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"<p>This course is designed for developers who are looking to build interoperable applications using the FDC3 standard, as well as community participants who provide FDC3 technology and services.</p><p>LFD237 is priced at $299 but free seats are available to FINOS members.</p>\"\n  },\n  {\n    \"title\": \"FDC3 Certified Practitioner (FCFP)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/FCFP.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/certification/finos-certified-fdc3-practitioner/\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"<p>The FCFP is a professional certification designed for technical business analysts, software developers and FDC3 implementers in the finance, insurance, banking, and investment industries.</p><p>FCFP is priced at $250 but free seats are available to FINOS members.</p>\"\n  },\n  {\n    \"title\": \"ChartIQ\",\n    \"publisher\": \"S&P Global\",\n    \"image\": \"/img/users/ChartIQ.png\",\n    \"infoLink\": \"https://chartiq.com/\",\n    \"docsLink\": \"https://documentation.chartiq.com/\",\n    \"type\": \"application-provider\",\n    \"badges\": [\n      {\n        \"text\": \"FDC3 1.2 Supported\"\n      }\n    ],\n    \"description\": \"<p>ChartIQ is a powerful and flexible HTML5 charting library with millions of users worldwide. Written in JavaScript, it runs entirely within the browser. With state of the art integrations, including  third-party apps, educational components, analysis, and more, you can create efficient workflows and streamline the way to work.</p><p>ChartIQ works on any platform (mobile, web, desktop) and any framework (Angular, React).</p><p>Most companies have at least one financial charting library for each platform or app they target—web, C#, Java, Android, iOS, etc., so developers have multiple code bases to maintain. With ChartIQ, write your code once and use it everywhere.</p>\"\n  },\n  {\n    \"title\": \"FDC3 Sail\",\n    \"publisher\": \"FINOS\",\n    \"image\": \"/img/community/FDC3_Sail_Horizontal_Light.svg\",\n    \"infoLink\": \"https://github.com/finos/FDC3-Sail\",\n    \"docsLink\": \"https://github.com/finos/FDC3-Sail\",\n    \"type\": \"platform-provider\",\n    \"badges\": [\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-1.2.png\",\n        \"items\": [\n          {\n            \"text\": \"FDC3 Sail 1.0 Certified Conformant With FDC3 1.2 Specification on 6th December 2022\",\n            \"link\": \"https://www.finos.org/blog/first-fdc3-1.2-certified-desktop-agents\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"<p>This project provides a fully open source implementation of the FDC3 interoperability standard. </p><p>Includes a fully featured and secure electron desktop agent featuring intent resolution, channel linking, directory search and a local file-based app directory implementation. </p>\"\n  },\n  {\n    \"title\": \"Finsemble\",\n    \"publisher\": \"interop.io\",\n    \"image\": \"/img/users/interop.io-primary-1.svg\",\n    \"infoLink\": \"https://interop.io/\",\n    \"docsLink\": \"https://documentation.finsemble.com/\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-1.2.png\",\n        \"items\": [\n          {\n            \"text\": \"Finsemble v8.3.0-beta.3 Certified Conformant With FDC3 1.2 Specification on 2nd December 2022\",\n            \"link\": \"https://www.finos.org/blog/first-fdc3-1.2-certified-desktop-agents\"\n          }\n        ]\n      },\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"Finsemble Version 8.9.0-beta.2 Certified Conformant With FDC3 2.0 Specification on 9th June 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-2.0-conformance-a-merger\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"<p>interop.io was formed in June 2023 through the merger of Finsemble and Glue42 to create the global powerhouse driving application interoperability in capital markets and beyond. Leveraging FDC3 and workflow automation, interop.io allows clients to create Straight Through Workflows™ and benefit from unparalleled levels of business agility, a more productive workforce and better operational control.</p><p>The firm employs over 170 people including 110 full time R&D and implementation engineers located in New York, Charlottesville, London, and Sofia. For more information, visit <a href='https://interop.io' alt='interop.io website'>interop.io</a>.</p>\"\n  },\n  {\n    \"title\": \"FDC3 Workbench\",\n    \"publisher\": \"FDC3 / FINOS\",\n    \"image\": \"/toolbox/fdc3-workbench/fdc3-icon-256.png\",\n    \"infoLink\": \"http://fdc3.finos.org/toolbox/fdc3-workbench\",\n    \"docsLink\": \"https://github.com/finos/FDC3/blob/main/toolbox/fdc3-workbench/README.md\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"description\": \"<p>When developing an FDC3-compliant app or desktop agent, you need to test. Because FDC3 is about communicating, you need at least one other app to communicate with. You could grab an existing app, but there may not be one available that uses the messaging you need to test.</p><p>Many developers end up writing their own helper tool, which they often discard when the work on their app is done. We've seen so many devs create these throwaway apps that the Finsemble team decided to build and contribute a workbench (for any FDC3-compliant platform provider) that helps develop and test your app without writing throwaway code.</p>\"\n  },\n  {\n    \"title\": \"FDC3 Conformance Framework\",\n    \"publisher\": \"FDC3 / FINOS / ScottLogic\",\n    \"image\": \"/img/community/conformance.svg\",\n    \"infoLink\": \"https://github.com/finos/FDC3-conformance-framework\",\n    \"docsLink\": \"https://github.com/finos/FDC3/blob/main/toolbox/fdc3-conformance/README.md\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"description\": \"<p>As part of FINOS' commitment to the FDC3 standard, ScottLogic have been engaged to produce a conformance testing framework for desktop agent API compatibility.  Delivered as a set of FDC3 Applications, this Conformance pack will test 1.2 and 2.0 compatibility by exercising a desktop agent's implementation of the FDC3 API.</p>\"\n  },\n  {\n    \"title\": \"FDC3 eXplained\",\n    \"publisher\": \"FDC3 / FINOS\",\n    \"image\": \"/toolbox/fdc3-explained/logo.png\",\n    \"infoLink\": \"https://fdc3.finos.org/toolbox/fdc3-explained\",\n    \"docsLink\": \"https://github.com/finos/FDC3/blob/main/toolbox/fdc3-explained/README.md\",\n    \"type\": \"demos\",\n    \"badges\": [\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"description\": \"FDC3 eXplained is a no-frills tool for learning more about FDC3 concepts without requiring any engineering or coding knowledge. Click the buttons and see the API response, type in context and broadcast it. No dependencies, libraries or frameworks - just a single html page per version that you can load in any environment. Similar to FDC3 Workbench it provides a reference implementation for you to test and verify the FDC3 functionality of other applications and desktop agents.\"\n  },\n  {\n    \"title\": \"Glue42\",\n    \"publisher\": \"interop.io\",\n    \"image\": \"/img/users/interop.io-primary-1.svg\",\n    \"infoLink\": \"https://interop.io/\",\n    \"docsLink\": \"https://docs.glue42.com/\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-1.2.png\",\n        \"items\": [\n          {\n            \"text\": \"Glue42 Enterprise v3.17.0 / Glue FDC3 v2.6.0 Certified Conformant With FDC3 1.2 Specification on 2nd December 2022\",\n            \"link\": \"https://www.finos.org/blog/first-fdc3-1.2-certified-desktop-agents\"\n          },\n          {\n            \"text\": \"Glue42 Core+ v1.0 Browser Extension v1.4 / Glue FDC3 v2.6.0 Certified Conformant With FDC3 1.2 Specification on 6th December 2022\",\n            \"link\": \"https://www.finos.org/blog/first-fdc3-1.2-certified-desktop-agents\"\n          },\n          {\n            \"text\": \"Glue42 Core v2.6.1 Certified Conformant With FDC3 1.2 Specification on 13th March 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-1.2-agent-conformance-language-bindings\"\n          }\n        ]\n      },\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"Glue42 Enterprise v3.20.0.19 / Glue FDC3 v3.2.2 Certified Conformant With FDC3 2.0 Specification on 9th June 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-2.0-conformance-a-merger\"\n          },\n          {\n            \"text\": \"Glue42 Core+ v1.5.5 / Glue FDC3 v3.2.2 Certified Conformant With FDC3 2.0 Specification on 9th June 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-2.0-conformance-a-merger\"\n          },\n          {\n            \"text\": \"Glue42 Core (@glue42/web-platform - v1.26.1, @glue42/web - v2.21.0, @glue42/fdc3 - v3.2.2) Certified Conformant With FDC3 2.0 Specification on 9th June 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-2.0-conformance-a-merger\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"<p>interop.io was formed in June 2023 through the merger of Finsemble and Glue42 to create the global powerhouse driving application interoperability in capital markets and beyond. Leveraging FDC3 and workflow automation, interop.io allows clients to create Straight Through Workflows™ and benefit from unparalleled levels of business agility, a more productive workforce and better operational control.</p><p>The firm employs over 170 people including 110 full time R&D and implementation engineers located in New York, Charlottesville, London, and Sofia. For more information, visit <a href='https://interop.io' alt='interop.io website'>interop.io</a>.</p>\"\n  },\n  {\n    \"title\": \"Here\",\n    \"publisher\": \"Here Enterprise Inc.\",\n    \"image\": \"/img/users/OpenFin_Here_Browser_250x120.png\",\n    \"infoLink\": \"https://here.io/\",\n    \"docsLink\": \"https://developers.openfin.co/of-docs\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"description\": \"<p>Here&#8482; (formerly OpenFin) founded the FDC3 standard in 2017 in collaboration with major banks and asset managers. Deployed at more than 2400 financial firms, OpenFin OS, allows applications from multiple providers to co-exist and interoperate on the desktop.</p><p>OpenFin OS consists of a secure, Chromium-based runtime called Container and a visual interface called <a href='https://www.openfin.co/workspace/' alt='OpenFin Workspace'>Workspace</a>. Workspace gets you running in no time, with themeable UI components for complex windowing, advanced search, actionable notifications and application discovery.</p><p>You can also build your own solutions using the <a href='https://www.openfin.co/container/' alt='OpenFin Container'>OpenFin Container</a>, native language <a href='https://www.openfin.co/container/adapters/' alt='OpenFin Native Adapters'>adapters</a> and APIs while remaining compatible with everything else built on OpenFin.</p>\",\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-1.2.png\",\n        \"items\": [\n          {\n            \"text\": \"OpenFin - 31.111.74.3 Certified Conformant With FDC3 1.2 Specification on 22nd February 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-march-2023\"\n          }\n        ]\n      },\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"OpenFin - 32.114.76.14  Certified Conformant With FDC3 2.0 Specification on 19th October 2023\",\n            \"link\": \"https://www.finos.org/press/finos-announces-fdc3-2.1\"\n          }, \n          {\n            \"text\": \"HERE Enterprise Browser 9.0.1  Certified Conformant With FDC3 2.0 Specification on 5th December 2025\",\n            \"link\": \"https://www.finos.org/blog/conformance-news-here-enterprise-browser-9.0.1-passes-fdc3-2.0-conformance\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"title\": \"FDC3 Fast and Easy: Introducing the FDC3 Workbench for Vendors\",\n    \"publisher\": \"The Linux Foundation\",\n    \"image\": \"/img/community/lf.png\",\n    \"infoLink\": \"https://www.youtube.com/watch?v=JSEAC_1rku8\",\n    \"description\": \"Kris West (Finsemble) introduces FDC3 and the FDC3 Workbench at the October 2021 Open Source Strategy Forum in London. \",\n    \"badges\": [\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"type\": \"other\"\n  },\n  {\n    \"title\": \"Building an FDC3-enabled Web Application\",\n    \"publisher\": \"The Linux Foundation\",\n    \"image\": \"/img/community/lf.png\",\n    \"infoLink\": \"https://www.youtube.com/watch?v=BJvbVeL7ZJA\",\n    \"description\": \"Riko Eksteen (Adaptive Financial Consulting) explains why and how to build an FDC3-enabled application at the December 2020 Open-Source Strategy Forum\",\n    \"badges\": [],\n    \"type\": \"demos\"\n  },\n  {\n    \"title\": \"Symphony Demo - FDC3\",\n    \"publisher\": \"Symphony\",\n    \"image\": \"/img/users/Symphony.png\",\n    \"infoLink\": \"https://www.youtube.com/watch?v=wMF1h7RaAJY\",\n    \"description\": \"This demo showcases Symphony’s interoperability, flexibility and open architecture via FDC3 protocol. Leveraging FDC3, data and information can be seamlessly shared across multiple platforms on the same desktop. In this demo we showcase FX liquidity pricing via Tradefeedr, and data and trading analytics via S&P Global’s ChartIQ and Finsemble.\",\n    \"badges\": [],\n    \"type\": \"demos\"\n  },\n  {\n    \"title\": \"FDC3: A Review of Industry Activity - Matt Barrett & Sachin Gaba\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/community/lf.png\",\n    \"infoLink\": \"https://www.youtube.com/watch?v=w1d0d1nM8iI\",\n    \"description\": \"9 Oct 2021  FDC3: A Review of Industry Activity - Matt Barrett, Adaptive Financial Consulting & Sachin Gaba, State Street.  “Since we last gathered in person, FDC3 usage has seen incredible growth. This talk will provide an overview of FDC3 usage across the industry, highlighting both internal and external usage. We will cover high-impact FDC3 usage and identify some key themes and trends. I’ll share some predictions about the next year of FDC3 growth, and identify missed opportunities.\",\n    \"badges\": [],\n    \"type\": \"other\"\n  },\n  {\n    \"title\": \"FDC3 Google Groups\",\n    \"publisher\": \"Google Groups\",\n    \"image\": \"/img/community/groups.png\",\n    \"infoLink\": \"https://groups.google.com/a/finos.org/g/fdc3\",\n    \"description\": \"A (fairly active) Google group where you can get involved with the FDC3 project.   Talk with implementers, ask questions, find answers and hear the latest news on the FDC3 project.\",\n    \"badges\": [],\n    \"type\": \"other\"\n  },\n  {\n    \"title\": \"S&P Front Office\",\n    \"publisher\": \"S&P Global Market Intelligence\",\n    \"image\": \"/img/users/spglobal.png\",\n    \"infoLink\": \"https://www.spglobal.com/marketintelligence/en/client-segments/investment-management#portfolio-management\",\n    \"description\": \"As a provider of buyside Front Office applications, we are advocating for and pushing the standard forward.  We intend to utilize the protocol(s) within our next-generation Investment Management platform in order to power both S&P Global and third-party desktop app integrations.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"Norman & Sons\",\n    \"publisher\": \"Norman & Sons\",\n    \"image\": \"/img/users/norman-and-sons.png\",\n    \"infoLink\": \"https://www.normanandsons.com/\",\n    \"docsLink\": \"https://www.normanandsons.com/research/\",\n    \"description\": \"Norman & Sons is a digital product studio specializing in the research, design and build of user-centered enterprise applications. The studio has led the design and delivery of some of the best-known enterprise digital platforms for world-leading financial services firms and product firms. <br /><br /> They are starting to contribute to the development of FDC3 Sail.\",\n    \"badges\": [],\n    \"type\": \"solution-provider\"\n  },\n  {\n    \"title\": \"Ignite UI\",\n    \"publisher\": \"Infragistics\",\n    \"image\": \"https://static.infragistics.com/marketing/Website/General/Infragistics-horizontal.svg\",\n    \"infoLink\": \"https://www.infragistics.com/openfin\",\n    \"docsLink\": \"https://www.npmjs.com/package/igniteui-webcomponents-fdc3\",\n    \"description\": \"Ignite UI from Infragistics is a feature complete UI Platform for FDC3-enabled financial services apps. With over 60 UI controls & components plus charting including the world’s fastest virtualized data grids & data charts. No-lag, smooth scrolling for unlimited columns & rows of data, real-time, high-volume data support, with support for Web Components, Angular, React & Blazor, you have all the UX features you need for your modern FinTech apps.\\nWith our FDC3 Data Adapter, build low-touch, composite-based financial services desktop workflows with FDC3 and give your apps the chance to participate in the broader FinTech ecosystem.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"Client Engagement and Data Driven Advisory\",\n    \"publisher\": \"Singletrack\",\n    \"image\": \"https://www.singletrack.com/wp-content/uploads/2021/03/singletrack-logo-1.svg\",\n    \"infoLink\": \"https://www.singletrack.com/sell-side/\",\n    \"docsLink\": \"https://www2.singletrack.com/sell-side-product-overview\",\n    \"description\": \"Singletrack uses FDC3 to provide smooth desktop workflows for Sales, Research and Corporate Access professionals as they move between tools such as Chat & Email and platforms such as Order Management, Authoring & our own to deliver their daily work. With FDC3 we increase efficiency and ensure rich, relevant information is always at hand.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"Scott Logic Financial Services\",\n    \"publisher\": \"Scott Logic\",\n    \"image\": \"/img/users/scottlogic.png\",\n    \"infoLink\": \"https://www.scottlogic.com/\",\n    \"docsLink\": \"\",\n    \"description\": \"Scott Logic is a UK-based software consultancy that provides software development services to a number of financial services companies, many of which are FINOS members. We have built numerous bespoke, feature-rich and high-end web-based desktop solutions for our clients, including trading platforms, risk analytics and regulatory reporting. This has given us a wealth of experience of desktop container technologies and desktop interoperability. We use FDC3 with numerous clients.\\nAs active FINOS members, we are keen supporters of FDC3, and have recently created the FDC3 conformance framework which automates the process of ensuring the FDC3 APIs are faithfully implemented.\",\n    \"badges\": [],\n    \"type\": \"solution-provider\"\n  },\n  {\n    \"title\": \"AdapTable\",\n    \"publisher\": \"Adaptable Tools\",\n    \"image\": \"/img/users/adaptabletools.svg\",\n    \"infoLink\": \"https://www.adaptabletools.com/\",\n    \"docsLink\": \"https://docs.adaptabletools.com/guide/handbook-fdc3\",\n    \"description\": \"AdapTable - the FDC3-Ready DataGrid - is a powerful, low-code AG Grid extension which allows users to manage, visualise and transform their data in ways not previously possible. <br /><br />AdapTable provides a range of cutting-edge DataGrid features including Alerts, Calculated Columns, Conditional Styles, Scheduled Reports, Custom Filters, State Management, Team Sharing, Charting and much more. <br /><br />AdapTable includes full FDC3 capabilities which developers can leverage to broadcast and receive FDC3 Context, raise and receive FDC3 Intents and support custom FDC3.  AdapTable ships with a range of configurable FDC3 UI components, that work seamlessly with all FDC3 Platform Providers (e.g. OpenFin, interop.io, Connectifi and others) to promote collaboration and communication between multiple applications using FDC3.\",\n    \"badges\": [\n      {\n        \"text\": \"FDC3 2.0 Supported\"\n      }\n    ],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"ipushpull\",\n    \"publisher\": \"Pushpull Technology Ltd\",\n    \"image\": \"/img/users/ipp-logo.png\",\n    \"infoLink\": \"https://ipushpull.com/\",\n    \"docsLink\": \"https://support.ipushpull.com/\",\n    \"description\": \"ipushpull is a configurable low & no-code platform that makes it easy to maximise the value of your data-driven services. We help you to transform your clients’ experience with our low-code custom applications & solutions and integrated, white-labelled workflows. <br /><br />The ipushpull platform seamlessly integrates with all desktop interop solutions and lets you build your own FDC3-driven workflows through configuration alone.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"Symphony\",\n    \"publisher\": \"Symphony\",\n    \"image\": \"/img/users/Symphony.png\",\n    \"infoLink\": \"https://symphony.com/\",\n    \"docsLink\": \"https://docs.developers.symphony.com/embedded-modules/desktop-interoperability\",\n    \"description\": \"Symphony is the most secure and compliance-enabling markets’ infrastructure and technology platform, where solutions are built or integrated to standardize, automate and innovate financial services workflows. It is a vibrant community of over half a million financial professionals with a trusted directory and serves over 1,000 institutions. <br /><br />Symphony is powering over 2,000 community built applications and bots.<br /><br />The company's mission is to promote a strong ecosystem of innovation by our customers and partners on the platform. As a result, the platform has been built with an open API approach to benefit our end users through the fostering of deep integrations and novel workflows.<br /><br />Specifically, Symphony considers Desktop Integration Platforms integration as a key workflow enabler, bringing benefits like cross-application workflows and context sharing, better screen real-estate management and aggregated notification centers. As such, the company is actively working with the FINOS FDC3 working group to standardize DIP integration APIs across the industry.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"UBS uses FDC3 to build their next generation Derivatives Sales and Trading Desktop\",\n    \"publisher\": \"UBS AG\",\n    \"image\": \"/img/users/ubs.png\",\n    \"infoLink\": \"https://ubs.com/\",\n    \"description\": \"UBS Investment Bank are developing their next generation of Derivatives Sales and Trading Desktop using FDC3 from the ground up.<br/><br />  Contributions are predominantly via FDC3 related meetings and discussions around the standards, contexts and intents.\",\n    \"badges\": [],\n    \"type\": \"adopter\"\n  },\n  {\n    \"title\": \"Reactive Trader\",\n    \"publisher\": \"Adaptive Financial Consulting\",\n    \"image\": \"https://www.reactivetrader.com/static/media/reactive-trader-icon-256x256.png\",\n    \"infoLink\": \"https://www.reactivetrader.com/\",\n    \"docsLink\": \"https://weareadaptive.com/showcase/\",\n    \"description\": \"Reactive Trader® is Adaptive’s showcase FX trading application, built with modern web technologies, and available as open source. It showcases integration with multiple different desktop platforms, including PWA, OpenFin, Finsemble, Glue42 and Symphony. Reactive Trader® broadcasts out instrument messages via FDC3 when currency pairs are selected in the blotter. It can interoperate with Reactive Analytics.\",\n    \"badges\": [\n      {\n        \"text\": \"FDC3 1.2 Supported\"\n      },\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"type\": \"demos\"\n  },\n  {\n    \"title\": \"Reactive Analytics\",\n    \"publisher\": \"Adaptive Financial Consulting\",\n    \"image\": \"https://demo-reactive-analytics.adaptivecluster.com/static/media/reactive-analytics-icon-256x256.png\",\n    \"infoLink\": \"https://demo-reactive-analytics.adaptivecluster.com/ \",\n    \"docsLink\": \" https://github.com/AdaptiveConsulting/ReactiveAnalytics#readme\",\n    \"description\": \"Reactive Analytics is an Adaptive’s example stock and FX analytics application, built with modern web technologies, and available as open source. It showcases integration with multiple different desktop platforms, including PWA, OpenFin and Finsemble. Reactive Analytics listens and responds to instrument broadcast messages from other applications via FDC3, and can interoperate with Reactive Trader. \",\n    \"badges\": [\n      {\n        \"text\": \"FDC3 1.2 Supported\"\n      },\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"type\": \"demos\"\n  },\n  {\n    \"title\": \"Consulting Services\",\n    \"publisher\": \"Adaptive Financial Consulting\",\n    \"image\": \"https://fdc3.finos.org/img/users/adaptive.png\",\n    \"infoLink\": \"https://demo-reactive-analytics.adaptivecluster.com/ \",\n    \"docsLink\": \" https://weareadaptive.com/clients-stories/#electronic-trading-with-a-personal-touch\",\n    \"description\": \"This case study dives into how Adaptive was able to utilise FDC3 to deliver all the benefits of an electronic trading platform with full MiFID II compliance, while providing clients with the advantages of high-touch voice trading.\",\n    \"badges\": [],\n    \"type\": \"solution-provider\"\n  },\n  {\n    \"title\": \"Connectifi\",\n    \"publisher\": \"Connectifi Co.\",\n    \"image\": \"/img/users/connectifi.png\",\n    \"infoLink\": \"https://www.connectifi.co\",\n    \"description\": \"Connectifi provides FDC3 interop as a cloud service, empowering organizations to connect anything, anywhere, in a security-first environment that does not require installs.\\n\\nUse Connectifi to leverage FDC3 in standard browser and mobile environments, to expand the reach and ROI of your existing desktop tech stack, and to create secure and verifiable interop channels between mission critical applications.\",\n    \"badges\": [],\n    \"type\": \"platform-provider\",\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-1.2.png\",\n        \"items\": [\n          {\n            \"text\": \"Connectifi v1.1.0 Certified Conformant With FDC3 1.2 Specification on 26th April 2023\",\n            \"link\": \"https://www.finos.org/blog/fdc3-news-1.2-agent-conformance-language-bindings\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"title\": \"FlexTrade Buy and Sell-Side O/EMS Solutions\",\n    \"publisher\": \"FlexTrade Systems\",\n    \"image\": \"/img/users/flextrade.jpg\",\n    \"infoLink\": \"https://flextrade.com/buy-side-flextrade-products/\",\n    \"docsLink\": \"https://flextrade.com/openfin/\",\n    \"description\": \"FlexTrade uses the FDC3 standard for application interoperability to deliver trading teams a seamless experience across its full suite of buy and sell-side O/EMS solutions. Using FDC3 within FlexTrade’s solutions, trading teams are empowered to choose to customize their workflow with the specific tools and data unique to their needs. Further, it is visualized into a single view within their order blotter, eliminating the need to context switch between different screens or solutions within their workflow, enabling better decision-making and improving trading performance. <br/><br/>The work with OpenFin and LSEG Turquoise recently picked up “Financial Technology Innovation of the Year” in the Financial News Excellence in Trading and Tech Awards 2022. \",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"NexJ Integrated Advisor Desktop\",\n    \"publisher\": \"NexJ\",\n    \"image\": \"/img/users/nexj-systems-logo.png\",\n    \"infoLink\": \"https://www.nexj.com\",\n    \"docsLink\": \"https://www.nexj.com/resources-center/\",\n    \"type\": \"application-provider\",\n    \"badges\": [],\n    \"description\": \"<p>NexJ’s Integrated Advisor Desktop acts as a hub connecting best-of-breed solutions to deliver a superior seamless advisor experience that improves productivity, accelerates client acquisition, increases client retention and maximizes relationships. It contains all information about each client and household and integrates to other systems, allowing advisors to complete processes without logging into multiple applications and switching contexts.</p>\"\n  },\n  {\n    \"title\": \"FactSet\",\n    \"publisher\": \"FactSet\",\n    \"image\": \"/img/users/FactSet.png\",\n    \"infoLink\": \"https://www.factset.com\",\n    \"docsLink\": \"https://www.factset.com/solutions/data-solutions\",\n    \"description\": \"FactSet delivers financial data, analytics, and open technology in a digital platform to help approximately 180,000 users see more, think bigger, and do their best work. We empower the financial community to acquire new insights with access to comprehensive and contextualized content and multiply their effectiveness with flexible next-generation workflow solutions powered by innovative technologies. We meet our clients wherever they work and provide a platform built for seamless interoperability to enable users to create the desktop of their choice.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"FDC3 Sweden\",\n    \"publisher\": \"FDC3\",\n    \"image\": \"/img/meetups/fdc3-sweden.png\",\n    \"infoLink\": \"https://www.meetup.com/fdc3-sweden/\",\n    \"description\": \"FDC3 Sweden is organized in partnership with FINOS. The meetup aims to expand contributions to and consumption of FDC3 open standards for financial desktop technologies. The meetup also wants to grow a healthy engineering community in Sweden's financial services industry. Join the <a href='https://www.meetup.com/fdc3-sweden/' target='_blank' rel='noopener noreferrer'>FDC3 Sweden Meetup Here</a>.\",\n    \"badges\": [],\n    \"type\": \"other\"\n  },\n  {\n    \"title\": \"CAS Workflow\",\n    \"publisher\": \"comitFS\",\n    \"image\": \"https://www.comitfs.com/assets/img/logo@2x.webp\",\n    \"infoLink\": \"https://www.comitfs.com/cas-workflow.html\",\n    \"docsLink\": \"\",\n    \"description\": \"comitFS has been delivering a Telephony Integration Middleware dedicated to the the financial community for 20 years. Recently we have been exploring how to leverage FDC3 capabilities to bring call control and call based contextual data to user's desktops.\",\n    \"badges\": [\n      {\n        \"text\": \"FDC3 1.2 Supported\"\n      },\n      {\n        \"text\": \"Open Source\"\n      }\n    ],\n    \"type\": \"solution-provider\"\n  },\n  {\n    \"title\": \"Bank of Montreal\",\n    \"publisher\": \"BMO\",\n    \"image\": \"/img/users/bmo.png\",\n    \"infoLink\": \"https://www.bmo.com\",\n    \"description\": \"BMO is a strong advocate for interoperability and is developing multiple internal applications using FDC3. We contribute to the FDC3-related meetings and discussions around the standards, contexts and intents.\",\n    \"badges\": [],\n    \"type\": \"adopter\"\n  },\n  {\n    \"title\": \"Dow Jones Newswires\",\n    \"publisher\": \"Dow Jones\",\n    \"image\": \"/img/users/Dow_Jones_Logo.png\",\n    \"infoLink\": \" https://www.dowjones.com/professional/resources/blog/integration-innovation-interoperability-in-fintech-future\",\n    \"docsLink\": \"https://www.dowjones.com/professional/newswires/\",\n    \"description\": \"Dow Jones’ Interoperable Modules enable seamless integration of Dow Jones’ news into workflows, applications and content. Featuring premium financial and business content from trusted Dow Jones brands such as The Wall Street Journal, Barron’s, MarketWatch and Investor’s Business Daily, these news and data modules leverage FDC3 standards to enhance system interoperability. <br /> <br />As part of the workspace ecosystem, Dow Jones’ news and data modules help financial services firms optimize the financial professional’s experience. Modules are easily integrated into your company’s workflow, analytics and other platforms to make it easier to offer a personalized user experience. \",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"Interop Security Scorecard\",\n    \"publisher\": \"Connectifi Co.\",\n    \"image\": \"/img/users/connectifi.png\",\n    \"infoLink\": \"https://hubs.ly/Q02krHRh0\",\n    \"docsLink\": \"https://www.connectifi.co/post/interop-security-scorecard\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"Questions about security and identity in FDC3 are even more critical now, as adopters look to address higher value use cases through application interoperability.  The Interop Security Scorecard is a free, easy to use, and vendor-agnostic framework to evaluate FDC3 implementations across multiple vectors.\"\n  },\n  {\n    \"title\": \"Connectifi FDC3 Sandbox\",\n    \"publisher\": \"Connectifi Co.\",\n    \"image\": \"/img/users/connectifi.png\",\n    \"infoLink\": \"https://apps.connectifi-interop.com/sandbox\",\n    \"docsLink\": \"https://www.connectifi.co/post/getting-started\",\n    \"type\": \"demos\",\n    \"badges\": [],\n    \"description\": \"The Connectifi FDC3 Sandbox is a free FDC3 development tool that uses the Connectifi cloud service to securely enable interoperability across applications regardless of technology or device they are running on.  It uses the FDC3 standard and works without installs so that FDC3 can be used directly in a browser, bridging across desktop containers and across devices.\"\n  },\n  {\n    \"title\": \"Morgan Stanley\",\n    \"publisher\": \"Morgan Stanley\",\n    \"image\": \"/img/users/MorganStanley.png\",\n    \"infoLink\": \"https://github.com/morganstanley/ComposeUI\",\n    \"docsLink\": \"https://morganstanley.github.io/ComposeUI/documentation\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"conformance\": [\n      {\n        \"src\": \"\",\n        \"items\": []\n      },\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"Morgan Stanley ComposeUI version alpha-5 Certified Conformant With FDC3 2.0 Specification on 30th September 2024\",\n            \"link\": \"https://www.finos.org/press/fdc3-2.0-blackrock-morgan-stanley-lead-charge\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"ComposeUI is a .NET based general UI Container and Unified UI and App host which enables the hosting of Web and desktop content. It supports desktop and web applications in order to provide an evergreen alternative to Electron by the use of WebView2.\"\n  },\n  {\n    \"title\": \"Aladdin\",\n    \"publisher\": \"BlackRock\",\n    \"image\": \"/img/users/aladdin.png\",\n    \"infoLink\": \"https://www.blackrock.com/aladdin\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"BlackRock's Aladdin (currently unpublished) Certified Conformant With FDC3 2.0 Specification on 30th September 2024\",\n            \"link\": \"https://www.finos.org/press/fdc3-2.0-blackrock-morgan-stanley-lead-charge\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"Aladdin® is a tech platform that unifies the investment management process through a common data language. With a view of your whole portfolio—across public & private markets—it enables scale, provides insights, and supports business transformation.\"\n  },\n  {\n    \"title\": \"Morgan Stanley\",\n    \"publisher\": \"Morgan Stanley\",\n    \"image\": \"/img/users/MorganStanley.png\",\n    \"infoLink\": \"https://www.morganstanley.com\",\n    \"description\": \"Morgan Stanley believes that open standards like FDC3 are essential for unlocking new scenarios and efficiencies in user experience on the desktop for both our employees and our clients.\",\n    \"badges\": [],\n    \"type\": \"adopter\"\n  },\n  {\n    \"title\": \"NatWest Group\",\n    \"publisher\": \"NatWest Group\",\n    \"image\": \"/img/users/NatWestGroup.png\",\n    \"infoLink\": \"https://www.NatWestgroup.com/\",\n    \"description\": \"NatWest Group is proud to support the adoption of open standards such as FDC3, recognizing their transformative potential in reshaping how financial institutions connect applications and data across the desktop and thus unlocking new possibilities for both our colleagues and our customers.\",\n    \"badges\": [],\n    \"type\": \"adopter\"\n  },\n  {\n    \"title\": \"Agile Markets\",\n    \"publisher\": \"NatWest Group\",\n    \"image\": \"/img/users/AgileMarkets.png\",\n    \"infoLink\": \"https://www.agilemarkets.com\",\n    \"description\": \"Agile Markets is NatWest Markets's online platform for managing their clients currency needs. With trading, analysis, commentary and post-trade functionality, it’s a streamlined way to trade and navigate foreign exchange (FX) markets.\",\n    \"badges\": [],\n    \"type\": \"application-provider\"\n  },\n  {\n    \"title\": \"FDC3 Developer Training Workshop - Rob Moffat, FINOS\",\n    \"publisher\": \"FINOS\",\n    \"image\": \"/img/training/fdc3-developer-training-workshop.png\",\n    \"infoLink\": \"https://youtu.be/9uUKTk2e-Xs?si=ndejBtoHsKIXBAYy\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"The FDC3 Developer Training Workshop led by Rob Moffat from FINOS aims to teach participants how to build FDC3-enabled applications and understand the framework for defining Contexts and Intents to enable seamless interoperability between desktop applications in the financial services industry.\"\n  },\n  {\n    \"title\": \"How to Add FDC3 to Your Apps - Julianna Langston, interop.io\",\n    \"publisher\": \"FINOS\",\n    \"image\": \"/img/training/how-to-add-fdc3-to-your-apps.png\",\n    \"infoLink\": \"https://youtu.be/D6WST19pYUs?si=BtGSG7mkEdXBVEGL\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"This video training provides a practical guide on how to add the FDC3 (Financial Desktop Connectivity and Collaboration) open standard to your applications to enable interoperability between financial desktop applications.\"\n  },\n  {\n    \"title\": \"FDC3 2.2 & FDC3 on the Web! - Kristopher West, interop.io & Rob Moffat, FINOS\",\n    \"publisher\": \"FINOS\",\n    \"image\": \"/img/training/fdc3-2.2.png\",\n    \"infoLink\": \"https://youtu.be/Z98eSdIt2b0?si=e54cMAY_PvBFTv-c\",\n    \"type\": \"tools-and-training\",\n    \"badges\": [],\n    \"description\": \"This training video discusses FDC3 2.2, which tightens several aspects of the FDC3 standard and brings long-awaited improvements, as presented by Kristopher West from interop.io and Rob Moffat from FINOS.\"\n  },\n  {\n    \"title\": \"BMO X 9.0.0\",\n    \"publisher\": \"BMO\",\n    \"image\": \"/img/users/bmo.png\",\n    \"infoLink\": \"https://www.youtube.com/watch?v=ItwfBKYOLrs\",\n    \"type\": \"platform-provider\",\n    \"badges\": [],\n    \"conformance\": [\n      {\n        \"src\": \"/img/community/certified-2.0.png\",\n        \"items\": [\n          {\n            \"text\": \"BMO X 9.0.0 Certified Conformant With FDC3 2.0 Specification in October 2025.\",\n            \"link\": \"https://www.finos.org/blog/bmo-x-achieves-fdc3-certification-a-milestone-for-interoperability-in-banking\"\n          }\n        ]\n      }\n    ],\n    \"description\": \"<p>BMO is a leading financial institution that is committed to the use of open standards for interoperability.</p>\"\n  }\n]\n"
  },
  {
    "path": "website/data/get-involved/1.mdx",
    "content": "## Collaborate with the Community\n\nMost FDC3 collaboration takes place in the [FDC3 GitHub repository](https://github.com/finos/FDC3), where you can raise [issues](https://github.com/finos/FDC3/issues), submit [pull requests](https://github.com/finos/FDC3/pulls) and view [meeting minutes](https://github.com/finos/FDC3/issues?q=label%3Ameeting+)."
  },
  {
    "path": "website/data/get-involved/2.mdx",
    "content": "## Working Groups\n\n- If you're interested in discussing business workflows and other use cases that you can implementation with FDC3, you can join the [Use Cases & Workflows Discussion Group](https://github.com/finos/FDC3/issues?q=is%3Aopen+label%3A%22Use+cases%22+label%3Ameeting)\n\n- If you're interested in [Desktop Agent bridging](https://fdc3.finos.org/docs/next/agent-bridging/spec), you can join their next [Discussion Group call](https://github.com/finos/FDC3/issues?q=label%3A%22Desktop+Agent+Bridging%22+label%3A%22meeting%22+)\n\n- If you're implementing a Desktop Agent in a Web Browser and interested in helping define standards for doing so, you can join the [FDC3 for Web Browsers Discussion Group](https://github.com/finos/FDC3/issues?q=label%3A%22FDC3+for+Web+Browsers%22)\n\n\n"
  },
  {
    "path": "website/data/get-involved/3.mdx",
    "content": "## Participate in the Standard's ideation\n\nThe [Standard Working Group](https://github.com/finos/FDC3/issues?q=label%3A%22Standard+WG+Meeting%22) meets once a month to shape the next version of the Standard: you can find meeting details in the [FINOS Project Calendar](https://calendar.google.com/calendar/u/0/embed?src=finos.org_fac8mo1rfc6ehscg0d80fi8jig@group.calendar.google.com). \n\nIf you'd like to formally enroll as a voting Standard participant, please use this link: [fdc3-participants+subscribe@finos.org](mailto:fdc3-participants+subscribe@finos.org?subject=Please%20enroll%20me%20as%20an%20FDC3%20Standards%20Participant&body=HI%2C%20my%20name%20is%20%3CFirstName%20LastName%3E%20and%20I'd%20like%20to%20formally%20participate%20to%20the%20FDC3%20standard%20process.%20I%20plan%20to%20contribute%20as%20%3Cindividual%7Con%20behalf%20of%20organizationName%3E%20and%20I%20have%20reviewed%20the%20policies%20described%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FGOVERNANCE.md%20and%20read%20the%20license%20at%20https%3A%2F%2Fgithub.com%2Ffinos%2FFDC3%2Fblob%2Fmain%2FLICENSE%20.%20Thank%20you!) to send a templated email email to join the enrolled voting participants group. Please note that standard participants are bound to the provisions as described in the [FDC3 Governance document](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md#11-participants)."
  },
  {
    "path": "website/data/get-involved/4.mdx",
    "content": "## Are you using FDC3?\n\nIf you are an existing user of the FDC3 Standard, we would love to hear from you: just email the [FDC3 General List](mailto:fdc3@finos.org) with details about how you are using it. \n\nWe'd also like to list you as a user on our [Community page](https://fdc3.finos.org/community), you can directly [send a pull request](https://github.com/finos/FDC3/edit/main/website/data/community.json) or [contact us](mailto:fdc3-private@finos.org) (particularly if you need help with legal evaluation of your logo)."
  },
  {
    "path": "website/data/get-involved/5.mdx",
    "content": "## General Meeting\n\n- You can also attend the quarterly [FDC3 General Meeting](https://github.com/finos/FDC3/issues?q=label%3A%22General+Meeting%22): you can find meeting details in the [FINOS Project Calendar](https://calendar.google.com/calendar/u/0/embed?src=finos.org_fac8mo1rfc6ehscg0d80fi8jig@group.calendar.google.com).\n"
  },
  {
    "path": "website/data/pending-community.json",
    "content": "\n    {\n        \"title\": \"Open Source Fraud Risk Management (Transaction Monitoring)\",\n        \"publisher\": \"Tecnknowmage.com\",\n        \"image\": \"\",\n        \"infoLink\": \"https://github.com/ActioFRM\",\n        \"docsLink\": \"https://github.com/ActioFRM\",\n        \"description\": \"Recognizing the need, the Bill & Melinda Gates Foundation funded the development of an MVP Open-Source Transactional Monitoring System. The goals were:\\nTo continue the previously funded work around anti-fraud in mobile money systems and the typologies and assessment models developed in partnership with Deloitte and others.\\nBuild an effective and efficient API driven transactional monitoring engine that can be consumed in full or in part by any organization desiring to consume it and build around it.\\nRun large or small anti-fraud programs.\\nThe system must be state of the art and use only open-source components. MVP is complete. Onward!\",\n        \"badges\": [],\n        \"type\": \"application-provider\"\n      }\n"
  },
  {
    "path": "website/data/training.json",
    "content": "[\n  {\n    \"title\": \"Introduction to FDC3 (LFEL1000)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/LFEL1000.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/\",\n    \"type\": \"examples-and-training\",\n    \"badges\": [\n    ],\n    \"description\": \"<p>This <strong>FREE</strong> entry-level course is designed for business technologists who are looking to adopt application interoperability within their technology landscape and for developers who want to build interoperable applications using the FDC3 Standard.</p>\"\n  },\n  {\n    \"title\": \"Developing Solutions with FDC3 (LFD237)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/LFD237.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/training/developing-solutions-with-fdc3-lfd237/\",\n    \"type\": \"examples-and-training\",\n    \"badges\": [\n    ],\n    \"description\": \"<p>This course is designed for developers who are looking to build interoperable applications using the FDC3 standard, as well as community participants who provide FDC3 technology and services.</p><p>LFD237 is priced at $299 but free seats are available to FINOS members.</p>\"\n  },\n  {\n    \"title\": \"FDC3 Certified Practitioner (FCFP)\",\n    \"publisher\": \"Linux Foundation\",\n    \"image\": \"/img/training/FCFP.png\",\n    \"infoLink\": \"https://training.linuxfoundation.org/certification/finos-certified-fdc3-practitioner/\",\n    \"type\": \"examples-and-training\",\n    \"badges\": [\n    ],\n    \"description\": \"<p>The FCFP is a professional certification designed for technical business analysts, software developers and FDC3 implementers in the finance, insurance, banking, and investment industries.</p><p>FCFP is priced at $250 but free seats are available to FINOS members.</p>\"\n  }\n]\n"
  },
  {
    "path": "website/data/users.json",
    "content": "[\n    {\n        \"caption\": \"Adaptive Financial Consulting\",\n        \"image\": \"/img/users/adaptive.png\",\n        \"infoLink\": \"https://weareadaptive.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"BlackRock\",\n        \"image\": \"/img/users/blackrock.png\",\n        \"infoLink\": \"https://www.blackrock.com\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"ChartIQ\",\n        \"image\": \"/img/users/ChartIQ.png\",\n        \"infoLink\": \"https://chartiq.com\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Citi\",\n        \"image\": \"/img/users/citi.png\",\n        \"infoLink\": \"https://www.citigroup.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Finsemble\",\n        \"image\": \"/img/users/Finsemble.png\",\n        \"infoLink\": \"https://www.finsemble.com/\",\n        \"pinned\": false,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"FactSet\",\n        \"image\": \"/img/users/FactSet.png\",\n        \"infoLink\": \"https://www.factset.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Genesis Global\",\n        \"image\": \"/img/users/Genesis.png\",\n        \"infoLink\": \"https://genesis.global/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Glue42\",\n        \"image\": \"/img/users/GLUE42.png\",\n        \"infoLink\": \"https://glue42.com/\",\n        \"pinned\": false,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"GreenKey\",\n        \"image\": \"/img/users/GreenKey.png\",\n        \"infoLink\": \"https://greenkeytech.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"interop.io\",\n        \"image\": \"/img/users/interop.io-primary-1.svg\",\n        \"infoLink\": \"https://interop.io/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"S&P Global\",\n        \"image\": \"/img/users/spglobal.png\",\n        \"infoLink\": \"https://spglobal.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"JP Morgan\",\n        \"image\": \"/img/users/JPMorgan.png\",\n        \"infoLink\": \"https://www.jpmorgan.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Here\",\n        \"image\": \"/img/users/OpenFin_Here_Browser_250x120.png\",\n        \"infoLink\": \"https://here.io/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"RBC Capital Markets\",\n        \"image\": \"/img/users/RBCCMlogo.png\",\n        \"infoLink\": \"https://www.rbccm.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Refinitv\",\n        \"image\": \"/img/users/Refinitiv.png\",\n        \"infoLink\": \"https://www.refinitiv.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Scott Logic\",\n        \"image\": \"/img/users/scottlogic.png\",\n        \"infoLink\": \"https://www.scottlogic.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Singletrack\",\n        \"image\": \"/img/users/singletrack.png\",\n        \"infoLink\": \"https://www.singletrack.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Norman & Sons\",\n        \"image\": \"/img/users/norman-and-sons.png\",\n        \"infoLink\": \"https://www.normanandsons.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"iPushPull\",\n        \"image\": \"/img/users/ipp-logo.png\",\n        \"infoLink\": \"https://www.ipushpull.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Symphony\",\n        \"image\": \"/img/users/Symphony.png\",\n        \"infoLink\": \"https://www.symphony.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"UBS\",\n        \"image\": \"/img/users/ubs.png\",\n        \"infoLink\": \"https://www.ubs.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Connectifi\",\n        \"image\": \"/img/users/connectifi.png\",\n        \"infoLink\": \"https://www.connectifi.co/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"FlexTrade\",\n        \"image\": \"/img/users/flextrade.jpg\",\n        \"infoLink\": \"https://www.flextrade.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"NexJ\",\n        \"image\": \"/img/users/nexj-systems-logo.png\",\n        \"infoLink\": \"https://www.nexj.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Adaptable Tools\",\n        \"image\": \"/img/users/adaptabletools.svg\",\n        \"infoLink\": \"https://www.adaptabletools.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"BMO\",\n        \"image\": \"/img/users/bmo.png\",\n        \"infoLink\": \"https://www.bmo.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Dow Jones\",\n        \"image\": \"/img/users/Dow_Jones_Logo.png\",\n        \"infoLink\": \"https://www.dowjones.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"Morgan Stanley\",\n        \"image\": \"/img/users/MorganStanley.png\",\n        \"infoLink\": \"https://www.morganstanley.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    },\n    {\n        \"caption\": \"NatWest Group\",\n        \"image\": \"/img/users/NatWestGroup.png\",\n        \"infoLink\": \"https://www.natwestgroup.com/\",\n        \"pinned\": true,\n        \"isMember\": true\n    }    \n]\n"
  },
  {
    "path": "website/docs/.markdownlint.jsonc",
    "content": "{\n\t//Disabled as we often use manual H1 heading for reference pages, \n\t// where the markdown metadata is picked up as the top level heading\n\t\"single-h1\": false,\n\t//Many lines in md files are longer than 80 chars\n\t\"line-length\": false,\n\t//We have repeated headings, like 'Properties' or 'Fields' in reference docs.\n\t\"no-duplicate-header\": {\n\t\t\"siblings_only\": true\n\t},\n\t\"no-inline-html\": {\n\t\t\"allowed_elements\": [\n\t\t\t\"Tabs\",\n\t\t\t\"TabItem\"\n\t\t]\n\t},\n\t\"ul-style\": {\n\t\t\"style\": \"dash\"\n\t}\n}"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.broadcast.md",
    "content": "---\nid: PrivateChannel.broadcast\nsidebar_label: PC.broadcast\ntitle: PrivateChannel.broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast` API call on a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.broadcast(context: Context)`](../../api/ref/Channel#broadcast) (inherited from the [Channel](../../api/ref/Channel#broadcast) class)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.broadcast()\n    DA ->> DAB: PrivateChannel.broadcast\n    DAB ->> DB: PrivateChannel.broadcast\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelBroadcastAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelBroadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelBroadcastBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelBroadcastBridgeRequest.schema.json)\n\n### Example\n\n```javascript\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const privateChannel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = privateChannel.onAddContextListener((contextType) => {\n        // broadcast price quotes as they come in from our quote feed\n        feed.onQuote(symbol, (price) => {\n            privateChannel.broadcast({ type: \"price\", price});\n        });\n    });\n\n    ...\n\n    return channel;\n});\n```\n\nBroadcast messages that are sent from Agents that received the private channel from a remote agent are sent to the Desktop Agent that created the channel and returned it as an `IntentResult`, which is responsible for forwarding them onto other subscribers. If a broadcast message is generated on the Agent that created the channel it simply forwards it onto each subscriber.\n\nHence, the broadcast message should be repeated once for each subscriber, and modified such that it includes a destination, specified as a full `AppIdentifier`, and the `type` should indicate that it is a `PrivateChannel` broadcast:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.broadcast\", //modified type for PrivateChannel broadcasts\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.eventListenerAdded.md",
    "content": "---\nid: PrivateChannel.eventListenerAdded\nsidebar_label: PC.eventListenerAdded\ntitle: PrivateChannel.eventListenerAdded\n---\n\nDesktop Agent bridging message exchange for the addition of an event handler to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.onAddContextListener(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onaddcontextlistener)\n- [`PrivateChannel.onUnsubscribe(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onunsubscribe)\n- [`PrivateChannel.onDisconnect(handler: () => void): Listener`](../../api/ref/PrivateChannel#ondisconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application adds one of these event listeners to a private channel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel to facilitate routing of event messages. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: adds an event listener\n    DA ->> DAB: PrivateChannel.eventListenerAdded\n    DAB ->> DB: PrivateChannel.eventListenerAdded\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerAddedAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelEventListenerAddedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerAdded\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.eventListenerRemoved.md",
    "content": "---\nid: PrivateChannel.eventListenerRemoved\nsidebar_label: PC.eventListenerRemoved\ntitle: PrivateChannel.eventListenerRemoved\n---\n\nDesktop Agent bridging message exchange for the removal of an event handler from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe(): void`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) functions:\n    - [`onAddContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onaddcontextlistener)\n    - [`onUnsubscribe(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onunsubscribe)\n    - [`onDisconnect(handler: () => void): Promise<Listener>`](../../api/ref/PrivateChannel#ondisconnect)\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application removes an event listener from a PrivateChannel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel so it can discard retained routing information. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: removes an event listener\n    DA ->> DAB: PrivateChannel.eventListenerRemoved\n    DAB ->> DB: PrivateChannel.eventListenerRemoved\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerRemoved\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.onAddContextListener.md",
    "content": "---\nid: PrivateChannel.onAddContextListener\nsidebar_label: PC.onAddContextListener\ntitle: PrivateChannel.onAddContextListener\n---\n\nDesktop Agent bridging message exchange for the addition of a [`ContextHandler`](../../api/ref/Types#contexthandler) to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is added to a `PrivateChannel` any applications that have added an `onAddContextListener` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.addContextListener()\n    DA ->> DAB: PrivateChannel.onAddContextListener\n    DAB ->> DB: PrivateChannel.onAddContextListener\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onAddContextListener\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.onDisconnect.md",
    "content": "---\nid: PrivateChannel.onDisconnect\nsidebar_label: PC.onDisconnect\ntitle: PrivateChannel.onDisconnect\n---\n\nDesktop Agent bridging message exchange for a `disconnect()` API call on  [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen the `disconnect` function is is called on a `PrivateChannel` any applications that have added an `onDisconnect` handler or an `onUnsubscribe` handler (which is automatically called when an application disconnects) MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information. If the `PrivateChannel` was created by a remote agent, only the single `PrivateChannel.onDisconnect` is required. It is the responsibility of the Desktop Agent that created the channel to ensure that any relevant `onUnsubscribe` handlers are also called by sending additional `PrivateChannel.onUnsubscribe` messages to them before forwarding the `PrivateChannel.onDisconnect`. This applies whether the disconnection occurred on that agent or on a remote agent.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.disconnect()\n    DA ->> DAB: PrivateChannel.onDisconnect\n    DAB ->> DB: PrivateChannel.onDisconnect\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnDisconnectAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnDisconnectAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnDisconnectBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnDisconnectBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onDisconnect\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/PrivateChannel.onUnsubscribe.md",
    "content": "---\nid: PrivateChannel.onUnsubscribe\nsidebar_label: PC.onUnsubscribe\ntitle: PrivateChannel.onUnsubscribe\n---\n\nDesktop Agent bridging message exchange for the removal of a [`ContextHandler`](../../api/ref/Types#contexthandler) from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe()`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) function:\n    - [`addContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n- [`PrivateChannel.disconnect()`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is removed from a `PrivateChannel` (via `listener.unsubscribe`) any applications that have added an `onSubscribe` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: listener.unsubscribe()\n    DA ->>+ DAB: PrivateChannel.onUnsubscribe\n    DAB ->>+ DB: PrivateChannel.onUnsubscribe\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json](pathname:///schemas/next/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json)\n\n### Example\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.onUnsubscribe\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/broadcast.md",
    "content": "---\nid: broadcast\nsidebar_label: broadcast\ntitle: broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast()` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent) or a [`Channel`](../../api/ref/Channel). Generated by API calls:\n\n- [`fdc3.broadcast(context: Context): Promise<void>`](../../api/ref/DesktopAgent#broadcast)\n- [`Channel.broadcast(context: Context): Promise<void>`](../../api/ref/Channel#broadcast)\n\n:::caution\n\nBroadcasts on a [`PrivateChannel`](../../api/ref/PrivateChannel) have a separate message exchange, see [`PrivateChannel.broadcast`](PrivateChannel.broadcast).\n\n:::\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\nE.g.\n\n```javascript\nfdc3.broadcast(contextObj);\n```\n\nor\n\n```javascript\n(await fdc3.getOrCreateChannel(\"myChannel\")).broadcast(contextObj)\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.broadcast() / channel.broadcast()\n    DA ->> DAB: broadcastRequest\n    DAB ->> DB: broadcastRequest\n    DAB ->> DC: broadcastRequest\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/broadcastAgentRequest.schema.json](pathname:///schemas/next/bridging/broadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/broadcastBridgeRequest.schema.json](pathname:///schemas/next/bridging/broadcastBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/ }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2022-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nwhich it repeats on to agent-B AND agent-C with the `source.desktopAgent` metadata added.\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/findInstances.md",
    "content": "---\nid: findInstances\nsidebar_label: findInstances\ntitle: findInstances\n---\n\nDesktop Agent bridging message exchange for a `findInstances` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>`](../../api/ref/DesktopAgent#findinstances)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)** or **Request Response (single)**\n\nA Desktop Agent's [`findInstances`](../../api/ref/DesktopAgent#findinstances) API call should return an empty array for known applications and [`ResolveError.NoAppsFound`](../../api/ref/Errors#resolveerror) for unknown apps. Hence, if a findInstances request is received through bridging for a known app with no instances then a normal response should be returned with an empty array. The bridge should add the responding agent to the `sources` array in the collated response as this is a valid response. If the application is not known to the agent an error response should be used instead with the `ResolveError.NoAppsFound` message and the responding Desktop Agent should be added to the `meta.errorSources` of the bridge response.\n\nIn the event that all agents returned an error response, then the bridge will also return an error response, which is passed back to the calling application. However, if any agent returned a valid response (including with an empty array) then the application was known, but had no instances, resulting in an empty array being returned to the calling application.\nE.g.\n\n```javascript\n// Retrieve a list of all instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Retrieve a list of instances of an application on a specified Desktop Agent\nlet instances = await fdc3.findInstances({appId: \"MyAppId\", desktopAgent: \"agent-A\"});\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findInstances()\n    DA ->> DAB: findInstancesRequest\n    DAB ->> DB: findInstancesRequest\n    DAB ->> DC: findInstancesRequest\n    DB ->> DAB: findInstancesResponse (B)\n    DC ->> DAB: findInstancesResponse (C)\n    DAB ->> DA: findInstancesResponse (B + C)\n    DA --) AA: resolve (AppIdentifier[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentRequest.schema.json](pathname:///schemas/next/bridging/findInstancesAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeRequest.schema.json](pathname:///schemas/next/bridging/findInstancesBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n:::note\nIf the `findInstancesRequest` from the requesting agent does not include a `meta.source` field then the Bridge MUST set the `meta.source.desktopAgent` field to attribute the request to the requesting agent. This is the case for all agent request messages that don't require application details.\n:::\n\nIf results should be constrained to a particular Desktop Agent, then set a `desktopAgent` field in `payload.app` and a matching `destination` field in `meta`:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\": \"agent-B\" // destination agent\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"destination\": { \"desktopAgent\": \"agent-B\" }, //destination agent\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nThe Desktop Agent Bridge should only forward the request to the requested Desktop Agent and handle the message exchange as a **Request Response (single)**.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentResponse.schema.json](pathname:///schemas/next/bridging/findInstancesAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/findInstancesAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeResponse.schema.json](pathname:///schemas/next/bridging/findInstancesBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findInstancesBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/findInstancesBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, augmenting each appIdentifier with a `desktopAgent` field, producing the following collated response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n            //\"desktopAgent\" added by DAB\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\", \n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::info\nIf a target Desktop Agent was specified in the request (via a `desktopAgent` field in `payload.app`), then the DAB is not collating responses and does not need to generate a unique `meta.responseUuid` and MUST quote that given by the responding Desktop Agent.\n:::\n\n:::note\nIn the event that an agent times out or returns an error, where others respond, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources`.\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// DAB -> agent-A\n[\n    { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"688dbd5e-21dc-4469-b8cf-4b6a606f9a27\" } //local response\n]\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/findIntent.md",
    "content": "---\nid: findIntent\nsidebar_label: findIntent\ntitle: findIntent\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>`](../../api/ref/DesktopAgent#findintent)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with `appId: \"agentA-app1\"` and `instanceId: \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.findIntent(\"StartChat\", context);\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A \n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntent()\n    DA ->> DAB: findIntentRequest\n    DAB ->> DB: findIntentRequest\n    DAB ->> DC: findIntentRequest\n    DB ->> DAB: findIntentResponse (B)\n    DC ->> DAB: findIntentResponse (C)\n    DAB ->> DA: findIntentResponse (B + C)\n    DA --) AA: resolve (AppIntent)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentAgentRequest.schema.json](pathname:///schemas/next/bridging/findIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeRequest.schema.json](pathname:///schemas/next/bridging/findIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB (with `intent` and `context` specified, but not `resultType`):\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C):\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\nNote that the `source.desktopAgent` field has been populated with the id of the agent that raised the requests, enabling the routing of responses.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentAgentResponse.schema.json](pathname:///schemas/next/bridging/findIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/findIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeResponse.schema.json](pathname:///schemas/next/bridging/findIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/findIntentBridgeErrorResponse.schema.json)\n\n### Example\n\nNormal response from agent-A, where the request was raised.\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"myChat\" }\n    ]\n}\n```\n\nDA agent-B would produce the following response if the request was generated locally:\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n        { \"appId\": \"Symphony\", \n          \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n          \"title\": \"Symphony\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\" }\n    ]\n}\n```\n\nHence, the response it sends to the bridge is encoded as follows:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */ },\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\" }\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nNote the response UUID generated by the agent-B and the reference to the request UUID produced by agent-A where the request was originated. Further, note that the `AppMetadata` elements in the `AppIntent` do not have a `desktopAgent` field yet, and the `meta` element does not contain a `sources` element, both of which the bridge will add.\n\nDA agent-C would produce the following response locally:\n\n```json\n{\n    \"intent\":  { \"name\": \"StartChat\" },\n    \"apps\": [\n       { \"appId\": \"WebIce\"}\n    ]\n}\n```\n\nwhich is sent back over the bridge as a response to the request message as:\n\n```json\n// agent-C -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"WebIce\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentC>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, producing the following collated response which is sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"intent\":  \"StartChat\",\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" }, //desktopAgent added by DAB\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\", \n                  \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::note\n\nIn the event that an agent referred to in the API call is not connected to the bridge, an agent that was connected times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` and the appropriate error ([`ResolveError.DesktopAgentNotFound`](../../api/ref/Errors#resolveerror), [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// agent-A -> requesting App\n{\n    \"intent\":  { \"name\": \"StartChat\", \"displayName\": \"Chat\" },\n    \"apps\": [\n        // local to this agent\n        { \"appId\": \"myChat\" },\n        //agent-B responses\n        { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"Symphony\", \n            \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n        //agent-C responses\n        { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n    ]\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/findIntentsByContext.md",
    "content": "---\nid: findIntentsByContext\nsidebar_label: findIntentsByContext\ntitle: findIntentsByContext\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>`](../../api/ref/DesktopAgent#findintentsbycontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntentArr = await fdc3.findIntentsByContext(context);\n```\n\n:::note\nThe message exchanges for this API call are nearly identical to that used for [`findIntent()`](findIntent), differing only by the lack of an `intent` field in the request message payload and the structure of the response message (where an array of `AppIntents` is returned).\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntentsByContext\n    DA ->> DAB: findIntentsByContextRequest\n    DAB ->> DB: findIntentsByContextRequest\n    DAB ->> DC: findIntentsByContextRequest\n    DB ->> DAB: findIntentsByContextResponse (B)\n    DC ->> DAB: findIntentsByContextResponse (C)\n    DAB ->> DA: findIntentsByContextResponse (B + C)\n    DA --) AA: resolve (AppIntent[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentRequest.schema.json](pathname:///schemas/next/bridging/findIntentsByContextAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeRequest.schema.json](pathname:///schemas/next/bridging/findIntentsByContextBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/},\n        \"resultType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C).\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/},\n        \"resultType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentResponse.schema.json](pathname:///schemas/next/bridging/findIntentsByContextAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/findIntentsByContextAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeResponse.schema.json](pathname:///schemas/next/bridging/findIntentsByContextBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/findIntentsByContextBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/findIntentsByContextBridgeErrorResponse.schema.json)\n\n### Example\n\nAn individual agent (for example agentB) would generate a local response as an array of `AppIntent` objects:\n\n```json\n[\n    {\n        \"intent\": { \"name\": \"StartChat\" },\n        \"apps\": [\n            { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n            { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n            { \"appId\": \"Symphony\", \n                \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                \"title\": \"Symphony\" },\n            { \"appId\": \"Slack\", \"title\": \"Slack\" }\n        ]\n    },\n    {\n        \"intent\": { \"name\": \"ViewProfile\" },\n        \"apps\": [\n            { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n            { \"appId\": \"myCRM\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"My CRM\" }\n        ]\n    }\n]\n```\n\nThis response is encoded and sent to the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\" }\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nEach `AppMetadata` object is augmented by the bridge with a `desktopAgent` field, the responding `DesktopAgentIdentifier` value is added to the `meta.sources` element and the message payload is collated with responses from other agents into a response to the requesting agent:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    //agent-B responses\n                    { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\", \n                        \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                    //agent-C response\n                    { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    //agent-A responses\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\",\n                    \"desktopAgent\": \"agent-B\" }\n                    //agent-C responses\n                    { \"appId\": \"riskToolkit\", \"title\": \"Client Risk Toolkit\", \"desktopAgent\": \"agent-C\" },\n                    { \"appId\": \"linkedIn\", \"title\": \"LinkedIn\", \"desktopAgent\": \"agent-C\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [\n            { \"desktopAgent\": \"agent-B\" }, \n            { \"desktopAgent\": \"agent-C\" }\n        ]\n    }\n}\n```\n\nFinally agent-A combines the payload received with it own response and returns it to the requesting application.\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/getAppMetadata.md",
    "content": "---\nid: getAppMetadata\nsidebar_label: getAppMetadata\ntitle: getAppMetadata\n---\n\nDesktop Agent bridging message exchange for a `getAppMetadata` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`getAppMetadata(app: AppIdentifier): Promise<AppMetadata>`](../../api/ref/DesktopAgent#getappmetadata)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\nlet appIdentifier = { appId: \"myApp@my.appd.com\", desktopAgent: \"agent-B\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n:::info\n`fdc3.getAppMetadata` calls should only involve the Desktop Agent Bridge where a `desktopAgent` field appears in the AppIdentifier being queried, all other calls should be handled locally by the Desktop Agent. Hence, the `payload.app.desktopAgent` is required on all requests.\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.getAppMetadata()\n    DA ->> DAB: getAppMetadataRequest\n    DAB ->> DB: getAppMetadataRequest\n    DB ->> DAB: getAppMetadataResponse (B)\n    DAB ->> DA: getAppMetadataResponse (B)\n    DA --) AA: resolve (AppMetadata)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentRequest.schema.json](pathname:///schemas/next/bridging/getAppMetadataAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeRequest.schema.json](pathname:///schemas/next/bridging/getAppMetadataBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentResponse.schema.json](pathname:///schemas/next/bridging/getAppMetadataAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/getAppMetadataAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeResponse.schema.json](pathname:///schemas/next/bridging/getAppMetadataBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/getAppMetadataBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/getAppMetadataBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...] \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives the response, augments the appMetadata with a `desktopAgent` field, producing the following response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...],\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }]\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/open.md",
    "content": "---\nid: open\nsidebar_label: open\ntitle: open\n---\n\nDesktop Agent bridging message exchange for a `open` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>`](../../api/ref/DesktopAgent#open)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\n// Open an app without context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n\n// Open an app with context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier, contextObj);\n```\n\nNote that it is not currently possible to identify resolve all available applications within a Desktop Agent via the FDC3 API. Hence, `fdc3.open` calls without a specified `desktopAgent` field in their `AppIdentifier`, e.g.:\n\n```javascript\n// Open a target app via AppIdentifier, without a specified Desktop Agent \nlet AppIdentifier = {appId: 'myApp-v1.0.1'};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n```\n\nshould always be processed locally without be passed to the bridge.\n\nThe `fdc3.open` command should result in a single copy of the specified app being opened and its instance data returned, or an error if it could not be opened. When receiving a response from invoking `fdc3.open` via the Desktop Agent Bridge, the new app instances MUST be initialized before responding as the responding Desktop Agent will need to return an `AppIdentifier` with an `instanceId` field set.\n\nIf the remote Desktop Agent is not currently connected from the bridge, the [`OpenError.DesktopAgentNotFound` error](../../api/ref/Errors#openerror) should be returned in the response from the bridge and the promise returned  from the call to `fdc3.open` rejected with it.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.open()\n    DA ->> DAB: openRequest\n    DAB ->> DB: openRequest\n    DB ->> DAB: openResponse\n    DAB ->> DA: openResponse\n    DA --) AA: resolve (AppIdentifier)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/openAgentRequest.schema.json](pathname:///schemas/next/bridging/openAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/openBridgeRequest.schema.json](pathname:///schemas/next/bridging/openBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"agent-B\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"DesktopAgentB\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/openAgentResponse.schema.json](pathname:///schemas/next/bridging/openAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/openAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/openAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/openBridgeResponse.schema.json](pathname:///schemas/next/bridging/openBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/openBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/openBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from target Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nwhich is augmented and repeated on by the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/ref/raiseIntent.md",
    "content": "---\nid: raiseIntent\nsidebar_label: raiseIntent\ntitle: raiseIntent\n---\n\nDesktop Agent bridging message exchange for a `raiseIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`raiseIntent(intent: string, context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintent)\n- [`raiseIntentForContext(context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintentforcontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Multiple Response (single)**\n\nFor Desktop Agent Bridging, a `raiseIntent` message exchange MUST always pass an `app: AppIdentifier` argument to target the intent. Further, if no `instanceId` is set in the `AppIdentifier`, then it should be interpreted to mean *'spawn a new instance of the target application'*. A local FDC3 API implementation call would normally defer to a resolver UI or similar if there are multiple options for resolving a specified `appId` (i.e. existing instance(s) and the option spawning a new instance), whereas this message exchange assumes that resolution has already taken place on the source Desktop Agent.\n\nHence, if a target [`AppIdentifier`](../../api/ref/Types#appidentifier) is not passed in the original `DesktopAgent` API call, then the [`findIntent`](findIntent) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange may then be used (if a remote option was selected as the resolution) to raise the intent.\n\n:::info\n\nThe same approach applies to `fdc3.raiseIntentForContext` calls, in that a [`findIntentByContext`](findIntentsByContext) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange is then used (if a remote option was selected as the resolution) to raise the intent.\n\n:::\n\ne.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context);\n```\n\nAgent A should then conduct the `findIntent` message exchange as described above, displaying its Intent resolver UI if necessary. Once an option is selected, the `raiseIntent` message exchange is conducted as if the API call had been made with a target app:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context, {\"appId\": \"Slack\", \"desktopAgent\": \"agent-B\"});\n```\n\nIn the event that an agent referred to in the API call is not connected to the bridge, it is connected but times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` in the `raiseIntentResponse` and the appropriate error (which might include any error from the [`ResolveError`](../../api/ref/Errors#resolveerror) enumeration, [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::tip\n\nDesktop Agents MAY support the deprecated `raiseIntent` signature that uses the app `name` field by using the `findIntent` message exchange to attempt to resolve the `name` to an `AppIdentifier`.\n\n:::\n\n## Message exchange\n\n:::note\n\nAgent-C is not involved in the diagram below as the `raiseIntent` is always specified with a target application and Desktop Agent.\n\n:::\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.raiseIntent \n    DA ->> DAB: raiseIntentRequest\n    DAB ->> DB: raiseIntentRequest\n    DB ->> DAB: raiseIntentResponse\n    DAB ->> DA: raiseIntentResponse\n    DA -->> AA: resolve (IntentResolution)\n    AA --) DA: resolution.getResult()\n    DB ->> DAB: raiseIntentResultResponse\n    DAB ->> DA: raiseIntentResultResponse\n    DA --) AA: resolve (IntentResult)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentRequest.schema.json](pathname:///schemas/next/bridging/raiseIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeRequest.schema.json](pathname:///schemas/next/bridging/raiseIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": { // AppIdentifier for chosen resolution including desktopAgent value\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\nThe bridge fills in the `source.desktopAgent` field and forwards the request to the target Desktop Agent:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": {\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultAgentResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentResultAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultAgentErrorResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentResultAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentBridgeErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultBridgeResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentResultBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/next/bridging/raiseIntentResultBridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/raiseIntentResultBridgeErrorResponse.schema.json)\n\n### Example\n\nIf the `raiseIntent` request were made locally, agent-B would deliver the intent and context to the target app's `IntentHandler` and respond to the raising application with an `IntentResolution`:\n\n```javascript\n{\n    \"intent\": \"StartChat\",\n    \"source\": {\n        \"appId\": \"Slack\",\n        \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"   \n    },\n    getResult: ƒ\n}\n```\n\nThis is encoded and sent to the bridge (omitting the `getResult()` function) as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"      \n            }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nWhen producing a response to a `raiseIntent` request, the instance of the receiving application MUST be initialized (if it does not already exist) and an `instanceId` generated for it before the `IntentResolution` is generated so that it can include the `instanceId`.\n\n:::\n\nThe bridge will fill in the `intentResolution.source.DesktopAgent` & `source.desktopAgent` and relay the message back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\",\n                \"desktopAgent\": \"agent-B\" // added by DAB\n            }  \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nWhen `Slack` produces an `IntentResult` from its `IntentHandler`, or the intent handler finishes running without returning a result, it should send a further `raiseIntentResultResponse` message to indicate that it's finished running and to pass any `IntentResult` onto the raising application (setting either `payload.intentResult.context` or `payload.intentResult.channel` to indicate the type of the `IntentResult`, or leaving `payload.intentResult` empty to indicate a `void` result). There is no need to provide a `source` field in this response as the source information was already provided in the `raiseIntentResponse` message preceding it.\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"intentResult\": {\n            \"context\": {/*contextObj*/}\n            /* for a channel IntentResult use:\n            \"channel\": {\n                \"id\": \"app-channel xyz\",\n                \"type\": \"user\"\n            }\n\n            or for a void result use leave this object empty.\n            */\n\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\", //a different UUID should be used for the result response\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nIf intent result is private channel see [PrivateChannels](../spec#privatechannels) for additional message exchanges that may be needed.\n\n:::\n\nFinally, the bridge augments the response with `sources[0].desktopAgent` and passes it back to Agent-A.\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nIf the `IntentHandler` returned `void` rather than an intent result `payload` should be empty, e.g.:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {},\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/docs/agent-bridging/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Agent Bridging Overview (next)\n---\n\n:::info _[@experimental](../fdc3-compliance#experimental-features)_\n\nDesktop Agent Bridging is an experimental feature added to FDC3 in 2.1, hence, its design may change in the future and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\n<!-- ## TODO list\n\n* Expand on how the DAB should create the JWT token (and its claims, which must change to avoid replay attacks) which it sends out in the `hello` message for DAs to validate.\n* Link to BackPlane project somewhere \n\n-->\n\nThe FDC3 Desktop Agent API addresses interoperability between apps running within the context of a single Desktop Agent (DA), enabling cross-application workflows and context sharing.\n\n![A single desktop and FDC3 Desktop Agent](/assets/dab-overview-1.png)\n\nIt is clear, however, that user desktops are substantially more complicated in reality. Some Desktop Agent implementations already provide additional features allowing \"external\" applications (e.g. those not launched by the Desktop Agent) to connect in order to participate in interoperability.\n\n![A single desktop and Desktop Agent, with external apps](/assets/dab-overview-2.png)\n\nFirms that make extensive use of FDC3 have also identified use cases where interoperability workflows span different physical desktops, and have built proprietary bridging solutions (e.g. [Backplane](https://backplane.finos.org/) was originally developed as an in-house solution to this problem).\n\n![Two physical desktops with a desktop agent each](/assets/dab-overview-3.png)\n\nWith the success of FDC3, usage of vendor-provided Desktop Agents has increased substantially among banks and buy-side institutions. Buy-side firms who are clients of multiple banks' platforms have multiple desktop agents delivered to their desktops. Several software vendors also deliver FDC3-compatible software: some as apps that can run in any Desktop Agent, but some as self-contained applications running in their own desktop agent. They are often multi-component suites of functionality with a customized user experience, and are not simple to export to a different Desktop Agent. In these cases, being able to provide a single installable platform bundled with a Desktop Agent is a far more practical solution for the vendor and customer.\n\n![Two physical desktops, one with multiple desktop agents](/assets/dab-overview-4.png)\n\nHowever, unless the Desktop Agents themselves can interoperate, unfortunately, this approach prevents interoperability rather than promoting it. To support user workflows spanning the whole environment there needs to be some form of network connectivity between Desktop Agents.\n\nDesktop Agent Bridging addresses the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can also interoperate, allowing workflows to span multiple Desktop Agents. This is achieved, without implementation changes or special handling in the apps, by providing a protocol and service for the Desktop Agents to interoperate with each other instead, allowing application interop to extend across the bridged agents, seamlessly.\n\nIn any Desktop Agent Bridging scenario, it is expected that each DA is being operated by the same user (as the scope of FDC3 contemplates cross-application workflows for a single user, rather than cross-user workflows), although DAs may be run on different machines operated by the same user. Whether a bridge is running for Desktop Agents to connect to, whether it requires the agents to authenticate etc., is in the hands of the user (and their local IT team).\n\n## Bridging Desktop Agents\n\nThe Desktop Agent Bridging Part of the FDC3 Standard is composed of three components:\n\n- **[Bridge Connection](#connection)**: A means for Desktop Agents to communicate with a bridge, and through that bridge, with each other.\n- **[Bridge Connection Protocol (BCP)](#bridge-connection-protocol)**: A protocol defining message exchanges necessary to connect to a Bridge and to perform initial state synchronization.\n- **[Bridge Messaging Protocol (BMP)](#bridge-messaging-protocol)**: A protocol defining message exchanges that allow FDC3 API interop to extend across multiple Desktop Agents.\n\nDetail on each of these components is defined in the following sections.\n\n:::note\n\nAlthough this specification defines a particular [connection](#connection) type (based on a websocket server), it has been divided into parts so that the protocol definitions might be reused to implement a bridge over an alternative connection in future.\n\n::: \n\n:::tip\n\nThe Desktop Agent Bridging protocol has been designed such that an application using the FDC3 API does not need to make any significant changes in order to make use of the Bridging connection between its Desktop Agent and another agent. This is achieved via messaging workflows that allow the bridged agents to cooperate on behalf of the applications, for example, by retrieving options for intent resolution from other agent or forwarding on messages that were broadcast on channels.\n\nHowever, Bridging should still be visible to applications, which is achieved through the addition of a `desktopAgent` field to the `AppIdentifier` type allowing it to indicate that an app or app instance exists on another agent, as well as a number of new error messages that may be returned to indicate bridging issues.\n\n:::\n\n### Agent Bridging Compliance\n\nAgent Bridging is introduced in FDC3 2.1 as an [@experimental](../fdc3-compliance#experimental-features) feature of the FDC3 Standard, included to enable implementation by and feedback from the FDC3 community. As such, it is currently optional for the purposes of compliance and is exempted from the normal versioning and deprecation polices in order to facilitate any refinement needed.\n\n### JSON Message Protocol & JSON Schema\n\nThe Bridge Connection Protocol (BCP) and Bridge Messaging Protocols (BMP) that the Desktop Agent Bridging Part defines are based on messages encoded in JSON. [JSON Schema](https://json-schema.org/) is used to define the format of each message in the protocol. These schema files should be considered the 'source of truth' for each and may be used to validate that individual messages are in the correct format. However, examples are provided in the documentation in TypeScript and JavaScript formats for convenience. TypeScript interfaces for individual messages, included in the FDC3 NPM module, are generated from the JSON Schema source files using [quicktype](https://quicktype.io/).\n\n## Connection\n\n### Topology\n\nIn order to implement Desktop Agent Bridging some means for Desktop Agents to connect to and communicate with each other is needed. This Standard assumes that Desktop Agent Bridging is implemented via a standalone 'bridge' which each agent connects to and will use to route messages to or from other agents. This topology is similar to a star topology in networking, where the Desktop Agent Bridge (a 'bridge') will be the central node acting as a router.\n\n```mermaid\nflowchart TD;\n    A[DA A]\n    B[DA B]\n    C[DA C]\n    D[DA D]\n    E{Bridge} \n    E <--> |websocket| A\n    E <--> |websocket| B\n    C <--> |websocket| E\n    D <--> |websocket| E\n```\n\nOther possible topologies include peer-to-peer or client/server networks, however, these introduce significant additional complexity into multiple aspects of the bridging protocol that must be implemented by Desktop Agents, (including discovery, authentication and message routing), where a star topology/standalone bridge enables a relatively simple set of protocols, with the most difficult parts being implemented in the bridge itself.\n\nWhilst the standalone bridge represents a single point of failure for the interconnection of Desktop Agents, it will also be significantly simpler than a full Desktop Agent implementation. Further, failures may be mitigated by setting the bridge up as a system service, such that it is started when the user's computer is started and may be restarted automatically if it fails. In the event of a bridge failure or manual shutdown, then Desktop Agents will no longer be bridged and should act as single agents.\n\nBy using the Desktop Agent Bridging Connection and Messaging protocols, a bridge will implement \"server\" behavior by:\n\n- Accepting connections from client Desktop Agents, receiving and authenticating credentials and assigning a name (for routing purposes)\n- Receiving requests from client Desktop Agents.\n- Routing requests to client Desktop Agents.\n- Receiving responses from client Desktop Agents and collating them.\n- Routing responses to client Desktop Agents.\n\nA Desktop Agent will implement \"client\" behavior by:\n\n- Connecting to the bridge, providing authentication credentials and receiving an assigned named (for routing purposes).\n- Forwarding requests to the bridge.\n- Awaiting response(s) from the bridge.\n- Receiving requests from the bridge.\n- Sending responses to the bridge.\n\nHence, message paths and propagation are simple. All messages to other Desktop Agents are passed to the bridge for routing and all messages (both requests and responses) are received back from it, i.e. the bridge is responsible for all message routing.\n\n#### Multi-Machine Use Cases\n\nIn financial services it is not unusual for a single user to be working with applications on more than one desktop. As Desktop Agents do not span desktops bridging Desktop Agents across multiple machines is an additional use case for Desktop Agent bridging. However, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user.\n\n```mermaid\nflowchart LR;\n    A[DA A]\n    B[DA B]\n    B1{Bridge 1} \n    C[DA C]\n    D[DA D]\n    B2{Bridge 2}\n\n    subgraph PC1 [PC 1]\n      direction RL\n      B1 <--> |websocket| A\n      B1 <--> |websocket| B\n    end\n    subgraph PC2 [PC 2]\n      direction LR\n      B2 <--> |websocket| C\n      B2 <--> |websocket| D\n    end\n    PC1 .- |Bridge interconnect| PC2\n```\n\nHowever, cross-machine routing is currently considered to be an internal concern of a Desktop Agent Bridge implementation, with each Desktop Agent simply communicating with a bridge instance located on the same machine. Hence, the connection protocol between bridges themselves is currently beyond the scope of this standard and my be implemented via any suitable means.\n\nFurther, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user. However, methods of verifying the identity of users are currently beyond the scope of the Standard.\n\n### Websocket Connection\n\nConnections between Desktop Agents and the Desktop Agent Bridge will be made via websocket connections, with the bridge acting as the websocket server and each connected Desktop Agent as a client.\n\nThe bridge MUST run on the same machine as the Desktop Agents, and the websocket MUST be bound to the loopback adapter IP address (127.0.0.1), ensuring that the websocket is not exposed to wider networks.\n\nBridge implementations SHOULD default to binding the websocket server to a port in the recommended port range 4475 - 4575, enabling simple discovery of a running bridge via attempting socket connections to ports in that range and attempting a handshake (as defined later in this proposal) that will identify the websocket as belong to a Desktop Agent Bridge. A port range MAY be used, in preference to a single nominated port, in order to enable the automatic resolution of port clashes with other services.\n\nBoth DAs and bridge implementations SHOULD support at least connection to the recommended port range and MAY also support configuration for connection to an alternative bridging port or port range.\n\n#### WebSockets and Multiple Machines\n\nAs the bridge binds its websocket on the loopback address (127.0.0.1) it cannot be connected to from another device. Hence, an instance of the standalone bridge may be run on each device and those instances exchange messages by other means in order to implement the bridge cross-device.\n\n## Bridge Connection Protocol\n\nOn connection to the bridge's websocket, a handshake must be completed that may include an authentication step before a name is assigned to the Desktop Agent for use in routing messages. The purpose of the handshake is to allow:\n\n- The Desktop Agent to confirm that it is connecting to the Desktop Agent Bridge, rather than another service exposed via a websocket.\n- The Desktop Agent Bridge to require that the Desktop Agent authenticate itself, allowing it to control access to the network of bridged Desktop Agents.\n- The Desktop Agent to request a particular name by which it will be addressed by other agents and for the bridge to assign the requested name, after confirming that no other agent is connected with that name, or a derivative of that name if it is already in use.\n\nThe bridge is ultimately responsible for assigning each Desktop Agent a name and for routing messages using those names. Desktop Agents MUST accept the name they are assigned by the bridge.\n\nExchange standardized handshake messages that identify:\n\n- That the server is a bridge, including:\n  - implementation details for logging by DA.\n  - supported FDC3 version(s).\n- That the client is an FDC3 DA, including:\n  - implementation details (ImplementationMeta returned by fdc3.getInfo() call) for logging by DA and sharing with other DAs.\n    - already includes supported FDC3 version.\n  - request for a specific agent name.\n\n```mermaid\nsequenceDiagram\n    participant DA as Desktop Agent A\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    DA -->>+ DAB: connect (step 1)\n    DAB ->>+ DA: hello (step 2)\n    DA ->>+ DAB: handshake (steps 3-5)\n    DAB ->>+ DA: connectedAgentsUpdate (step 6)\n    DAB ->>+ DB: connectedAgentsUpdate (step 6)\n    DAB ->>+ DC: connectedAgentsUpdate (step 6)\n```\n\n### Step 1. Connect to Websocket\n\nThe Desktop Agent attempts to connect to the websocket at the first port in the defined port range. If a connection cannot be made on the current port, move to the next port in the range and reattempt connection.\n\nIn the event that there are no ports remaining in the range, the Desktop Agent SHOULD reset to the beginning of the range, SHOULD pause its attempts to connect and resume later (a minimum wait period of 5 seconds SHOULD be used)\n\nNote, if the Desktop Agent is configured to run at startup (of the user's machine) it is possible that the Desktop Agent Bridge may start later (or be restarted at some point). Hence, Desktop Agents SHOULD be capable of connecting to the bridge once they are already running (rather than purely at startup).\n\n### Step 2. Hello\n\nWhen a new connection is made to the Desktop Agent Bridge websocket, it sends a `hello` message, including its metadata.\n\n```typescript\n{\n    type: \"hello\",\n    payload: {\n        desktopAgentBridgeVersion: string,\n        supportedFDC3Versions: string[],\n        authRequired: boolean,\n        /** The DAB JWT authentication token */\n        authToken?: string\n    },\n    meta: {\n        timestamp: date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/next/bridging/connectionStep2Hello.schema.json](pathname:///schemas/next/bridging/connectionStep2Hello.schema.json)\n\nA Desktop Agent can use the structure of this message to determine that it has connected to a Desktop Agent Bridge (i.e by checking `msg.type === \"hello\" && msg.payload.desktopAgentBridgeVersion`), whether it supports a compatible FDC3 version and whether it is expected to provide authentication credentials in the next step (`if(msg.payload.authRequired) { ... }`).\n\nAn optional JWT token can be included in the `hello` message to allow the connecting agent to authenticate the bridge. Verification of the supplied JWT by the DA is optional but recommended, meaning that the DA SHOULD verify the received JWT when one is included in the `hello` message.\n\nIf no hello message is received, the message doesn't match the defined format or validation of the optional JWT fails, the Desktop Agent should return to step 1 and attempt connection to the next port in the range.  \n\n### Step 3. Handshake & Authentication\n\nThe DA must then respond to the `hello` message with a `handshake` request to the bridge, including an auth token (JWT) if required.\n\n```typescript\n{\n    type:  \"handshake\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** The JWT authentication token */\n        authToken?: string,\n        /** Metadata about the Desktop Agent connecting, normally retrieved within the \n         *  context of the Desktop Agent via `fdc3.getInfo()`.*/\n        implementationMetadata: {\n          /** The version number of the FDC3 specification that the implementation\n          *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1. */\n          fdc3Version: string,\n          /** The name of the provider of the FDC3 Desktop Agent Implementation\n           *  (e.g.Finsemble, io.Connect, OpenFin etc.). */\n          provider: string,\n          /** The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0). */\n          providerVersion: string,\n          /** Metadata indicating whether the Desktop Agent implements optional features of\n           *  the Desktop Agent API. */\n          readonly optionalFeatures: {\n            /** Used to indicate whether the exposure of 'originating app metadata' for\n             *  context and intent messages is supported by the Desktop Agent.*/\n            \"OriginatingAppMetadata\": boolean;\n            /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n             *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n             *  the Desktop Agent.*/\n            \"UserChannelMembershipAPIs\": boolean;\n            /** Used to indicate whether the experimental Desktop Agent Bridging\n             *  feature is implemented by the Desktop Agent.*/\n            \"DesktopAgentBridging\": boolean;\n          }\n        },\n        /** The requested DA name */\n        requestedName: string,\n        /** The current state of the Desktop Agent's App and User channels (exclude any \n         *  Private channels), as a mapping of channel id to an array of Context objects, \n         *  one per type found in the channel, most recent first.*/\n        channelsState: Record<string, Context[]>\n    },\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/next/bridging/connectionStep3Handshake.schema.json](pathname:///schemas/next/bridging/connectionStep3Handshake.schema.json)\n\nNote that the `meta` element of of the handshake message contains both a `timestamp` field (for logging purposes) and a `requestUuid` field that should be populated with a Universally Unique Identifier (UUID), generated by the Desktop Agent. This `responseUuid` will be used to link the handshake message to a response from the Desktop Agent Bridge that assigns it a name. For more details on UUID generation see [Universally Unique Identifier](#universally-unique-identifier) section.\n\nIf requested by the server, the JWT auth token payload should take the form:\n\n```typescript\n{\n    \"sub\": string, // UUID for the key pair used to sign the token\n    \"iat\": date    // timestamp at which the the token was generated as specified in ISO 8601\n}\n```\n\ne.g.\n\n```json\n{\n    \"sub\": \"65141135-7200-47d3-9777-eb8786dd31c7\",\n    \"iat\": \"2022-07-06T10:11:43.492Z\"\n}\n```\n\nNote that the `sub` SHOULD be a UUID that does NOT need to match the name requested by the Desktop Agent. It will be used to identify the key pair that should be used to validate the JWT token. Further, multiple Desktop Agent's MAY share the same keys for authentication and hence the same `sub`, but they will be assigned different names for routing purposes by the Desktop Agent Bridge. If an agent disconnects from the bridge and later re-connects it MAY request and be assigned the same name it connected with before.\n\n### Step 4. Auth Confirmation and Name Assignment\n\nThe Desktop Agent Bridge will extract the authentication token `sub` from the JWT token's claims and then verify the token's signature against any public key it has been configured with. If the signature can't be verified, the bridge should respond with the below authentication failed message and the socket should be disconnected by the bridge.\n\n```typescript\n{\n    type:  \"authenticationFailed\",\n    payload: {\n        message: string\n    },\n    meta: {\n        /** Timestamp at which response was generated */\n        timestamp:  Date,\n        /** UUID for the handshake request */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/next/bridging/connectionStep4AuthenticationFailed.schema.json](pathname:///schemas/next/bridging/connectionStep4AuthenticationFailed.schema.json)\n\nIf authentication succeeds (or is not required), then the Desktop Agent Bridge should assign the Desktop Agent the name requested in the `handshake` message, unless another agent is already connected with that name in which case it should generate a new name which MAY be derived from the requested name. Note that the assigned name is not communicated to the connecting agent until step 6.\n\n### Step 5. Synchronize the Bridge's Channel State\n\nChannels are the main stateful mechanism in the FDC3 that we have to consider. The state of any FDC3 channel includes the most recent context broadcast on the channel, plus the most recent context of each type that has been broadcast on it (allowing applications to receive the most recent context of the type that they listen for, rather than just the most recent context of any type).\n\nA key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync. To do so, the states must be synchronized whenever a new agent connects. Hence, the Bridge MUST process the `channelState` provided by the new agent in the `handshake` request, which MUST contain details of each known User Channel or App Channel and its state (the most recent context object and the most recent context object of each type that it has received). The bridge MUST compare the received channel names and states to its own representation of the current state of channels in connected agents, merge that state with that of the new agent and communicate the updated state to all connected agents to ensure that they are synchronized with it.\n\nHence, if we assume that the state of each channel can be represented by an array of the most recent context object of each type, with the most recent context occupying the first position in the array, the Desktop Agent Bridge MUST merge the incoming `channelsState` with the `existingChannelsState` as follows:\n\n```typescript\nObject.keys(channelsState).forEach((channelId) => {\n    if (!existingChannelsState[channelId]) {\n        //unknown channels: just adopt its state\n        existingChannelsState[channelId] = channelsState[channelId];\n    } else {\n        //known channels: merge state, with existing state taking precedence\n        const currentState = existingChannelsState[channelId];\n        const incoming = channelsState[channelId];\n        incoming.forEach((context) => {\n            //only add previously unknown context types to the state\n            if (!currentState.find(element => element.type === context.type)){\n                //add to end of array to avoid setting most recent context type at the beginning\n                currentState.push(context);\n            } \n            // else ignore any types that are already known          \n        });\n    }\n});\n```\n\nWhen multiple agents attempt to connect to the Desktop Agent Bridge at the same time, steps 3-6 of the connection protocol MUST be handled by the Desktop Agent Bridge serially to ensure correct channel state synchronization.\n\n### Step 6. Connected Agents Update\n\nThe updated `existingChannelsState` will then be shared with all connected agents along with updated details of all connected agents via a `connectedAgentsUpdate` message sent to all connected sockets. The newly connected agent will receive both its assigned name and channel state via this message. The `connectedAgentsUpdate` message will be linked to the handshake request by quoting the `meta.requestUuid` of the `handshake` message.\n\nThe `connectedAgentsUpdate` message will take the form:\n\n```typescript\n{\n    type:  \"connectedAgentsUpdate\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** Should be set when an agent first connects to the bridge and provide \n         * its assigned name. */\n        addAgent?: string,\n        /** Should be set when an agent disconnects from the bridge and provide \n         * the name that no longer is assigned. */\n        removeAgent?: string,\n        /** Desktop Agent Bridge implementation metadata of all connected agents. \n         *  Note that this object is extended to include a `desktopAgent` field \n         *  with the name assigned by the DAB. */\n        allAgents: ImplementationMetadata[],\n        /** The updated state of channels that should be adopted by the agents. \n         *  SHOULD only be set when an agent is connecting to the bridge. */\n        channelsState?: Record<string, Context[]> // see step4\n    },\n    meta: {\n        /** For a new connection, should be the same as the handshake requestUuid. \n         *  Should be the same as the responseUuid for a disconnection.\n        */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n        /** Timestamp at which response was generated */\n        timestamp:  date,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/next/bridging/connectionStep6ConnectedAgentsUpdate.schema.json](pathname:///schemas/next/bridging/connectionStep6ConnectedAgentsUpdate.schema.json)\n\nWhen an agent connects to the bridge, it and other agents connected to the bridge, should adopt the state of any channels that do not currently exist or do not currently contain state of a particular type. This synchronization is NOT performed via broadcast as the context being merged would become the most recent context on the channel, when other contexts may have been broadcast subsequently. Rather, it should be adopted internally by each Desktop Agent, merging it such that it would be received by applications that have added a context listener to the channel or call `channel.getCurrentContext()` on it.\n\nIt should be noted that Desktop Agents will not have context listeners for previously unknown channels, and SHOULD simply record that channel's state for use when that channel is first used.\n\nFor known channel names, the Desktop Agents MUST also compare their current state to that which they have just received and may need to internally adopt context of types not previously seen on a channel. As context listeners can be registered for either a specific type or all types some care is necessary when doing so (as only the most recently transmitted Context should be received by un-typed listeners). Hence, the new context MUST only be passed to a context listener if it was registered specifically for that type and a context of that type did not previously exist on the channel.\n\nIn summary, updating listeners for a known channel should be performed as follows:\n\n1. The incoming channel state `channelState` for a particular channel should be processed from last to first (most recent context broadcast).\n2. If there is no current context of that type, broadcast it to any listeners of that specific type only.\n3. If there is a current context of that type, and it does not match the incoming object exactly, broadcast it to listeners of that specific type only.\n4. If the most recent (first in the incoming array) type OR value of that type doesn't match the most recent context broadcast on the channel, broadcast it to un-typed listeners only.\n\nThis procedure is the same for both previously connected and connecting agents, however, the merging procedure used by the Desktop Agent Bridge in step 5 will result in apps managed by previously connected agents only rarely receiving context broadcasts (and only for types they have not yet seen on a channel).\n\nAfter applying the `connectedAgentsUpdate` message, the newly connected Desktop Agent and other already connected agents are able to begin communicating through the bridge.\n\n#### Channels\n\nIt is assumed that Desktop Agents SHOULD adopt the recommended 8 channel set (and the respective display metadata). Desktop Agents MAY support channel customization through configuration.\n\nThe Desktop Agent Bridge MAY support channel mapping ability, to deal with issues caused by differing channel sets.\n\nA key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync, which requires an initial synchronization step as part of the connection protocol.\n\n#### Atomicity and handling concurrent operations\n\nHandling by the Desktop Agent of the synchronization message from the Desktop Agent Bridge in step 6 of the connection protocol should be atomic to prevent message overlap with `fdc3.broadcast`, `channel.broadcast`, `fdc3.addContextListener` or `channel.getCurrentContext`. I.e. the `connectedAgentsUpdate` message must be processed immediately on receipt by Desktop Agents and updates applied before any other messages are sent or responses processed.\n\nSimilarly, the Desktop Agent Bridge must process steps 3-6 of the connection protocol (receiving a `handshake` messages up to issuing the `connectedAgentsUpdate` messages to all participants) as a single atomic unit, allowing no overlap with the processing of other messages from connected agents (as they might modify the state information it is processing during those steps).\n\n#### Notification to users of connection events\n\nDesktop Agents SHOULD provide visual feedback to end users when they or other agents connect or disconnect from the Desktop Agent Bridge (i.e. whenever a `connectedAgentsUpdate` message is received, or a disconnection happens). Doing so will ensure that the end user understands whether their apps and Desktop Agent can communicate with other apps running under other Desktop Agents, and can better attribute any issues with interoperability between them to the probable source.\n\n### Step 7. Disconnects\n\nAlthough not part of the connection protocol, it should be noted that the `connectedAgentsUpdate` message sent in step 6 should also be sent whenever an agent disconnects from the bridge to update other agents. If any agents remain connected, then the `channelState` does not change and can be omitted. However, if the last agent disconnects the bridge SHOULD discard its internal `channelState`, instead of issuing the update.\n\n## Bridge Messaging Protocol\n\nIn order for Desktop Agents to communicate with the Desktop Agent Bridge and thereby other Desktop Agents, a messaging protocol is required. FDC3 supports both 'fire and forget' interactions (such as the broadcast of context messages) and interactions with specific responses (such as raising intents and returning a resolution and optional result), both of which must be handled by that messaging protocol and message formats it defines, as described in this section.\n\n### Collating Responses\n\nWhilst some FDC3 requests are 'fire and forget' (e.g. broadcast) the main requests such as `findIntent` or `raiseIntent` expect a response. In a bridging scenario, the response can come from multiple Desktop Agents and therefore need to be aggregated and augmented before they are sent back to the requesting DA.\n\n:::note\nA set of classifications for message exchange types are provided in the [Individual message exchanges](#individual-message-exchanges) section.\n:::\n\nThe Desktop Agent Bridge is the responsible entity for collating responses together from all DAs. Whilst this approach may add some complexity to bridge implementations, it will simplify DA implementations since they only need to handle one response.\n\nThe Desktop Agent Bridge MUST allow for timeout configuration.\n\nThe Bridge SHOULD also implement timeout for waiting on DA responses. Assuming the message exchange will be all intra-machine, a recommended maximum timeout of 1500ms SHOULD be used. Similarly, Desktop Agents SHOULD apply a timeout to requests made to the bridge that require a response (collated or otherwise), to handle situations where the bridge is not responding as expected. A recommended maximum timeout of 3000ms SHOULD be used in this case.\n\n### Message Format\n\nAll messages sent or received by the Desktop Agent Bridge will be encoded in JSON and will have the same basic structure (including those already defined in the connection protocol):\n\n```typescript\n{\n    /** Identifier used to declare what aspect of FDC3 that the message relates to. */\n    type:  string,\n    /** Request body, containing any the arguments to the FDC3 interactions. */\n    payload: { ... },\n    /** Metadata relating to the message, its sender and destination. */\n    meta: { ... }\n}\n```\n\nMessages can be divided into four categories:\n\n- Requests from a Desktop Agent: Messages that initiate a particular interaction.\n- Requests forwarded by the Bridge: Messages augmented and forwarded on by the Bridge.\n- Responses from a Desktop Agent: Messages from a single Desktop Agent that respond to a prior request from the Bridge.\n- Responses collated and forwarded by the Bridge: Messages from the Bridge back to the Desktop Agent that initiated an interaction, which may combine the responses from multiple other Desktop Agents.\n\nDetails specific to each are provided in the following sections.\n\n#### Request Messages\n\nRequest messages from a Desktop Agent use the following format:\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the FDC3\n     * function name that the message relates to, e.g. 'findIntent', with \n     * 'Request' appended. */\n    type:  string,\n    /** Request body, typically containing the arguments to the function called.*/\n    payload: {\n        /** Used to indicate which channel `broadcast` functions were called on.*/\n        channelId?: string,\n        /** Used as an argument to `findIntent` and `raiseIntent` functions.`*/\n        intent?: string,\n        /** Used as an argument to `broadcast`, `findIntent` and `raiseIntent` \n         * functions.*/\n        context?: Context,\n        /** Used as an argument to `open`, `raiseIntent`, `getAppMetadata`, and \n         * `findInstances` functions.*/\n        app?: AppIdentifier,\n        /** Used as an argument to `findIntent` functions. */\n        resultType?: string,\n        /** Context type name used in Private Channel event messages. */\n        contextType?: string\n    },\n    /** Metadata used to uniquely identify the message and its sender. */\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date,\n         /** Field that represents the source application that the request was \n          * received from, or the source Desktop Agent if it issued the request \n          * itself. */\n        source: AppIdentifier | DesktopAgentIdentifier,\n        /** Optional field that represents the destination that the request\n         * should be routed to. Must be set by the Desktop Agent for API calls\n         * that include a target app parameter and must include the name of the\n         * Desktop Agent hosting the target application. */\n        destination?: AppIdentifier | DesktopAgentIdentifier\n    }\n}\n```\n\n**Request Schema**: [https://fdc3.finos.org/schemas/next/bridging/agentRequest.schema.json](pathname:///schemas/next/bridging/agentRequest.schema.json)\n\nIf the FDC3 API call underlying the request message includes a target (typically defined by an `app` argument, in the form of an AppIdentifier object) it is the responsibility of the Desktop Agent to copy that argument into the `meta.destination` field of the message and to ensure that it includes a `meta.destination.desktopAgent` value. If the target is provided in the FDC3 API call, but without a `meta.destination.desktopAgent` value, the Desktop Agent should assume that the call relates to a local application and does not need to send it to the bridge.\n\nRequests without a `meta.destination` field will be forwarded to all other agents by the bridge, which will also handle the collation of responses which quote the `meta.requestUuid`.\n\n##### Request Messages Forwarded by the Bridge\n\nRequest messages forwarded by the Bridge onto other Desktop Agents use the same format as incoming requests from Desktop Agents, with the exception that the `desktopAgent` properties of the `meta.source` field MUST be provided, and should be overwritten by the Bridge (based on the connection that the message was received from) to prevent spoofing of request message origins.\n\n**Bridge Request Schema**: [https://fdc3.finos.org/schemas/next/bridging/bridgeRequest.schema.json](pathname:///schemas/next/bridging/bridgeRequest.schema.json)\n\n#### Response Messages\n\nResponse messages from a Desktop Agent back to the Bridge use a similar format that is differentiated from requests by the presence of a `meta.responseUuid` field. They MUST also quote the `meta.requestUuid` that they are responding to.\n\n:::info\nResponse messages do not include a `meta.destination` as the routing of responses is handled by the Bridge via the `meta.requestUuid` field. They also do not include a `source` field as responses are currently always from the Desktop Agent, and the bridge is required to provide this information itself to prevent spoofing.\n:::\n\nThere are two types of each response message, a successful response and an error response.\n\n##### Successful Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/next/bridging/agentResponse.schema.json](pathname:///schemas/next/bridging/agentResponse.schema.json)\n\n##### Error Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error strings from an appropriate FDC3 API Error \n         *  enumeration. */\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/next/bridging/agentErrorResponse.schema.json](pathname:///schemas/next/bridging/agentErrorResponse.schema.json)\n\n##### Response Messages Collated and Forwarded by the Bridge\n\nResponses from individual Desktop Agents are collated by the Bridge and are forwarded on to the the Desktop Agent that initiated the interaction. The format used is very similar to that used for responses by the Desktop Agents, with the exception of the source information in the `meta` field. Specifically, the `meta.source` field does not need to be provided by agents, as responses are currently always provided by the Desktop Agent, whose details will be provided by the bridge when it receives the response. In responses from the bridge, the `meta.source` is replaced by two arrays, `meta.sources` and `meta.errorSources`, which provide details on the Desktop Agents that responded normally or responded with errors. The detail of any errors returned (in the `payload.error` field of a Desktop Agent's response) is collected up into a `meta.errorDetails` field. Moving the error details from the `payload` to the `meta` field enables the return of a valid response to the originating Desktop Agent in cases where some agents produced valid responses, and others produced errors.\n\nHence, for responses forwarded by the bridge there are two type of response messages from the Bridge returned to agents, one for requests that received at least one successful response, and another for use when all agents (or the targeted agent) returned an error.\n\n##### At Least One Successful Response\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for the sources\n         * that generated responses to the request. Will contain a single value\n         * for individual responses and multiple values for responses that were\n         * collated by the bridge. May be omitted if all sources errored. MUST\n         * include the `desktopAgent` field when returned by the bridge. */\n        sources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. May be omitted if all sources responded. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/next/bridging/bridgeResponse.schema.json](pathname:///schemas/next/bridging/bridgeResponse.schema.json)\n\n##### All Responses are Errors\n\n:::info\nIn this case there are no successful responses and the bridge must populate the `payload.error` field in the response to the agent with one of the error messages returned, so that the receiving Desktop Agent may return it to the app that made the original call.\n:::\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error string from an appropriate FDC3 API Error \n         *  enumeration. This should also appear in `meta.errorDetails`.*/\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/next/bridging/bridgeErrorResponse.schema.json](pathname:///schemas/next/bridging/bridgeErrorResponse.schema.json)\n\n### Identifying Individual Messages\n\nThere are a variety of message types that need to be sent between bridged Desktop Agents, several of which will need to be replied to specifically (e.g. a `fdc3.raiseIntent` call should receive an `IntentResolution` when an app has been chosen, and may subsequently receive an `IntentResult` after the intent handler has run). Hence, messages also need a unique identity, which should be generated at the Desktop Agent that is the source of that message, in the form of a Universally Unique Identifier (UUID). Response messages will include the identity of the request message they are related to, allowing multiple message exchanges to be 'in-flight' at the same time.\n\nHence, whenever a request message is generated by a Desktop Agent it should contain a unique `meta.requestUuid` value. Response messages should quote that same value in the `meta.requestUuid` field and generate a further unique identity for their response, which is included in the `meta.responseUuid` field. Where a response is collated by the Desktop Agent Bridge, the Bridge should generate its own `meta.responseUuid` for the collated response message.\n\nDesktop Agent Bridge implementations should consider request messages that omit `meta.requestUuid` and response messages that omit either `meta.requestUuid` or `meta.responseUuid` to be invalid and should discard them.\n\n#### Universally Unique Identifier\n\nA UUID (Universally Unique IDentifier), also known as a Globally Unique IDentifier (GUID), is a generated 128-bit text string that is intended to be 'unique across space and time', as defined in [IETF RFC 4122](https://www.ietf.org/rfc/rfc4122.txt).  \n\nThere are several types of UUIDs, which vary how they are generated. As Desktop Agents will typically be running on the same machine, system clock and hardware details may not provide sufficient uniqueness in UUIDs generated (including during the connect step, where Desktop Agent name collisions may exist). Hence, it is recommended that both Desktop Agents and Desktop Agent Bridges SHOULD use a version 4 generation type (random).\n\n### Identifying Desktop Agents Identity and Message Sources\n\nDesktop Agents will prepare messages in the above format and transmit them to the bridge. However, to target intents and perform other actions that require specific routing between DAs, DAs need to have an identity. Identities should be assigned to Desktop Agents when they connect to the bridge. This allows for multiple copies of the same underlying Desktop Agent implementation to be bridged and ensures that identity clashes can be avoided.\n\nTo facilitate routing of messages between agents, the `AppIdentifier` is expanded to contain an optional `desktopAgent` field:\n\n```typescript\ninterface AppIdentifier {\n  readonly appId: string;\n  readonly instanceId?: string;\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental Introduced in FDC3 2.1 and may be refined by further changes\n   *  outside the normal FDC3 versioning policy.\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\nFurther, a new `DesktopAgentIdentifier` type is introduced to handle cases where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. This is particularly relevant for `findIntent` message exchanges:\n\n```typescript\n/** @experimental Introduced in FDC3 2.1 and may be refined by further changes\n *  outside the normal FDC3 versioning policy. */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent. */ \n  readonly desktopAgent: string;\n}\n```\n\nHence, either an `AppIdentifier` or `DesktopAgentIdentifier` is used as the `meta.source` value of both request or response messages and the source Desktop Agent identity for bridging messages will always be found at `meta.source.desktopAgent`. To prevent spoofing and to simplify the implementation of clients, the source Desktop Agent identity MUST be added to (or overwritten in) each message by the bridge when received.\n\nA request message may include a `destination` field, set by the source Desktop Agent if the message is intended for a particular Desktop Agent (e.g. to support a `raiseIntent` call with a specified target app or app instance on a particular Desktop Agent).\n\nResponse messages do not include a `destination` field. Instead, a Desktop Agent Bridge implementation MUST retain a record of `requestUuid` fields for request message, until the request is fully resolved, allowing them to determine the destination for the collated responses and effectively enforcing the routing policy for interactions.\n\nFurther, the Desktop Agent Bridge should also inspect the `payload` of both request and response messages and ensure that any `AppIdentifier` objects have been augmented with the correct `desktopAgent` value for the app's host Desktop Agent (e.g. if returning responses to `findIntent`, ensure each `AppIntent.apps[]` entry includes the correct `desktopAgent` value). Further details of any such augmentation are provided in the description of each message exchange.\n\n### Handling of Error Responses\n\nThe FDC3 Desktop Agent API specifies a number of error enumerations that define specific error strings that should be used as the `message` element of a JavaScript `Error` to be returned to the requesting application via a rejected promise. In the event that an Error must be returned by a Desktop Agent to the Desktop Agent Bridge, the message should be selected from the [Error enumeration](../api/ref/Errors) normally used by the corresponding FDC3 function (i.e. `OpenError` for `open` calls, `ResolveError` for `findIntent` and `raiseIntent` etc.). However, Desktop Agent Bridging does NOT require that an `Error` object is returned across the bridge as it cannot be fully recreated from its constituent fields in JavaScript. Rather, return only the specified message string in the `error` field of the `payload`, which should then be used to initialize a JavaScript `Error` on the receiving end. It is also advisable to output additional logging (in the Desktop Agent Bridge) indicating that the error was originally generated by a remote Desktop Agent and to provide the relevant details.\n\nFor example, a `raiseIntent` targeted at an app instance that no longer exists might generate the following response from the Desktop Agent:\n\n```json\n// e.g. agent-B -> DAB in response to a raiseIntent call\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"error\": \"TargetInstanceUnavailable\", //<error string from the relevant error enum\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nFor messages that target a specific agent, the Desktop Agent Bridge will augment the message with source information and return it to the calling agent, which will then respond to the app that made the original request.\n\nIf all agents (or the targeted agent) return errors, then a suitable error string should be forwarded in the `payload.error` field as returned by at least one of the agents. This allows the agent that made the original request to return that error to the app that made the original API call. All agents that returned errors should be listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`).\n\nHowever, API calls that require a collated response from all agents where at least one agent returns a successful response, will result in a successful response from the Desktop Agent Bridge (i.e. no `error` element should be included), with the agents returning errors listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`). This allows for successful exchanges on API calls such as `fdc3.findIntent` where some agents do not have options to return and would normally respond with (for example) `ResolveError.NoAppsFound`.\n\nFinally, to facilitate easier debugging, errors specific to Desktop Agent Bridge are added to the Error enumerations, including:\n\n```typescript\nenum OpenError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n\nenum ResolveError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n```\n\nAnd an error enumeration is created for errors related to bridging that may occur on any request, and are returnable through the FDC3 API.\n\n```typescript\nenum BridgingError {\n  /** Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging,\n   * within the allotted timeout. */\n  ResponseTimedOut = 'ResponseToBridgeTimedOut',\n  /** Returned if a Desktop Agent that has been targeted by a particular request has\n   * been disconnected from the Bridge before a response has been received from it. */\n  AgentDisconnected = 'AgentDisconnected',\n  /** Returned for FDC3 API calls that are specified with arguments indicating that\n   *  a remote Desktop Agent should be targeted (e.g. raiseIntent with an app on a\n   *  remote DesktopAgent targeted), when the local Desktop Agent is not connected to\n   *  a bridge. */\n  NotConnectedToBridge = 'NotConnectedToBridge',\n  /** Returned if a message to a Bridge deviates from the schema for that message\n   * sufficiently that it could not be processed.\n   */\n  MalformedMessage = 'MalformedMessage'\n}\n```\n\n### Handling Malformed Messages\n\nIt is the Bridge's responsibility to validate all messages that flow to and from Desktop Agents. When a request message is malformed the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` error to the sender.  For 'request only' message exchanges, no specific error response schema is provided. Hence, the generic [Bridge Error Response Message schema](#all-responses-are-errors) should be used for such messages (with the type set to match the request message type).\n\nWhere responses to requests from other agents are malformed, the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` to the sender and record `BridgingError.MalformedMessage` as the error response from the responder that sent the malformed message.\n\n### Forwarding of Messages and Collating Responses\n\nWhen handling request messages, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive request messages from connected Desktop Agents.\n- Augment request messages with `meta.source.desktopAgent` information (as described above).\n- Forward request messages onto either a specific Desktop Agent or all other Desktop Agents.\n  - The bridge MUST NOT forward the request to the agent that sent the request, nor expect a reply from it.\n\nFor message exchanges that involve responses, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive and collate response messages (where necessary) according the `meta.requestUuid` (allowing multiple message exchanges to be 'in-flight' at once).\n- Augment response messages with `meta.source.desktopAgent` information (as described above).\n- Apply a timeout to the receipt of response messages for each request.\n- Produce a single collated response message (where necessary) that incorporates the output of each individual response received and has its own unique `meta.responseUuid` value.\n- Deliver the collated and/or augmented response message to the source Desktop Agent that sent the request.\n\nCollated response messages generated by the bridge use the same format as individual response messages.\n\nThe following pseudo-code defines how messages should be forwarded or collated by the bridge:\n\n- **if** the message is a request (`meta.requestUuid` is set, but `meta.responseUuid` is not),\n  - **if** the message includes a `meta.destination` field,\n    - forward it to the specified destination agent,\n    - annotate the request as requiring only a response from the specified agent,\n    - await the response or the specified timeout.\n  - **else**\n    - forward it to all other Desktop Agents (not including the source),\n    - annotate the request as requiring responses from all other connected agents,\n    - await responses or the specified timeout.\n- **else if** the message is a response (both `meta.requestUuid` and `meta.responseUuid` are set)\n  - **if** the `meta.requestUuid` is known,\n    - augment any `AppIdentifier` types in the response message with a `desktopAgent` field matching that of the responding Desktop Agent,\n    - **if** `payload.error` is set in the response add the DesktopAgentIdentifier to the `meta.errorSources` element.\n    - **else**\n      - add the DesktopAgentIdentifier to the `meta.sources` element.\n    - **if** the message exchange requires collation,\n      - add the message to the collated responses for the request,\n      - **if** all expected responses have been received (i.e. all connected agents or the specified agent has responded, as appropriate),\n        - produce the collated response message and return to the requesting Desktop Agent.\n      - **else**\n        - await the configured response timeout or further responses,\n        - **if** the timeout is reached without any responses being received\n          - produce and return an appropriate [error response](../api/ref/Errors), including details of all Desktop Agents in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n        - **else if** the timeout is reached with a partial set of responses,\n          - produce and return, to requesting Desktop Agent, a collated response and include details of Desktop Agents that timed out in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n    - **else**\n      - forward the response message on to requesting Desktop Agent.\n  - **else**\n    - discard the response message (as it is a delayed to a request that has timed out or is otherwise invalid).\n- **else**\n  - the message is invalid and should be discarded.\n\n### Workflows Broken By Disconnects\n\nTargeted request and request/response workflows may be broken when a Desktop Agent disconnects from the bridge, which bridge implementations will need to handle.\n\nThree types of requests:\n\n1. Fire and forget (i.e. `broadcast`).\n2. Requests that require the bridge to collate multiple responses from the bridged Desktop Agents (e.g. `findIntent`).\n3. Requests targeted at a specific Desktop Agent that are forwarded to the target Desktop Agent (e.g. `raiseIntent`).\n\nThe latter two types embody workflows that may be broken by an agent disconnecting from the bridge either before or during the processing of the request.\n\nWhen processing the disconnection of an agent from the bridge, the bridge MUST examine requests currently 'in-flight' and:\n\n- For requests that require the bridge to collate multiple responses:\n  - add the disconnected Desktop Agent's details to the `errorSources` array in the response and the `BridgingError.AgentDisconnected` message to the `errorDetails` array.\n  - complete requests that no longer require further responses (all other agents have responded), or\n  - continue to await the timeout (if other agents are yet to respond), or\n  - return an 'empty' response in the expected format (if no other agents are connected and no data will be received).\n- For requests that target a specific agent:\n  - return the `BridgingError.AgentDisconnected` in the response's `payload.error` field (as the request cannot be completed).\n\nFinally, in the event that either a Desktop Agent or the bridge itself stops responding, but doesn't fully disconnect, the timeouts (specified earlier in this document) will be used to handle the request as if a disconnection had occurred.\n\nIn the event that a Desktop Agent repeatedly times out, the bridge SHOULD disconnect that agent (and update other agents via the `connectedAgentsUpdate` message specified in the connection protocol), to avoid all requests requiring the full timeout to complete.\n\nIn the event that the bridge repeatedly times out, connected Desktop Agents MAY disconnect from the bridge and attempt to reconnect by returning to Step 1 of the connection protocol.\n\n### Fully-Qualified AppIds\n\nThe FDC3 Standard allows appIds to be fully-qualified with the domain of the app directory that their details were loaded from, see the [API specification](../api/spec#fully-qualified-appids) for details of how the resolution of unqualified and fully-qualified appIds should be handled in the API. \n\nThere are only two types of API calls where `appId` resolution matters to the Bridging specification:\n\n- `fdc3.open`: For `open` to apply to a remote agent across the bridge, the agent has to be specified in the `AppIdentifier` (via the `DesktopAgent` field that is only used for bridging).\n  - If an `appId` provided as an argument to `open` cannot be matched as provided, then the receiving agent should apply the same resolution logic defined in the API standard in order to match unqualified and fully-qualified appIds. If a match is not found then the agent should respond with the `AppNotFound` from the `OpenError` enumeration.\n- `fdc3.raiseIntent`/`fdc3.raiseIntentForContext`: For `raiseIntent` calls to apply to a remote agent across the bridge, the agent has to be specified in the `AppIdentifier` (via the `DesktopAgent` field that is only used for bridging).\n  - If an `appId` provided as an argument cannot be matched as provided, then the receiving agent should apply the same resolution logic defined in the API standard in order to match unqualified and fully-qualified appIds. If a match is not found then the agent should respond with the `TargettedAppUnavailable` from the `ResolveError` enumeration.\n  - If no `appId` was specified, the `findIntent`/`findIntentForContext` exchanges are used to retrieve options from other agents. The Desktop Agent that raised the intent should select an option (involving the user via an intent resolver if it needs to) and then re-raise the intent with the selected option as the target. As it will be specifying exactly the `appId` (and `instanceId` if applicable) that was provided by the host agent, no resolution should be needed.\n\n### Individual message exchanges\n\nIndividual message exchanges are defined for each of the Desktop Agent methods that require bridging in the reference section of this Part.\n\nEach section assumes that we have 3 agents connected by a bridge (itself denoted by `DAB` in diagrams):\n\n- agent-A (denoted by `DA A` in diagrams)\n- agent-B (denoted by `DA A` in diagrams)\n- agent-C (denoted by `DA A` in diagrams)\n\nMessage exchanges come in a number of formats, which are known as:\n\n- **Request only**: A request message that does not require a response ('fire and forget'), such as a [`broadcast`](ref/broadcast).\n- **Request Response (single)**: A request message that expects a single response from a single Desktop Agent, such as `open` or `getAppMetadata`.\n- **Request Response (collated)**: A request message that expects responses from all other Desktop Agents that are collated by the bridge and returned as a single response to the requestor, such as `findIntent` or `findInstances`.\n- **Request Multiple Response (single)**: A request message that expects multiple responses from a single Desktop Agent, such as `raiseIntent`.\n\nThe message exchanges defined are:\n\n- [`broadcast`](ref/broadcast)\n- [`findInstances`](ref/findInstances)\n- [`findIntent`](ref/findIntent)\n- [`findIntentsByContext`](ref/findIntentsByContext)\n- [`getAppMetadata`](ref/getAppMetadata)\n- [`open`](ref/open)\n- [`raiseIntent`](ref/raiseIntent)\n- [`PrivateChannel.broadcast`](ref/PrivateChannel.broadcast)\n- [`PrivateChannel.eventListenerAdded`](ref/PrivateChannel.eventListenerAdded)\n- [`PrivateChannel.eventListenerRemoved`](ref/PrivateChannel.eventListenerRemoved)\n- [`PrivateChannel.onAddContextListener`](ref/PrivateChannel.onAddContextListener)\n- [`PrivateChannel.onUnsubscribe`](ref/PrivateChannel.onUnsubscribe)\n- [`PrivateChannel.onDisconnect`](ref/PrivateChannel.onDisconnect)\n\n#### PrivateChannels\n\n`PrivateChannels` are intended to provide a private communication channel for applications. In order to do so, there are differences in how their broadcasts and event messages (used to manage the channel's lifecycle) MUST be handled.\n\nBroadcasts and event messages should be addressed to the Desktop Agent that created the channel, which will route it to the relevant application and any other listeners. If any of those listeners are remote, the message should be repeated back to the bridge, once for each listener with the destination set as a full `AppIdentifier`. Both these messages and broadcast messages MUST NOT be repeated back to the application that generated them. The source information on repeated messages should be unmodified to ensure that the message is attributed to the original source.\n\nTo facilitate the addressing of messages to the relevant Desktop Agent and `AppIdentifier` some additional tracking of private channel metadata is necessary in each Desktop Agent (or Desktop Agent Bridge Client implementation). For applications receiving a private channel as an `IntentResult`, the `AppIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id. This data MUST be retained until the receiving application sends a `disconnect` message, after which it can be discarded. For applications that have created and returned a private channel, and have subsequently received event messages subscriptions (`onAddContextListener`, `onSubscribe`, `onDisconnect`) the `appIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id and listener type, which will facilitate repeating of messages to registered listeners. This data MUST be retained until the remote application sends a `disconnect` message or a message indicating that the listener has been removed.\n\n#### FDC3 API calls that do NOT generate bridge messages\n\nSome FDC3 API calls can be handled locally and do not need to generate request messages to the Desktop Agent Bridge, but are likely to be involved in other exchanges that do generate messages to the bridge (for example adding context or intent handlers). Those calls include:\n\n- `addContextListener` functions (excluding those for `PrivateChannel` instances)\n- `listener.unsubscribe` (excluding those for `PrivateChannel` instances)\n- `addIntentListener`\n- `getOrCreateChannel`\n- `createPrivateChannel`\n- `getUserChannels` and `getSystemChannels`\n- `joinUserChannel` and `joinChannel`\n- `getCurrentChannel`\n- `leaveCurrentChannel`\n- `getInfo`\n\nHowever, `PrivateChannel` instances allow the registration of additional event handlers (for the addition or removal of context listeners) that may be used to manage streaming data sent over them by starting or stopping the stream in response to those events. Hence, the following calls DO generate request messages when used on a PrivateChannel instance:\n\n- `addContextListener`\n- `listener.unsubscribe`\n- `disconnect`\n\n#### Message Schemas and generated sources\n\nJSONSchema definitions are provided for all Desktop Agent Bridging message exchanges defined by the Bridge Messaging Protocol (see links in each reference page), which may be used to validate the correct generation of messages to or from a bridge (a separate schema is provided for the agent and bridge versions of each message).\n\nThe JSONSchema definitions are also used to generate TypeScript interfaces for the messages to aid in implementation of a Desktop Agent Bridge or client library. These may be imported from the FDC3 npm module:\n\n```typescript\nimport { BridgingTypes } from \"@finos/fdc3\";\nconst aMessage: BridgingTypes.BroadcastAgentRequest\n```\n\nor\n\n```typescript\nimport { BroadcastAgentRequest } from \"@finos/fdc3/dist/bridging/BridgingTypes\";\nconst aMessage: BroadcastAgentRequest\n```\n\nSources may also be generated from the JSONSchema files for other languages.\n"
  },
  {
    "path": "website/docs/api/conformance/App-Channel-Tests.md",
    "content": "---\nid: App-Channel-Tests\nsidebar_label: App Channel Tests\ntitle: App Channel Tests\nhide_title: true\n---\n\n# App Channel Tests  \n<!-- markdownlint-disable MD033 -->\n\n## Basic Broadcast\n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add an _untyped_ context listener to the channel, using: <br /> !`await testChannel.addContextListener(null,handler)` |\n| B   | 3. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4. Broadcast            | Broadcast an `fdc3.instrument` Context to the channel with: <br />`testChannel.broadcast(<fdc3.instrument>)`|\n| A   | 5. Receive Context      | The handler added in step 2 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- `ACBasicUsage1` Perform above test.\n\n## Current Context\n\n| App | Step                        | Details                                                                    |\n|-----|-----------------------------|----------------------------------------------------------------------------|\n| B   | 1. Retrieve `Channel`       |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2. Broadcast                | Broadcast an `fdc3.instrument` to the channel using: <br />`testChannel.broadcast(<fdc3.instrument>)`|\n| A   | 3. Retrieve `Channel`       |Retrieve a `Channel` object representing the same 'App' channel B did (`test-channel`)|\n| A   | 4. Retrieve Current Context | A gets the _current context_ of the user channel. via:  `await testChannel.getCurrentContext()` <br />Ensure that the instrument received by A is identical to that sent by B    |\n\n- `ACBasicUsage2` Perform above test\n\n## Filtered Context\n\n| App | Step                    | Details                                                         |\n|-----|-------------------------|-----------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add an _typed_ context listener for `fdc3.instrument`, using: <br />`await testChannel.addContextListener(\"fdc3.instrument\",handler)`|\n| B   | 3. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4. Broadcast            | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)`|\n| A   | 5. Receive Context      | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received.                                                                   |\n\n- `ACFilteredContext1`: Perform above test.\n- `ACFilteredContext2`: Perform above test, but add listeners for both `fdc3.instrument` and `fdc3.contact` in step2.  Ensure that both context objects are received.\n- `ACFilteredContext3`: Perform above test, except creating a _different_ channel in app B. Check that you _don't_ receive anything (as the channels don't match).\n- `ACFilteredContext4`: Perform above test, except that after creating the channel **A** creates another channel with a further _different_ channel id and adds a further context listener to it.  Ensure that **A** is still able to receive context on the first channel (i.e. it is unaffected by the additional channel) and does NOT receive anything on the second channel.\n- `ACUnsubscribe`: Perform above test, except that after creating the channel **A** then `unsubscribe()`s the listener it added to the channel. Check that **A** does NOT receive anything.\n\n### App Channel History\n\n| App | Step                        | Details                                                 |\n|-----|-----------------------------|---------------------------------------------------------|\n| A   | 1. Retrieve `Channel`       | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2. Retrieve `Channel`       | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 3. Broadcast                | B broadcasts both the instrument context and a contact context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)` |\n| A   | 4. Add Context Listener     | A adds a context listener to the channel _after_ B has completed all its broadcasts, via: <br />`await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br /> Ensure that A does NOT receive any context via these listeners (past context is only retrieved via a `getCurrentContext()` call on App channels). |\n| A   | 5. Retrieve Current Context | A is able to retrieve the most recent context of each context type from the `Channel`  via: <br />`const instrument = await testChannel.getCurrentContext(\"fdc3.instrument\")`<br />`const contact = await testChannel.getCurrentContext(\"fdc3.contact\")`<br />Ensure that both contexts retrieved by A are identical to those sent by B|\n\n- `ACContextHistoryTyped`: Perform above test.\n- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types.  Ensure that only the last version of each type is received by **A**.\n- `ACContextHistoryLast`: In step 5. **A** retrieves the _untyped_ current context of the channel via `const currentContext = await testChannel.getCurrentContext()`. Ensure that A receives only the very last broadcast context item _of any type_.\n\n## Basic Broadcast - Destructured\n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Destructure Methods  | Destructure channel methods using: <br />`const { addContextListener, broadcast } = testChannel` |\n| A   | 3. Add Context Listener | Add an _untyped_ context listener to the channel, using destructured method: <br />`await addContextListener(null,handler)` |\n| B   | 4. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 5. Destructure & Broadcast | Destructure broadcast method and broadcast context: <br />`const { broadcast } = testChannel`<br />`broadcast(<fdc3.instrument>)`|\n| A   | 6. Receive Context      | The handler added in step 3 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- `ACBasicUsage1-Destructured` Perform above test to verify destructured methods work correctly.\n\n## Current Context - Destructured\n\n| App | Step                        | Details                                                                    |\n|-----|-----------------------------|----------------------------------------------------------------------------|\n| B   | 1. Retrieve `Channel`       |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2. Destructure & Broadcast  | Destructure broadcast method and broadcast context: <br />`const { broadcast } = testChannel`<br />`broadcast(<fdc3.instrument>)`|\n| A   | 3. Retrieve `Channel`       |Retrieve a `Channel` object representing the same 'App' channel B did (`test-channel`)|\n| A   | 4. Destructured & Get Context | Destructure getCurrentContext and retrieve context: <br />`const { getCurrentContext } = testChannel`<br />`await getCurrentContext()` <br />Ensure that the instrument received by A is identical to that sent by B    |\n\n- `ACBasicUsage2-Destructured` Perform above test to verify destructured getCurrentContext works correctly.\n\n## Clearing Context\n\n| App | Step                    | Details                                                         |\n|-----|-------------------------|-----------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add a _typed_ context listener for `fdc3.instrument`, using: <br />`await testChannel.addContextListener(\"fdc3.instrument\",handler)`|\n| B   | 3. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4. Broadcast            | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)`|\n| A   | 5. Receive Context      | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received.                                                                   |\n| A   | 6. Add Event Listener   | Add an event listener for `contextCleared` event, using: <br />`await testChannel.addEventListener(\"contextCleared\",handler)`  |\n| B   | 7. Clear Context        | B clears context using `testChannel.clearContext()`|\n| A   | 8. Received Event       | A receives event added in step 6 |\n\n- `ACClearContext1`: Perform above test.\n- `ACClearContext2`: Perform above test, but add specific type of the context type to the `testChannel.clearContext()`.\n\n\n## Multiple listeners On The Same Or Overlapping Context types  \n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add an _untyped_ context listener to the channel, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(null, handler1)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(null, handler1)` |\n| A   | 3. Add Context Listener | Add a _typed_ context listener for `fdc3.instrument` with a different handler, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(\"fdc3.instrument\", handler2)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(\"fdc3.instrument\", handler2)`|\n| B   | 4. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 5. Broadcast            | Broadcast an `fdc3.instrument` Context to the channel with: <br/>`testChannel.broadcast(<fdc3.instrument context>)`|\n| A   | 6. Receive Context      | The handlers added in step 2 and 3 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- ACMultipleOverlappingListeners1: Perform above test\n- ACMultipleOverlappingListeners2: Perform above test, but instead of _untyped_ context listener, in step 2, use `fdc3.instrument` (handler should remain different)\n\n"
  },
  {
    "path": "website/docs/api/conformance/Basic-Tests.md",
    "content": "---\nid: Basic-Tests\nsidebar_label: Basic Tests\ntitle: Basic Tests\nhide_title: true\n---\n\n# Basic Tests\n<!-- markdownlint-disable MD033 -->\n\n_These are some basic sanity tests implemented in the FDC3 Conformance Framework.  It is expected that Desktop Agent testers will run these first before commencing the much more thorough tests in section 2 onwards._\n\n## Connection\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface was introduced to support Browser-based FDC3 Desktop Agents, known as a 'Desktop Agent Proxy', and a new [`getAgent`](../ref/GetAgent) API call was introduced to all apps to retrieve the Desktop Agent API via that interface or the existing 'Desktop Agent Preload' interface. This test pack checks that the a connection is made correctly via `getAgent`.\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | `getAgent`      | App A calls `getAgent` and waits for the promise to resolve to a `DesktopAgent` instance. |\n| A   | `getInfo`       | App A can call the `getInfo()` method on the `DesktopAgent` instance to get the `ImplementationMetadata` object. <br /> Check that fdc3Version is set to 2.x.  <br />Check that provider and providerVersion are populated. |\n| A   | `getUserChannels`| App A can call the `getUserChannels()` method on the `DesktopAgent` instance to get the `Channel` objects representing the system channels.<br />Check **user** channels are returned.|\n\n- `GetAgentAPI`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n\n## Basic API Usage\n\n- `BasicCL1`: A context listener can be created for a specific context type by calling `fdc3.addContextListener(\"fdc3.contact\",<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicCL2`: An **unfiltered** context listener can be created by calling `fdc3.addContextListener(null,<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicIL1`: An intent listener can be created for a specific intent by calling `fdc3.addIntentListener(<intentName>,<handler>)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicGI1`: An `ImplementationMetadata` object can be retrieved, to find out the version of FDC3 that is in use along with details of the provider, by calling:\n  - `await fdc3.getInfo()`. The FDC3 version should match the API version being tested for conformance.\n- `BasicAC1`: A named 'App' channel can be retrieved by calling `fdc3.getOrCreateChannel(<name>)`. The `Channel` object returned conforms to the defined interface.\n- `BasicUC1`: The list available user/system channels can be retrieved, as an array of `Channel` Objects conforming to the defined interface, by calling `await fdc3.getUserChannels()`.\n- `BasicJC1`: A user/system channel can be joined with the with the channel's id by calling `fdc3.joinUserChannel(<channelId>)`.  Having done so, the current channel, retrieved by calling `fdc3.getCurrentChannel()` should NOT be null and should match _the channel id given_.  After leaving the current channel by calling `fdc3.leaveCurrentChannel()`, it should go back to being `null`.\n- `BasicRI1`: A specified intent can be raised by invoking `fdc3.raiseIntent(<intent name>, <context>)`. A promise should be returned.\n- `BasicRI2`: An intent can be raised for some item of context by invoking: `fdc3.raiseIntentForContext(<context>)`. A promise should be returned.\n"
  },
  {
    "path": "website/docs/api/conformance/Intents-Tests.md",
    "content": "---\nid: Intents-Tests\nsidebar_label: Intents Tests\ntitle: Intents Tests\nhide_title: true\n---\n\n# Intents Tests\n<!-- markdownlint-disable MD033 -->\n\n_Please note that API calls (and associated test cases) relating to API calls based on the `name` property of an appD record (used to specify a target application) were deprecated in FDC3 2.0 in favour of those based on `AppIdentifier`. Hence, those API calls have become optional and test cases related to them have been removed._\n\n## Setup\n\nWe assume 6 context types in the below tests (and associated AppD records):\n\n- `testContextX`\n- `testContextY`\n- `testContextZ`\n- `nonExistentContext` (context object with a unique type that does NOT appear in any of the apps (metadata or otherwise).\n- `privateChannelDetails`\n- `privateChannelIsPrivateResult`\n\nThese may be used in a test as a context object `{ \"type\": \"<typeName>\" }` or just the base type name.  Where the base type name is used it is surround with \"quotes\". If not wrapped in quotes assume it is an instance of that context type (generally just an object with a `type` field set to the type name - but occasionally with other data).\n\nYou will need to pre-populate the AppDirectory with the following items (some of which will never be started, but must be configured to confirm correct behavior from various API functions):\n\n| App | Usage                                                 | ListensFor `(pattern: intent([context-types…]) (=> result-type)`)                               | On Startup                                                                   |\n|-----|-------------------------------------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|\n| A   | Raise Intent tests without results                    | `aTestingIntent(testContextX,testContextZ)`<br />`sharedTestingIntent1(testContextX)`           | `addIntentListener()` for given intents                                       |\n| B   | Raise Intent tests with Context results               | `bTestingIntent(testContextY)`<br />`sharedTestingIntent1(testContextX, testContextY) => testContextY` | `addIntentListener()` for given intents                                       |\n| C   | Find Intent tests (never started)                     | `cTestingIntent(testContextX) => testContextZ`                                                  | `addIntentListener()` for given intents                                       |\n| D   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextX) => testContextZ`                                            | `addIntentListener()` for given intents                                       |\n| E   | Find Intent & Raise Intent with Channel result        | `sharedTestingIntent2(testContextY) => channel`                                                 | `addIntentListener()` for given intents                                       |\n| F   | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel<testContextZ>` *                                 | `addIntentListener()` for given intents                                       |\n| G   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextY)`                                                            | `addIntentListener()` for given intents                                       |\n| H   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                            | - no action                                                                   |\n| I   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                           | `addIntentListener(\"MadeUpIntent\", handler)`                          |\n| J   | PrivateChannels are private                           | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult`                   | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |\n| K   | PrivateChannel lifecycle events                       | `kTestingIntent(testContextX) => channel<testContextZ>`                                         | `addIntentListener()` for given intents                                       |\n\nNB:\n\n- There is no way to indicate in the app directory the difference between a private channel and app channel.\n- We assume a final test app `Test` that will discover the Intent support in the others using the API.\n\nFinally, please note that this is a larger set of apps than were required for 1.2 tests. This is due to an increased number of parameters to API calls and AppD records, which multiplies the number of apps required. The apps are all specified here (rather than broken down over multiple issues) to ensure that clashes between test case sets can be worked out here. For example, adding one additional app that works with a particular intent/context pair might corrupt the results of multiple `findIntent` or `raiseIntent` tests. Hence, please stick to the defined type and report any issues you find so that they can be rectified in these definitions.\n\n## Find Intent basic usage\n\n- `2.0-FindIntentAppD`: Calls `fdc3.findIntent(\"aTestingIntent\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** `AppMetadata`.\n- `2.0-FindNonExistentIntentAppD`: Calls `fdc3.findIntent(\"nonExistentIntent\")`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDRightContext`: Calls `fdc3.findIntent(\"aTestingIntent\",\"testContextX\")`.  Receives promise containing an `AppIntent` with metadata containing `aTestingIntent` and only metadata for app **A**.\n- `2.0-FindIntentAppDWrongContext`: Calls `fdc3.findIntent(\"aTestingIntent\",\"testContextY\")`.  Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDMultiple1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and metadata for apps  **D**, **E**, **F**, **G**, **H**  and **I** only.\n- `2.0-FindIntentAppDMultiple2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",\"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and `AppMetadata` for apps  **E**, **F**, **G**, **H**  and **I** only.\n\n## Find Intents By Context\n\n- `2.0-FindIntentByContextSingleContext`: Call `fdc3.findIntentsByContext(testContextX)`.  Should return:\n  - `aTestingIntent` (app **A**),\n  - `sharedTestingIntent1` (**A**, **B**)\n  - `cTestingIntent` (**C**),\n  - `sharedTestingIntent2` (**D**)\n  - `kTestingIntent` (**K**),\n  - AND nothing else.\n- `2.0FindIntentByContextWrongIntentAppD`: Calls `fdc3.findIntentsByContext(nonExistentContext)`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n\n## Find Intents By Result Type\n\n- `2.0-FindIntentAppDByResultSingle`: Calls `fdc3.findIntent(\"cTestingIntent\",testContextX,\"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultSingleNullContext`: Calls `fdc3.findIntent(\"cTestingIntent\",null,\"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultMultiple`: Calls `fdc3.findIntent(\"sharedTestingIntent1\",testContextX,\"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **B** app metadata.\n- `2.0-FindIntentAppDByResultChannel1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",testContextY,\"channel\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and only **E** and **F** app metadata.\n- `2.0-FindIntentAppDByResultChannel2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",testContextY,\"channel<testContextZ>\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **F** app metadata.\n\n## Raise Intent (Ignoring any result)\n\n| App   | Step                        | Details                                                                                           |\n|-------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test  | 1. Raise                    | `fdc3.raiseIntent(\"aTestingIntent\",testContextX)`<br />starts app A.                       |\n| A     | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent1\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test  | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.**                       |\n\n- `2.0-RaiseIntentSingleResolve`: Perform above test\n- `2.0-RaiseIntentTargetedAppResolve`: Repeat the above test, but:\n  - In the first step use `fdc3.raiseIntent(\"sharedTestingIntent1\",testContextX,{\"appID\":\"<B’s-appId>\"})` to start app B,\n  - Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveOpen`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})` to start A and retrieve its `AppIdentifier` with instance details.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveFindInstances`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})` to start A.\n  - Then use `const instances = await fdc3.findInstances({appId:\"<A's-appId>\"})` to retrieve a list of instances of app A. Confirm that only one is present and retrieve its `AppIdentifier`, confirming that it contains an `instanceId` field that matches that returned by the `fdc3.open` call.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentFailedResolve`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextY)`.  Note that no app supports this intent and context combination.**\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve1`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextY,{appId:\"<A's-appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,{appId:\"NonExistentApp\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.TargetAppUnavailable`.\n- `2.0-RaiseIntentFailTargetedAppResolve3`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<H's-appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but does not add any intent listeners).\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppResolve4`: Perform above test, but:\n  - `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<I's-appId>\"})`\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but adds intent listeners of the wrong type.\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve1`: Perform above test, but:\n  - First spawn an instance of App **A** and collect its `AppIdentifier` with `const appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})`.\n  - Then use `fdc3.raiseIntent(\"aTestingIntent\",testContextY,appIdentifier)` to target that instance.  \n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound` (since A doesn't support this context type).\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextX, {appId:\"<A's-appId>\",instanceId:\"NonExistentInstanceId\"})`.  \n  - You should receive a JavaScript Error with the message `ResolveError.TargetInstanceUnavailable`.\n\n## Raise Intent Result (void result)\n\n| App    | Step                        | Details                                                                                           |\n|--------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"aTestingIntent\",testContextX)`<br />starts app A.                       |\n| A      | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.                     |\n| Test   | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.                        |\n| A      | 5. return void              | A should return `void` after a short delay (e.g. 5 seconds).                        |\n| Test   | 6. receive void result      | The promise received by Test from `resolution.getResult()` should resolve to void. Confirm that the promise could be retrieved before the handler function returned and that the result was received _after_ the result was returned by A, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited.                      |\n\n- `2.0-RaiseIntentVoidResult5secs`: Perform above test\n- `2.0-RaiseIntentVoidResult0secs`: Perform above test, but A should return its result immediately (no delay). Ignore test step 6 (as there is too little time between the IntentResolution and IntentHandler completing).\n- `2.0-RaiseIntentVoidResult61secs`: Perform above test, but A should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n## Raise Intent Result (Context result)\n\n| App    | Step                        | Details                                                                                           |\n|--------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise                    | `fdc3.raiseIntent(\"sharedTestingIntent1\",testContextY)`<br />starts app **B**. |\n| B      | 2. Receive Intent & Context | After starting up, B runs `fdc3.addIntentListener(\"sharedTestingIntent1\")` to register its listener.<br />It then receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App B's `appId` and `instanceId` set. |\n| Test   | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |\n| B      | 5. return `testContextY`    | B should return a `testContextY` instance after a short delay (e.g. 5 seconds). |\n| Test   | 6. receive context result   | The promise received by Test from `resolution.getResult()` should resolve to the `testContextY` instance. Confirm that the promise could be retrieved before the handler function returned and that the result was received _after_ the result was returned by B, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited. |\n\n- `2.0-RaiseIntentContextResult5secs`: Perform the above test.\n- `2.0-RaiseIntentContextResult0secs`: Perform the previous test but B should return its result immediately (no delay).\n- `2.0-RaiseIntentContextResult61secs`: As above, but B should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n## Raise Intent Result (Channel results)\n\n| App  | Step                        | Details                                                                                           |\n|------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Raise Intent             | Test raises an intent with `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<E's-appId>\"})`<br />starts app E. |\n| E    | 2. Receive Intent & Context | After starting up, E runs `fdc3.addIntentListener(\"sharedTestingIntent2\")` to register its listener.<br />It them receives `testContextY`, matching that sent by Test |\n| Test | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App E's `appId` and `instanceId` set.   |\n| Test | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| E    | 5. return Channel           | E should retrieve a Channel object via `fdc3.getOrCreateChannel(\"someChannelName\")` and return it immediately. |\n| Test | 6. receive Channel result   | The promise received by Test from `resolution.getResult()` should resolve to a `Channel` object with the expected id. Confirm that the `type` of the Channel object is \"app\". |\n| Test | 7. addContextListener       | Add a context listener to the Channel object via `channelObj.addContextListener(\"testContextZ\",handler)` |\n| E    | 8. broadcast context        | After a short delay (of a few seconds) E should broadcast a `testContextZ` context object over the channel, including an `id` field with a unique identifier set (e.g. a uuid). |\n| Test | 9. receive context          | Test should receive the context broadcast by E and confirm that it contains the expected `id` value. |\n\n- `2.0-RaiseIntentChannelResult`: Perform the above test\n- `2.0-RaiseIntentPrivateChannelResult`: Perform the above test, but:\n  - Substitute app F throughout - which returns a PrivateChannel result instead of channel.\n  - At step 5, the PrivateChannel should be created via`fdc3.createPrivateChannel()`.\n  - At step 6 confirm that the type of the channel is \"private\".\n\n## PrivateChannels cannot be accessed as app channels\n\n| App  | Step                                      | Details                                                                                           |\n|------|-------------------------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Create a private channel               | Test creates a PrivateChannel with `const privChan = await fdc3.createPrivateChannel()`. Confirm that the Channel has an `id`. |\n| Test | 2. Confirm private channel `id` is unique | Test creates a second PrivateChannel with `const privChan2 = await fdc3.createPrivateChannel();`. Confirm that the Channel has an `id` and that it is distinct from the first channel created. |\n| Test | 3. Retrieve as app channel                | Attempt to retrieve the channels as App Channels with `const appChan = await fdc3.getOrCreateChannel(privChan.id)` this should fail with `ChannelError.AccessDenied`  |\n| Test | 4. Raise Intent & await result            | Start app J and pass it the id of the second PrivateChannel with `fdc3.raiseIntent(\"privateChannelIsPrivate\", privateChannelDetails)`, where the context object contains the id of the channel to attempt to retrieve. An IntentResolution should be returned and App J should start. Wait for a result to be returned via `await resolution.getResult()`. |\n| J    | 5. Receive Intent & Context               | J should add an Intent Listener and receive the context with `fdc3.addIntentListener(\"privateChannelIsPrivate\",handler)` |\n| J    | 6. Retrieve as app channel                | J should attempt to retrieve the channel as an App Channel by `id` with `const appChan = await fdc3.getOrCreateChannel(\"<idPassedInContext>\")` this should fail with `ChannelError.AccessDenied`. Return a `privateChannelIsPrivateResult` back to Test to complete the test. |\n| Test | 7. Receive result                         | Test receives the result back from J and confirms that the test was passed. |\n\n- `2.0-PrivateChannelsAreNotAppChannels`: Perform the above test\n\n## PrivateChannel Lifecycle Events\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, the existing [`PrivateChannel`](../ref/PrivateChannel) lifecycle event functions (`onAddContextListener`, `onUnsubscribe` and `onDisconnect`) functions were deprecated in favour of a new [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener) function which supports events of all three types. Hence, the tests in this section have been updated to use [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener).\n\n| App  | Step                                       | Details                                                                                                                                    |\n|------|--------------------------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Raise intent                            | Test raises an intent with `fdc3.raiseIntent(\"kTestingIntent\", testContextX, {appId: \"<K's appId>\"})`<br />starts app K. |\n| K    | 2. Receive Intent & Context                | After starting up, K runs `fdc3.addIntentListener(\"kTestingIntent\")` to register its listener.<br />It them receives `testContextX`, matching that sent by Test |\n| Test | 3. IntentResolution                        | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set.   |\n| Test | 4. await results                           | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| K    | 5. Create PrivateChannel & event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,<br />it should then add listeners for the 3 events offered + a context listener via:<br />- `const listener1 = await privChan.addEventListener(\"addContextListener\", handler1);`<br />- `const listener2 = await privChan.addEventListener(\"unsubscribe\", handler2);`<br />- `const listener3 = await privChan.addEventListener(\"disconnect\", handler3);`<br />- `const listener4 = await privChan.addEventListener(null, handler4);`<br />- `const listener5 = await privChan.addContextListener(\"testContextX\", handler5)`<br />it should then return the `PrivateChannel`. |\n| Test | 6. receive PrivateChannel                  | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is \"private\". |\n| Test | 7. addContextListener                      | Test should add a context listener to the PrivateChannel object via `const testListener1 = privChan.addContextListener(\"testContextZ\", contextHandler)` |\n| K    | 8. Receive event & broadcast context       | The handlers for both the \"addContextListener\" event (`handler1`) and all events (`handler4`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |\n| Test | 9. Unsubscribe listener                    | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `testListener1.unsubscribe().` |\n| K    | 10. Receive unsubscribe event              | The handlers for both the \"unsubscribe\" event (`handler2`) and all events registered by K (`handler4`) should fire. If either does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|\n| Test | 11. Broadcast context                      | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |\n| K    | 12. Receive context                        | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|\n| Test | 13. re-run addContextListener              | Test should (again) add a context listener to the PrivateChannel object via `const testListener2 = privChan.addContextListener(\"testContextZ\", contextHandler)` |\n| K    | 14. Receive event & broadcast context      | Both the \"addContextListener\" event handler (`handler1`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |\n| Test | 15. Disconnect                             | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |\n| K    | 16. Receive events & cleanup               | Both the \"unsubscribe\" event handler (`handler2`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, both the \"disconnect\" handler (`handler3`) and handler for all events (`handler4`) also added in step 5 should fire. Once they have, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |\n\n- `2.2-PrivateChannelsLifecycleEvents`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n\n## Resolving Ambiguous Intents\n\nAn FDC3 Desktop Agent MUST provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForContext that return multiple options). This is often accomplished by providing a user interface allowing the user to select the desired target application or intent and application.\n\nAs the methods of resolving ambiguous intents are often user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. These tests are based on the same applications defined for and used in other intent tests - however a separate manual test app should be provided to enable the test.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY)` |\n| User | 2. Chooser Interaction    | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousIntentTarget`: Perform above steps to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 2.  Chooser Interaction   | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousContextTarget`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY)` |\n| User | 3. Chooser Interaction    | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousIntentTargetMultiInstance`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Open 4 Apps            | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 3.  Chooser Interaction   | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousContextTargetMultiInstance`: Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n## Destructured Raise Intent (Ignoring any result)\n\n| App   | Step                        | Details                                                                                           |\n|-------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test  | 1. Destructure raiseIntent  | Destructure raiseIntent from DesktopAgent: <br />`const { raiseIntent } = fdc3`                 |\n| Test  | 2. Raise Intent             | Use destructured method: <br />`raiseIntent(\"aTestingIntent\",testContextX)`<br />starts app A.  |\n| A     | 3. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test  | 4. IntentResolution         | The destructured `raiseIntent` call returns an `IntentResolution` Object with App A's details   |\n\n- `2.0-RaiseIntentSingleResolve-Destructured`: Perform above test to verify destructured raiseIntent works correctly.\n\n## Destructured Raise Intent Result (Context result)\n\n| App    | Step                        | Details                                                                                           |\n|--------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise Intent             | `fdc3.raiseIntent(\"sharedTestingIntent1\",testContextY)`<br />starts app **B**. |\n| B      | 2. Receive Intent & Context | B receives context and prepares to return `testContextY` |\n| Test   | 3. Destructure getResult    | Destructure getResult from IntentResolution: <br />`const { getResult } = resolution` |\n| Test   | 4. Await Destructured Result | Use destructured method: <br />`await getResult()` |\n| B      | 5. Return Context           | B returns a `testContextY` instance |\n| Test   | 6. Receive Result           | Confirm destructured getResult returns the expected context |\n\n- `2.0-RaiseIntentContextResult5secs-Destructured`: Perform above test to verify destructured getResult works correctly.\n\n## Destructured Raise Intent Result (Channel results)\n\n| App  | Step                        | Details                                                                                           |\n|------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Raise Intent             | `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<E's-appId>\"})`<br />starts app E. |\n| E    | 2. Return Channel           | E returns a Channel object |\n| Test | 3. Destructure getResult    | `const { getResult } = resolution` |\n| Test | 4. Get Channel              | `const channel = await getResult()` |\n| Test | 5. Destructure Channel Methods | `const { addContextListener, broadcast } = channel` |\n| Test | 6. Use Destructured Methods | Use destructured methods to add listener and verify broadcast works |\n\n- `2.0-RaiseIntentChannelResult-Destructured`: Perform above test to verify destructured channel methods work correctly.\n\n## Avoiding Adding Multiple Intent Listeners\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Add Intent Listener            | App performs `fdc3.addIntentListener(\"aTestingIntent1\")`. |\n| Test | 2. Perform Step 1 again | App performs `fdc3.addIntentListener(\"aTestingIntent1\")` again. |\n\n- `2.3-MultipleAddingOfTheSameIntentListenerCausesIntentListenerConflict`: Perform above steps to which should cause `IntentListenerConflict` error.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Add Intent Listener            | App performs `fdc3.addIntentListener(\"aTestingIntent1\")` and saves listener. |\n| Test | 2. Unsubscribe from the intent | App performs `listener.unsubscribe()`. |\n| Test | 2. Perform Step 1 again | App performs `fdc3.addIntentListener(\"aTestingIntent1\")` again. |\n\n- `2.3-MultipleAddingOfTheSameIntentListenerAfterUnsubscribe`: Perform above steps to which should successfully add the listener again.\n"
  },
  {
    "path": "website/docs/api/conformance/Metadata-Tests.md",
    "content": "---\nid: Metadata-Tests\nsidebar_label: Metadata Tests\ntitle: Metadata Tests\nhide_title: true\n---\n\n# Metadata & Instance Test Cases\n<!-- markdownlint-disable MD033 -->\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                        |\n|-----|------------------------------------------|\n| A   | Generic AppD Record which contains at least the following fields:<br />- `name`<br />- `version`<br />- `title`<br />- `tooltip`<br />- `description`<br />- `icons` (`Array<Icon>`)<br />- `screenshots` (`Array<Image>`)<br />- `interop.intents.listensFor` (`aTestingIntent` with at least context type `testContextX`)  |\n\n## Retrieve `AppMetadata`\n\n| App    | Step              | Details                                                                                           |\n|--------|-------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. getAppMetadata | Retrieve metadata for the configured app A with <br/> `const metadata1 = await fdc3.getAppMetadata({appId:\"<A's-appId>\"})`  |\n| Test   | 2. Confirm        | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set  |\n\n- `GetAppMetadata`: perform the above steps.\n\n## Instance Metadata\n\n| App  | Step               | Details                                                                                           |\n|------|--------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Open1           | Open a first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test | 2. Open2           | Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test | 3. getAppMetadata1 | Retrieve metadata for the first instance of the app with<br/> `const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |\n| Test | 4. Confirm1        | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches.  |\n| Test | 5. getAppMetadata2 | Retrieve metadata for the second instance of the app with <br/>`const metadata2 = fdc3.getAppMetadata(appIdentifier2)`  |\n| Test | 6. Confirm2        | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2`  |\n\n- `AppInstanceMetadata`: Perform the above steps.\n\n## Finding Instances\n\n| App  | Step              | Details                                                                                           |\n|------|-------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Open1          | Open the first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId:\"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test | 2. Open2          | Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId:\"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test | 3. FindInstances  | Retrieve details of open instances of app A with <br/> `let instances = await fdc3.findInstances({appId:\"<A's-appId>\"})` <br/> confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array. |\n| Test | 4. RaiseIntent    | Use `appIdentifier1` to raise an intent and target that instance, with<br/> `const resolution = fdc3.raiseIntent(\"aTestingIntent\",{\"type\":\"testContextX\"},appIdentifier1)` |\n| Test | 5. Confirm1       | Check that `resolution.source` matches `appIdentifier1` |\n| A    | 6. ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |\n\n- `FindInstances`: Perform the above steps.\n\n## Getting Info For The Agent\n\n| App  | Step             | Details                                                                                           |\n|------|------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. getInfo       | Retrieve the `ImplementationMetadata` for the DesktopAgent with <br/> - `fdc3.getInfo().then((implMetadata) => { subsequent steps }`   <br />**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|\n| Test | 2. CheckVersion  | Check that the `fdc3Version` variable is present and at or greater than:  <br /> - 2.0  <br />(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):<br />`const isFDC3v2 = versionIsAtLeast(implMetadata, \"2.0\")`  |\n| Test | 3. CheckProvider | Check that the `provider` variable is present and not an empty string  |\n| Test | 4. CheckFeatures | Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values  |\n\n- `GetInfo1`: Perform the above steps.\n\n| App      | Step       | Details                                                                                           |\n|----------|------------|---------------------------------------------------------------------------------------------------|\n| Test     | 1. Open1   | Start an instance of App A with <br/>`const appIdentifier1 = await fdc3.open({appId:\"<A's-appId>\"})` <br /> retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |\n| A        | 2 .getInfo |   Retrieve the `ImplementationMetadata` for the DesktopAgent with: <br  />`fdc3.getInfo().then((implMetadata) => {  ... subsequent steps ...}` <br/> This should include `AppMetadata` for the retrieving app. |\n| A + Test | 3. Confirm | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |\n\n- `GetInfo2`: Perform the above steps.\n"
  },
  {
    "path": "website/docs/api/conformance/Open-Tests.md",
    "content": "---\nid: Open-Tests\nsidebar_label: Open Tests\ntitle: Open Tests\nhide_title: true\n---\n\n# Open Tests\n<!-- markdownlint-disable MD033 -->\n\n## A Opens B  \n\n| App | Step              | Description                                              |\n|-----|-------------------|----------------------------------------------------------|\n| A   | 1. Opening App    | App A calls a function (see below) to open a second app, B |\n| A   | 2. Check Metadata | Ensure that the correct app was opened |\n\n- `AOpensB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"})`\n- `AOpensB4`:   **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId:\"<app-B-ID>\"})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.\n\n## A Fails To Open Another App\n\n| App | Step                    | Description                                              |\n|-----|-------------------------|----------------------------------------------------------|\n| A   | 1. Opening App          | App A calls a function (see below) to try and open a non-existent app |\n| A   | 2. Check Error Response | `fdc3.open` returns a promise that rejects with an Error with the message \"App Not Found\" |\n\n- `AFailsToOpenB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"})`\n\n## A Opens B With Context\n\n| App | Step               | Description                                              |\n|-----|--------------------|----------------------------------------------------------|\n| A   | 1. Opening App     |App A opens app B with an `fdc3.instrument` Context Object by calling a function (see below) |\n| B   | 2. Receive Context | Add an untyped context listener via: <br/>`fdc3.addContextListener(null,handler)` <br /> B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open()` call made by A |\n\n- `AOpensBWithContext3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"}, <fdc3.instrument context>)`\n- `AOpensBWithSpecificContext`: Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener(\"fdc3.instrument\",handler)`\n- `AOpensBMultipleListen`:  Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener(\"fdc3.contact\",handler)` prior to the existing `addContextListener` for `fdc3.instrument`.  The correct context listener should receive the context, and the promise completes successfully.\n- `AOpensBWithWrongContext`: Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.\n  - Confirm that NO context is received.\n  - The promise returned to **A** by `fdc3.open` rejects with an Error with message `AppTimeout`\n\n## A Opens B - Destructured\n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Destructure open     | Destructure open method from DesktopAgent: <br />`const { open } = fdc3` |\n| A   | 2. Opening App          | Use destructured method to open app B: <br />`const result = await open({appId:\"<app-B-ID>\"})` |\n| A   | 3. Check Metadata       | Ensure that the correct app was opened and `result` contains expected `AppIdentifier` |\n\n- `AOpensB3-Destructured`: Perform above test to verify destructured `open` works correctly.\n\n## A Opens B With Context - Destructured\n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Destructure open     | Destructure open method from DesktopAgent: <br />`const { open } = fdc3` |\n| A   | 2. Opening App          | Use destructured method to open app B with context: <br />`const result = await open({appId:\"<app-B-ID>\"}, <fdc3.instrument context>)` |\n| A   | 3. Check Metadata       | Ensure that the correct app was opened and context was passed |\n\n- `AOpensB4-Destructured`: Perform above test to verify destructured `open` with context works correctly.\n"
  },
  {
    "path": "website/docs/api/conformance/Overview.md",
    "content": "---\nid: Conformance-Overview\nsidebar_label: Overview\ntitle: FDC3 Conformance Tests\nhide_title: true\n---\n\n# FDC3 Conformance Tests\n\nThis section contains test definitions that are used to test for conformance of a Desktop Agent API implementation with FDC3.\n\n:::note\n\nFDC3 2.2 introduces both a new interface to web-based FDC3 Desktop Agent, known as a \"Desktop Agent Proxy\", as an alternative to the injection of the FDC3 API at `window.fdc3`, which is now know as a \"Desktop Agent Preload\" interface `GetAgent`. 2.2 also introduces the [`getAgent`](../ref/GetAgent) function which can be used to connect to either interface and MUST be used by conformance testing apps to retrieve a interface (whichever is provided by the Desktop Agent being tested).\n\n:::\n\n:::info\n\nWhere tests were introduced in this version of FDC3, they are labelled with an in the header, like so: ![2.2](https://img.shields.io/badge/FDC3-2.2-purple)\n\n:::\n\nThere are currently 6 sections to the tests.  \n\n- [Basic Tests](Basic-Tests.md)\n- [Open Tests](Open-Tests.md)\n- [User Channel Tests](User-Channel-Tests.md)\n- [App Channel Tests](App-Channel-Tests.md)\n- [Metadata Tests](Metadata-Tests.md)\n- [Intents Tests](Intents-Tests.md)\n\nYou can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.\n"
  },
  {
    "path": "website/docs/api/conformance/User-Channel-Tests.md",
    "content": "---\nid: User-Channel-Tests\nsidebar_label: User Channel Tests\ntitle: User Channel Tests\nhide_title: true\n---\n\n# User Channel Tests\n<!-- markdownlint-disable MD033 -->\n\n## Basic Broadcast\n\n| App | Step                  | Details                                                                          |\n|-----|-----------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener | A adds an _unfiltered_ Context Listener using `addContextListener(null,handler)`. <br/>A promise resolving to  a `Listener` object is returned <br />Check that this has an `unsubscribe` method. |\n| A   | 2. joinUserChannel    | A joins the first available (non-global) user channel.  The available Channels are retrieved with: <br/>`fdc3.getUserChannels()` <br/> The first channel (that does not have the id 'global') is joined with: <br/>`fdc3.joinUserChannel(<channelId>)`  |\n| B   | 3. joinUserChannel    | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast(<fdc3.instrument>)`. <br/>Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the instrument object, matching the one broadcast by B.  |\n\n- `UCBasicUsage1` Perform above test.\n- `UCBasicUsage2` Perform steps in order: 2,1,3,4,5 to confirm that the order of `joinUserChannel` and `addContextListener` calls doesn't matter.\n- `UCBasicUsage3` Perform steps in order: 3,4,1,2,5 to confirm that the current context is automatically received on joining a channel.\n- `UCBasicUsage4` Perform steps in order: 3,4,2,1,5  to confirm that the current context is automatically received on adding a context listener to an already joined a channel.\n\n## Filtered Broadcast\n\n| App | Step                  | Details                                                                          |\n|-----|-----------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener | A adds an `fdc3.instrument` _typed_ Context Listener using `addContextListener(\"fdc3.instrument\",handler)`. <br/>A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` function.|\n| A   | 2. joinUserChannel    | A joins the first available user channel using: <br/>`getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel    | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts: <br/> 1.`fdc3.broadcast(<fdc3.instrument>)`. <br/> 2. `fdc3.broadcast(<fdc3.contact>)` <br />Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the `fdc3.instrument` object, matching the one broadcast by B. <br />Check that the `fdc3.contact` is NOT received. |\n\n- `UCFilteredUsage1` Perform above test.\n- `UCFilteredUsage2` Perform steps in order: 2,1,3,4,5.\n- `UCFilteredUsage3` Perform steps in order: 3,4,1,2,5.\n- `UCFilteredUsage4` Perform steps in order: 3,4,2,1,5.\n\n## Broadcast With Multiple Listeners\n\n| App | Step                   | Details                                                                                                     |\n|-----|------------------------|-------------------------------------------------------------------------------------------------------------|\n| A   | 1. addContextListeners | A sets up two Context Listeners.  One for `fdc3.instrument` and one for `fdc3.contact` by calling:  `addContextListener (\"fdc3.instrument\",handler)` <br/> `addContextListener(\"fdc3.contact\",handler)` <br/>A promise resolving a `Listener` object is returned for each. <br />Check that this has an `unsubscribe` method for each.  |\n| A   | 2. joinUserChannel     | A joins the first available user channel using: <br/>`getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel     | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast           | `fdc3.broadcast(<fdc3.instrument>)` <br/> `fdc3.broadcast(<fdc3.contact>)` . |\n| A   | 5. Receive Context     | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.<br />A's `fdc3.contact` object matches the one broadcast  by B, and arrives on the correct listener. |\n\n- `UCFilteredUsage5`: Perform above test.\n- `UCFilteredUsage6`: Perform above test, except B will join a _different_ channel to A. Check that you _don't_ receive anything.\n- `UCFilteredUsageChange`: Perform above test, except that after joining, **A** changes channel to a _different_ channel via a further call to `fdc3.joinUserChannel`.  Check that **A** does NOT receive anything.\n- `UCFilteredUsageUnsubscribe`: Perform above test, except that after joining, **A** then `unsubscribe()`s from the channel using the `listener.unsubscribe` function. Check that **A** does NOT receive anything.\n- `UCFilteredUsageLeave`: Perform above test, except that immediately after joining, **A** _leaves the channel_, and so receives nothing.\n- `UCFilteredUsageNoJoin`: Perform the above test, but skip step 2 so that **A** does NOT join a channel. Confirm that the _current channel_ for **A** is NOT set before continuing with the rest of the test.  **A** should receive nothing.\n\n## Event on channel changed\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface `addEventListener` function was added allowing an app to listen for events raised. In 2.2 only one event is supported, `userChannelChanged`.\n\nAn FDC3 Desktop Agent MUST provide a method to set the current User Channel for an application. This is often accomplished by providing a control within the user interface of a window or frame, allowing the user to select the desired channel.\n\nAs the method of setting the user channel is user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. A separate manual test app should be provided to enable the test.\n\n| App                 | Step                                       | Details |\n|---------------------|--------------------------------------------|---------|\n| ChannelChangedEvent | 1. Open the test application               | A dedicated test application for  FDC3ChannelChangedEvent should be opened. |\n| ChannelChangedEvent | 2. Register for `userChannelChanged` event | `await fdc3.addEventListener(\"userChannelChanged\", handler);`<br />The `handler` function should log or render details of events received|\n| User                | 3. Set User Channel                        | The user should set the current user channel of the app and change it a few times. Details of each change should be displayed by the test app. |\n\n- `2.2-ChannelChangedEvent`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n\n\n## Broadcast With Multiple Listeners On The Same or Overlapping Types\n\n| App | Step               | Details                                                                                                     |\n|-----|--------------------|-------------------------------------------------------------------------------------------------------------|\n| A   | 1. addContextListeners | A sets up two Context Listeners.  One _untyped_ and one for `fdc3.contact` by calling:  `addContextListener(null, handler1)` <br/> `addContextListener(\"fdc3.contact\", handler2)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned for each.  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned for each. <br />Check that this has an `unsubscribe` method for each.  |\n| A   | 2. joinUserChannel     |A joins the first available user channel using: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `getSystemChannels()` Check channels are returned. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          |`fdc3.broadcast(<contact context>)` . |\n| A   | 5. Receive Context    | A's `fdc3.contact` object matches the one broadcast  by B, both handlers from step 1 are triggered, and broadcast arrives on the correct listener.   |\n\n- UCMultipleOverlappingListeners1: Perform above test\n- UCMultipleOverlappingListeners2: Perform above test, but instead of _untyped_ context listener, in step 2, use `fdc3.instrument` (handler should remain different)"
  },
  {
    "path": "website/docs/api/ref/Channel.md",
    "content": "---\nid: Channel\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `Channel`\n\nRepresents a context channel that applications can join to share context data and provides functions for interacting with it.\n\nA channel can be either a [\"User\" channel](../spec#joining-user-channels) (retrieved with [`getUserChannels`](DesktopAgent#getuserchannels)), a custom [\"App\" channel](../spec#app-channels) (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)) or a [\"Private\" channel](../spec#private-channels) (obtained via an intent result).\n\n:::note\n\nThere are differences in behavior when you interact with a User channel via the Desktop Agent interface and the Channel interface. Specifically, when 'joining' a User channel or adding a context listener when already joined to a channel via the `DesktopAgent` interface, existing context (matching the type of the context listener) on the channel is received by the context listener immediately. Whereas, when add a context listener via the Channel interface, context is not received automatically, but may be retrieved manually via the [`getCurrentContext()`](#getcurrentcontext) function.\n\n:::\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: \"user\" | \"app\" | \"private\";\n  displayMetadata?: DisplayMetadata;\n\n  // functions\n  broadcast(context: Context): Promise<void>;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n  clearContext(contextType?: string): Promise<void>;\n  addEventListener(type: string  | null, handler: EventHandler): Promise<Listener>;\n  \n  //deprecated functions\n  /**\n   * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IChannel: IIntentResult\n{\n    string Id { get; }\n    ChannelType Type { get; }\n    IDisplayMetadata? DisplayMetadata { get; }\n    Task Broadcast(IContext context);\n    Task<IContext?> GetCurrentContext(string? contextType);\n    Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n    Task ClearContext(string? contextType);\n    Task<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n@experimental\ntype IChannel interface {\n    Broadcast(context Context) <-chan Result[any]\n    GetCurrentContext(contextType string) <-chan Result[IContext]\n    AddContextListener(contextType string, handler ContextHandler) <-chan Result[Listener]\n}\n\n@experimental\ntype Channel struct {\n\tId              string        `json:\"id\"`\n\tType            ChannelType      `json:\"type\"`\n\tDisplayMetadata *DisplayMetadata `json:\"displayMetadata\"`\n}\n\n@experimental\ntype ChannelType string\n\n@experimental\nconst (\n\tApp     ChannelType = \"app\"\n\tPrivate ChannelType = \"private\"\n\tUser    ChannelType = \"user\"\n\tSystem  ChannelType = \"system\"\n)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n\n## Properties\n\n### `id`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly id: string;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nstring Id { get; }\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nId string\n```\n\n</TabItem>\n</Tabs>\n\nUniquely identifies the channel. It is either assigned by the desktop agent (User Channel) or defined by an application (App Channel).\n\n### `type`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly type: \"user\" | \"app\" | \"private\";\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nChannelType Type { get; }\n\npublic enum ChannelType\n{\n    User = 1,\n    App = 2,\n    Private = 3\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype ChannelType string\n\nconst (\n\tApp     ChannelType = \"app\"\n\tSystem  ChannelType = \"system\"\n\tPrivate ChannelType = \"private\"\n)\n```\n</TabItem>\n</Tabs>\n\nCan be _user_,  _app_ or _private_.\n\n### `displayMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIDisplayMetadata? DisplayMetadata { get; }\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nDisplayMetadata *DisplayMetadata\n```\n</TabItem>\n</Tabs>\n\nDisplayMetadata can be used to provide display hints for User Channels intended to be visualized and selectable by end users.\n\n**See also:**\n\n- [`DisplayMetadata`](Metadata#displaymetadata)\n\n## Functions\n\n### `addContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (ch *Channel) AddContextListener(contextType string, handler ContextHandler) <-chan Result[Listener]  { \n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\nIf, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the [`getCurrentContext(contextType)`](#getcurrentcontext) function.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\nAdding multiple context listeners on the same or overlapping types (i.e. specific `contextType` and `null` type) MUST be allowed, and MUST trigger all ContextHandlers when a relevant context type is broadcast on the current channel. \n\n**Examples:**\n\nAdd a listener for any context that is broadcast on the channel:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst listener = await channel.addContextListener(null, context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIChannel channel;\nvar listener = await channel.AddContextListener<IContext>(null, (context, metadata) => {\n    if (context.Type == ContextTypes.Contact)\n    {\n        // handle the contact\n    }\n    else if (context.Type == ContextTypes.Instrument) {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.Unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nlistenerResult := <-channel.AddContextListener(\"\", func(contextInt IContext, contextMetadata *ContextMetadata) {\n        if context, ok := contextInt.(Context); ok {\n\t\t\tif context.Type == \"fdc3.contact\" {\n\t\t\t\t// handle the contact \n\t\t\t} else if context.Type == \"fdc3.instrument\" {\n\t\t\t\t// handle the instrument \n\t\t\t}\n        } \n\t})\n\n// later \nif listenerResult.Value != nil {\n\tlistenerResult.Value.Unsubscribe()\n}\n```\n\n</TabItem>\n</Tabs>\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst contactListener = await channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar contactListener = await channel.AddContextListener<Contact>(\"fdc3.contact\", (contact, metadata) => {\n    // handle the contact\n});\n\nvar instrumentListener = await channel.AddContextListener<Instrument>(\"fdc3.instrument\", (instrument, metadata) => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nlistenerResultContact := <-channel.AddContextListener(\"fdc3.contact\", func(context IContext, contextMetadata *ContextMetadata) {\n    // handle the contact\n})\nlistenerResultInstrument := <-channel.AddContextListener(\"fdc3.instrument\", func(context IContext, contextMetadata *ContextMetadata) {\n    // handle the instrument\n})\n\n// later \nif listenerResultContact.Value != nil {\n\tlistenerResultContact.Value.Unsubscribe()\n}\nif listenerResultInstrument.Value != nil {\n\tlistenerResultInstrument.Value.Unsubscribe()\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`ContextHandler`](Types#contexthandler)\n- [`broadcast`](#broadcast)\n- [`getCurrentContext`](#getcurrentcontext)\n\n### `addEventListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddEventListener(type: string  | null, handler: EventHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n```\n\n</TabItem>\n</Tabs>\n\nRegister a handler for events from the Channel. Whenever the handler function is called it will be passed an event object with details related to the event.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// any event type\nconst listener: Listener = await myChannel.addEventListener(null, \n    (event: ApiEvent) => {\n        console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n    }\n);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIChannel myChannel;\nvar listener = await myChannel.AddEventListener(null, (event) => {\n    System.Diagnostics.Debug.WriteLine($\"Received event ${event.Type}\\n\\tDetails: ${event.Details}\");\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Events](./Events)\n- [EventHandler](./Events#eventhandler)\n- [ApiEvent](./Events#ApiEvent)\n\n### `broadcast`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic broadcast(context: Context): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Broadcast(IContext context);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (channel *Channel) Broadcast(context IContext) <-chan Result[any]  { \n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [FDC3 Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar instrument = new Instrument(new InstrumentID() { Ticker = \"AAPL\" });\n\ntry\n{\n    channel.Broadcast(instrument);\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresult := <-myChannel.Broadcast(types.Context{\n\t\t\tType: \"fdc3.instrument\",\n\t\t\tId: map[string]string{\n\t\t\t\t\"ticker\": \"AAPL\",\n\t\t},\n})\nif result.Err != null {\n    // handle error \n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`getCurrentContext`](#getcurrentcontext)\n- [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IContext?> GetCurrentContext(string? contextType);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (channel *Channel) GetCurrentContext(contextType string) <-chan Result[Context]  { \n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\nIf getting the current context fails, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Examples:**\n\nWithout specifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.GetCurrentContext();\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresult := <-myChannel.GetCurrentContext(\"\")\nif result.Err != null {\n    // handle error \n}\n```\n\n</TabItem>\n</Tabs>\n\nSpecifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.GetCurrentContext(\"fdc3.contact\");\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresult := <-myChannel.GetCurrentContext(\"fdc3.contact\")\nif result.Err != null {\n    // handle error \n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`broadcast`](#broadcast)\n- [`addContextListener`](#addcontextlistener)\n\n### `clearContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic clearContext(contextType?: string): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask ClearContext(string? contextType);\n```\n\n</TabItem>\n</Tabs>\n\nUsed to clear the specified context type if provided, otherwise, clear all context types present in the channel. The Desktop Agent MUST update its internal representation of the context in the channel and ensure that subsequent calls to [`getCurrentContext`](#getcurrentcontext) and any new joiners to that channel (through [`joinUserChannel`](DesktopAgent#joinUserChannel) or [`addContextListener`](DesktopAgent#addContextListener)) will not receive anything for either the specified context type or the most recent context until new context has been broadcast to the channel. \nDesktop Agents MUST also immediately notify the apps that are listening to `contextCleared` event for this channel. If a `contextType` parameter was provided, then the `contextType` field will be set to that type, otherwise, it is omitted. \n\n\n**Examples:**\n\nWithout specifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const context = await channel.clearContext();\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.ClearContext();\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n</Tabs>\n\nSpecifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const contact = await channel.clearContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.ClearContext(\"fdc3.contact\");\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n</Tabs>\n\n\n**See also:**\n\n- [`getCurrentContext`](#getcurrentcontext)\n- [`addContextListener`](DesktopAgent#addContextListener)\n- [`joinUserChannel`](DesktopAgent#joinUserChannel)\n- [`addEventListener`](#addeventlistener)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n/**\n * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\npublic addContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n\n</Tabs>\n\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n"
  },
  {
    "path": "website/docs/api/ref/DesktopAgent.md",
    "content": "---\nid: DesktopAgent\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `DesktopAgent`\n\nAn FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nFor details of how implementations of the `DesktopAgent` are made available to applications please see [Supported Platforms](../supported-platforms).\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n\n  // context\n  broadcast(context: Context): Promise<void>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n\n  // intents\n  findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n  findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n\n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  createPrivateChannel(): Promise<PrivateChannel>;\n  getUserChannels(): Promise<Array<Channel>>;\n\n  // OPTIONAL channel management functions\n  joinUserChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel | null>;\n  leaveCurrentChannel() : Promise<void>;\n\n  // non-context events\n  addEventListener(type: FDC3EventTypes  | null, handler: EventHandler): Promise<Listener>;\n\n  //implementation info\n  getInfo(): Promise<ImplementationMetadata>;\n\n  //Deprecated functions\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  open(name: string, context?: Context): Promise<AppIdentifier>;\n  raiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IDesktopAgent\n{\n    // Apps\n    Task<IAppIdentifier> Open(IAppIdentifier app, IContext? context = null);\n    Task<IEnumerable<IAppIdentifier>> FindInstances(IAppIdentifier app);\n    Task<IAppMetadata> GetAppMetadata(IAppIdentifier app);\n\n    // Context\n    Task Broadcast(IContext context);\n    Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n\n    // Intents\n    Task<IAppIntent> FindIntent(string intent, IContext? context = null, string? resultType = null);\n    Task<IEnumerable<IAppIntent>> FindIntentsByContext(IContext context, string? resultType = null);\n    Task<IIntentResolution> RaiseIntent(string intent, IContext context, IAppIdentifier? app = null);\n    Task<IIntentResolution> RaiseIntentForContext(IContext context, IAppIdentifier? app = null);\n    Task<IListener> AddIntentListener<T>(string intent, IntentHandler<T> handler) where T : IContext;\n\n    // Channels\n    Task<IChannel> GetOrCreateChannel(string channelId);\n    Task<IPrivateChannel> CreatePrivateChannel();\n    Task<IEnumerable<IChannel>> GetUserChannels();\n\n    // non-context events\n    Task<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n\n    // OPTIONAL channel management functions\n    Task JoinUserChannel(string channelId);\n    Task<IChannel?> GetCurrentChannel();\n    Task LeaveCurrentChannel();\n\n    // Implementation Information\n    Task<IImplementationMetadata> GetInfo();\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n@experimental\ntype Result[T any] struct {\n\tValue *T\n\tErr   error\n}\n@experimental\ntype DesktopAgent struct {}\n\n@experimental\ntype IDesktopAgent interface {\n    // Apps\n    Open(appIdentifier AppIdentifier, context *IContext) <-chan Result[AppIdentifier]\n    FindInstances(appIdentifier AppIdentifier) <-chan Result[[]AppIdentifier]\n    GetAppMetadata(appIdentifier AppIdentifier) <-chan Result[AppIdentifier]\n\n    // Context\n    Broadcast(context IContext) <-chan Result[any]\n    AddContextListener(contextType string, handler ContextHandler) <-chan Result[Listener]\n\n    // Intents\n    FindIntent(intent string, context *IContext, resultType *string) <-chan Result[AppIntent]\n    FindIntentsByContext(context IContext, resultType *string) <-chan Result[[]AppIntent]\n    RaiseIntent(intent string, context IContext, appIdentifier *AppIdentifier) <-chan Result[IntentResolution]\n    RaiseIntentForContext(context IContext, appIdentifier *AppIdentifier) <-chan Result[IntentResolution]\n    AddIntentListener(intent string, handler IntentHandler) <-chan Result[Listener]\n\n    // Channels\n    GetOrCreateChannel(channelId string) <-chan Result[Channel]\n    CreatePrivateChannel() <-chan Result[PrivateChannel]\n    GetUserChannels() <-chan Result[[]Channel]\n\n    // OPTIONAL channel management functions\n    JoinUserChannel(channelId string) <-chan Result[any]\n    GetCurrentChannel() <-chan Result[Channel]\n    LeaveCurrentChannel() <-chan Result[any]\n\n    // non-context events \n    AddEventListener(type *FDC3EventTypes, handler EventHandler) <-Result[Listener];\n\n    //implementation info\n    GetInfo() <-chan Result[ImplementationMetadata]\n}\n```\n\n</TabItem>\n</Tabs>\n\n## Functions\n\n### `addContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) AddContextListener(contextType string, handler ContextHandler) <-chan Result[Listener] { \n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or [`fdc3.open`](#open) API call). If the consumer is only interested in a context of a particular type, they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.\n\nContext broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from User channels. If this function is called after the app has already joined a channel and the channel already contains context that matches the type of the context listener, then it will be called immediately and the context passed to the handler function. If `null` was passed as the context type for the listener and the channel contains context, then the handler function will be called immediately with the most recent context - regardless of type.\n\nContext may also be received via this listener if the application was launched via a call to  [`fdc3.open`](#open), where context was passed as an argument. In order to receive this, applications SHOULD add their context listener as quickly as possible after launch, or an error MAY be returned to the caller and the context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the Desktop Agent implementation.\n\nAdding multiple context listeners on the same or overlapping types (i.e. specific `contextType` and `null` type) MUST be allowed, and MUST trigger all ContextHandlers when a relevant context type is broadcast on the current user channel. Please note, that this behavior differs from [`fdc3.addIntentListener`](#addintentlistener) call; refer to the relevant documentation for more details. \n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// any context\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n// listener for a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });\n\n// listener that logs metadata for the message a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', (contact, metadata) => {\n  console.log(`Received context message\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n  //do something else with the context\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// any context\nvar listener = await _desktopAgent.AddContextListener<IContext>(null, (context, meatadata) => { ... });\n\n// listener for a specific type\nvar listener = await _desktopAgent.AddContextListener<Instrument>(\"fdc3.contact\", (contact, metadata) => { ... });\n\n// listener that logs metadata for the message of a specific type\nvar contactListener = await _desktopAgent.AddContextListener<Contact>(\"fdc3.contact\", (contact, metadata) => {\n  System.Diagnostics.Debug.WriteLine($\"Received context message\\nContext: {contact}\\nOriginating app: {metadata?.Source}\");\n  // do something else with the context\n});\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n// any context\nlistenerResult := <-desktopAgent.AddContextListener(\"\", func(context IContext, contextMetadata *ContextMetadata) { ... })\n\n// listener for a specific type\nlistenerResult := <-desktopAgent.AddContextListener(\"fdc3.contact\", func(context IContext, contextMetadata *ContextMetadata) { ... })\n\n// listener that logs metadata for the message of a specific type\nlistenerResult := <-desktopAgent.AddContextListener(\"fdc3.contact\", func(context IContext, contextMetadata *ContextMetadata) {\n  if contextMetadata != nil {\n    log.Printf(\"Received context message\\nContext: %v\\nOriginating app: %v\", context, contextMetadata.Source)\n} else {\n    log.Printf(\"Received context message\\nContext: %v\", context)\n}\n})\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`ContextHandler`](Types#contexthandler)\n\n### `addEventListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddEventListener(type: FDC3EventTypes  | null, handler: EventHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) AddEventListener(type *FDC3EventTypes, handler EventHandler) <-Result[Listener]  { \n  // Implmentation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nRegisters a handler for non-context and non-intent events from the Desktop Agent. If the consumer is only interested in an event of a particular type, they can specify that type. If the consumer is able to receive events of any type or will inspect types received, then they can pass `null` as the `type` parameter to receive all event types.\n\nWhenever the handler function is called it will be passed an event object with details related to the event.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// any event type\nconst listener = await fdc3.addEventListener(null, event => { ... });\n\n// listener for a specific event type that logs its details\nconst userChannelChangedListener = await fdc3.addEventListener(\"userChannelChanged\", event => { \n  console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n  //do something else with the event\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar listener = await _desktopAgent.AddEventListener(null, (event) => { ... });\n\nvar userChannelChangedListener = await _desktopAgent.AddEventListener(\"userChannelChanged\", (event) => {\n  System.Diagnostics.Debug.Write($\"Received event ${event.Type}\\n\\tDetails: ${event.Details}\");\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`FDC3EventTypes`](./Events#fdc3eventtypes)\n- [`FDC3Event`](./Events#fdc3event)\n- [`EventHandler`](./Events#eventhandler)\n\n### `addIntentListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddIntentListener<T>(string intent, IntentHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) AddIntentListener(intent string, handler IntentHandler) <-chan Result[Listener]  { \n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming intents raised by other applications, via calls to [`fdc3.raiseIntent`](#raiseintent) or [`fdc3.raiseIntentForContext`](#raiseintentforcontext). If the application is intended to be launched to resolve raised intents, it SHOULD add its intent listeners as quickly as possible after launch or an error MAY be returned to the caller and the intent and context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nThe handler function may return void or a promise that resolves to a [`IntentResult`](Types#intentresult), which is either a [`Context`](Types#context) object, representing any data that should be returned to the app that raised the intent, or a [`Channel`](Channel), a [`PrivateChannel`](PrivateChannel) over which data responses will be sent, or `void`. The `IntentResult` will be returned to the app that raised the intent via the [`IntentResolution`](Metadata#intentresolution) and retrieved from it using the `getResult()` function.\n\nThe Desktop Agent MUST reject the promise returned by the `getResult()` function of `IntentResolution` if any of the following is true:\n\n1. The intent handling function's returned promise rejects.\n2. The intent handling function returns something other than a promise.\n3. The returned promise resolves to an invalid type.\n\nThe [`PrivateChannel`](PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n Adding multiple intent listeners on the same type MUST be rejected with the [`ResolveError.IntentListenerConflict`](Errors#resolveerror), unless the previous listener was removed first though [`listener.unsubscribe`](Types#unsubscribe)\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n//Handle a raised intent\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n  return;\n});\n\n//Handle a raised intent and log the originating app metadata\nconst listener = fdc3.addIntentListener('StartChat', (contact, metadata) => {\n  console.log(`Received intent StartChat\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n    return;\n});\n\n//Handle a raised intent and return Context data via a promise\nfdc3.addIntentListener(\"CreateOrder\", (context) => {\n  return new Promise<Context>((resolve) => {\n    // go create the order\n    resolve({type: \"fdc3.order\", id: { \"orderId\": 1234}});\n  });\n});\n\n//Handle a raised intent and return a PrivateChannel over which response will be sent\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel: PrivateChannel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // Called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // Stop the feed if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n//Handle a raised intent\nvar listener = await _desktopAgent.AddIntentListener<IContext>(\"StartChat\", (context, metadata) => {\n    // start chat has been requested by another application\n    // return IIntentResult;\n});\n\n//Handle a raised intent and log the originating app metadata\nvar listener = await _desktopAgent.AddIntentListener<IContext>(\"StartChat\", (contact, metadata) => {\n    System.Diagnostics.Debug.Write($\"Received intent StartChat\\nContext: {contact}\\nOriginating app: {metadata?.Source}\");\n    // return IIntentResult;\n});\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n//Handle a raised intent\nlistenerResult := <-desktopAgent.AddIntentListener(\"StartChat\", func(context IContext, contextMetadata *ContextMetadata) { \n  // start chat has been requested by another application\n})\n\n//Handle a raised intent and log the originating app metadata\nlistenerResult := <-desktopAgent.AddIntentListener(\"StartChat\", func(context IContext, contextMetadata *ContextMetadata) { \n  if contextMetadata != nil {\n    log.Printf(\"Received intent StartChat\\nContext: %v\\nOriginating app: %v\", context, contextMetadata.Source)\n  } else {\n    log.Printf(\"Received intent StartChat\\nContext: %v\", context)\n}\n})\n\n// listener that logs metadata for the message of a specific type\nlistenerResult := <-desktopAgent.AddIntentListener(\"fdc3.contact\", func(context IContext, contextMetadata *ContextMetadata) {\n  if contextMetadata != nil {\n    log.Printf(\"Received context message\\nContext: %v\\nOriginating app: %v\", context, contextMetadata.Source)\n} else {\n    log.Printf(\"Received context message\\nContext: %v\", context)\n}\n})\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Register an Intent Handler](../spec#register-an-intent-handler)\n- [`PrivateChannel`](PrivateChannel)\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`IntentHandler`](Types#intenthandler)\n- [`ResolveError`](Errors#resolveerror)\n\n### `broadcast`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nbroadcast(context: Context): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Broadcast(IContext context);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) Broadcast(context IContext) <-chan Result[any]  { \n  // Implmentation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User Channel_ the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\nDesktopAgent implementations SHOULD ensure that context messages broadcast to a channel by an application joined to it are not delivered back to that same application.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nInstrument instrument = new Instrument(\n    new InstrumentID()\n    {\n        Ticker = \"AAPL\"\n    }\n);\n\n_desktopAgent.Broadcast(instrument);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ncontext := types.Context{\n    Type: \"fdc3.instrument\",\n    Id: map[string]string{\n      \"ticker\": \"AAPL\",\n    },\n  }\ndesktopAgent.Broadcast(context)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [addContextListener](#addcontextlistener)\n\n### `createPrivateChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ncreatePrivateChannel(): Promise<PrivateChannel>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IPrivateChannel> CreatePrivateChannel();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) CreatePrivateChannel() <-chan Result[PrivateChannel] {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nReturns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.\n\nIf the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\nThe `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // This gets called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  const unsubscribeListener = channel.onUnsubscribe((contextType) => {\n    feed.stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n_desktopAgent.AddIntentListener<Instrument>(\"QuoteStream\", async (context, metadata) => {\n  var channel = await _desktopAgent.CreatePrivateChannel();\n  var symbol = context?.ID?.Ticker;\n\n  // This gets called when the remote side adds a context listener\n  var addContextListener = channel.OnAddContextListener((contextType) => {\n      // broadcast price quotes as they come in from our quote feed\n      _feed.OnQuote(symbol, (price) => {\n          channel.Broadcast(new Price(price));\n      });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  var unsubscribeListener = channel.OnUnsubscribe((contextType) => {\n      _feed.Stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  var disconnectListener = channel.OnDisconnect(() => {\n      _feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ndesktopAgent.AddIntentListener(\"fdc3.contact\", func(context IContext, contextMetadata *ContextMetadata) {\n  channelResult := <-desktopAgent.CreatePrivateChannel()\n  symbol := context.Id[\"ticker\"]\n\n  if channelResult.Err != nil {\n    return \n  }\n  channel := channelResult.Value\n  channel.OnAddContextListener\n})\n\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`PrivateChannel`](PrivateChannel)\n- [`raiseIntent`](#raiseintent)\n- [`addIntentListener`](#addintentlistener)\n\n### `findInstances`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IAppIdentifier>> FindInstances(IAppIdentifier app);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) FindInstances(appIdentifier AppIdentifier) <-chan Result[[]AppIdentifier] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nFind all the available instances for a particular application.\n\nIf the application is not known to the agent, the returned promise should be rejected with the `ResolveError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array.\n\nIf the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// Retrieve a list of instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Target a raised intent at a specific instance\nlet resolution = fdc3.raiseIntent(\"ViewInstrument\", context, instances[0]);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Retrieve a list of instances of an application\nvar instances = await _desktopAgent.FindInstances(new AppIdentifier(\"MyAppId\"));\n\n// Target a raised intent at a specific instance\nvar resolution = await _desktopAgent.RaiseIntent(\"ViewInstrument\", context, instances.First());\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n// Retrieve a list of instances of an application\nfindInstancesResult := <-desktopAgent.FindInstances(AppIdentifier{AppId: \"MyAppId\"})\nif findInstancesResult.Err != nil || len(findInstancesResult.Value) == 0 {\n  // handle error\n}\n\n// Target a raised intent at a specific instance\nresolutionResult := <-desktopAgent.RaiseIntent(\"ViewInstrument\", context, findInstancesResult.Value[0])\n```\n\n</TabItem>\n</Tabs>\n\n### `findIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppIntent> FindIntent(string intent, IContext? context = null, string? resultType = null);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) FindIntent(intent string, context *IContext, resultType *string) <-chan Result[AppIntent] {\n  // Implmentation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nFind out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type.\n\n`findIntent` is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to an `AppIntent` which provides details of the intent, its metadata and metadata about the apps and app instances that are registered to handle it. This can be used to raise the intent against a specific app or app instance.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no apps are found that resolve the intent, when the [`ResolveError.NoAppsFound`](Errors#resolveerror) message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nResult types 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.\n\n**Examples:**\n\nI know 'StartChat' exists as a concept, and want to know which apps can resolve it:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Slack\" }\n//   ]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0]);\n\n//later, we want to raise 'StartChat' intent again\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns an AppIntent, but with multiple options for resolution,\n// which includes an existing instance of an application:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//    { appId: \"Slack\" }\n//   ]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\");\n\n// raise the intent against a particular app\nawait _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfindIntentResult := <-desktopAgent.FindIntent(\"StartChat\", nil, nil)\nif findIntentResult.Err != nil {\n  // handle error\n}\n\n// raise the intent against a particular app\n<-desktopAgent.RaiseIntent(findIntentResult.Value.Intent.Name, context, findInstancesResult.Value.Apps[0])\n```\n\n</TabItem>\n</Tabs>\n\nAn optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\", contact);\n\n// returns only apps that support the type of the specified input context:\n// {\n//     intent: { name: \"StartChat\" },\n//     apps: { name: \"Symphony\" }]\n// }\n\nconst appIntent = await fdc3.findIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     intent: { name: \"ViewContact\" },\n//     apps: { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }\n\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     intent: { name: \"QuoteStream\" },\n//     apps: { appId: \"MyOMS\", resultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", contact);\n// returns only apps that support the type of the specified input context:\n// {\n//     Intent: { Name: \"StartChat\" },\n//     Apps: { Name: \"Symphony\" }]\n// }\n\nvar appIntent = await _desktopAgent.FindIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }\n\nvar appIntent = await _desktopAgent.FindIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     Intent: { Name: \"QuoteStream\" },\n//     Apps: { AppId: \"MyOMS\", ResultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfindIntentResult := <-desktopAgent.FindIntent(\"StartChat\", &contact, nil)\n// returns only apps that support the type of the specified input context:\n// {\n//     Intent: { Name: \"StartChat\" },\n//     Apps: { Name: \"Symphony\" }]\n// }\n\nresultType := \"fdc3.ContactList\"\nfindIntentResult := <-desktopAgent.FindIntent(\"ViewContact\", &nil, &resultType)\n// returns only apps that return the specified result type:\n// {\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }\n\nfindIntentResult := <-desktopAgent.FindIntent(\"QuoteStream\", &instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     Intent: { Name: \"QuoteStream\" },\n//     Apps: { AppId: \"MyOMS\", ResultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IAppIntent>> FindIntentsByContext(IContext context, string? resultType = null);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) FindIntentsByContext(context IContext, resultType *string) <-chan Result[[]AppIntent] {\n  // Implmentation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nFind all the available intents for a particular context, and optionally a desired result context type.\n\n`findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.\nA 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.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no intents with associated apps are found, when the `ResolveError.NoAppsFound` message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nThe 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 without a specified context type, 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.\n\n**Example:**\n\nI 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...\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [\n//   {\n//     intent: { name: \"StartCall\" },\n//     apps: [{ appId: \"Skype\" }]\n//   },\n//   {\n//     intent: { name: \"StartChat\" },\n//     apps: [\n//       { appId: \"Skype\" },\n//       { appId: \"Symphony\" },\n//       { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//       { appId: \"Slack\" }\n//     ]\n//   },\n//   {\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n//   }\n// ];\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntents = await _desktopAgent.FindIntentsByContext(context);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfindIntentResult := <-desktopAgent.FindIntentsByContext(context, nil)\n```\n\n</TabItem>\n</Tabs>\n\nor I look for only intents that are resolved by apps returning a particular result type\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntentsForType = await fdc3.findIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app or instance\nconst selectedApp = startChat.apps[2];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntentsForType = await _desktopAgent.FindIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: [{ AppId: \"Symphony\" }, { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nvar startChat = appIntentsForType.First();\n\n// target a particular app or instance\nvar selectedApp = startChat.Apps.First();\n\n// raise the intent, passing the given context, targeting the app\nawait _desktopAgent.RaiseIntent(startChat.Intent.Name, context, selectedApp);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresultType := \"fdc3.ContactList\"\nfindIntentResult := <-desktopAgent.FindIntentsByContext(context, &resultType)\n// returns for example:\n// [{\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: [{ AppId: \"Symphony\" }, { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }];\nif findIntentResult.Err != nil || len(findIntentResult.Value) == 0 {\n  // handle error or no results\n}\n// select a particular intent to raise\nstartChat := findIntentResult.Value[0]\n\n// target a particular app or instance\nselectedApp := startChat.Apps[0]\n\n// raise the intent, passing the given context, targeting the app\n<-desktopAgent.RaiseIntent(startChat.Intent.Name, context, selectedApp)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`findIntent()`](#findintent)\n- [`ResolveError`](Errors#resolveerror)\n\n### `getAppMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppMetadata> GetAppMetadata(IAppIdentifier app);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) GetAppMetadata(appIdentifier AppIdentifier) <-chan Result[AppIdentifier] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves the [`AppMetadata`](Metadata#appmetadata) for an [`AppIdentifier`](Types#appidentifier), which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes.\n\nIf the app is not found, the promise MUST be rejected with an `Error` Object with the `message` given by [`ResolveError.TargetAppUnavailable`](Errors#resolveerror), or (if connected to a Desktop Agent Bridge) an error from the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nlet appIdentifier = { appId: \"MyAppId@my.appd.com\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIdentifier = new AppIdentifier(\"MyAppId@my.appd.com\");\nvar appMetadata = await _desktopAgent.GetAppMetadata(appIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nappIdentifier := AppIdentifier{AppId: \"MyAppId@my.appd.com\"}\nappMetadataResult := <-desktopAgent.GetAppMetadata(appIdentifier)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`AppIdentifier`](Types#appidentifier)\n\n### `getCurrentChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetCurrentChannel() : Promise<Channel | null>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IChannel?> GetCurrentChannel();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) GetCurrentChannel() <-chan Result[Channel] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that returns the `Channel` object for the current User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nReturns `null` if the app is not joined to a channel.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// get the current channel membership\nvar current = await _desktopAgent.GetCurrentChannel();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ncurrentResult := <-desktopAgent.GetCurrentChannel()\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getInfo`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetInfo(): Promise<ImplementationMetadata>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IImplementationMetadata> GetInfo();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) GetInfo() <-chan Result[ImplementationMetadata] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves information about the FDC3 Desktop Agent implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent.\n\nReturns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.  This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar version = (await _desktopAgent.GetInfo()).Fdc3Version;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ninfoResult := <-desktopAgent.GetInfo()\nif infoResult.Value != nil {\n  version := infoResult.Fdc3Version\n}\n```\n\n</TabItem>\n</Tabs>\n\nThe `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar implementationMetadata = await _desktopAgent.GetInfo();\nvar appId = implementationMetadata.AppMetadata.AppId;\nvar instanceId = implementationMetadata.AppMetadata.InstanceId;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nimplementationMetadataResult := <-desktopAgent.GetInfo()\nif implementationMetadataResult.Value != nil {\n  appId := implementationMetadataResult.AppMetadata.AppId\n  instanceId := implementationMetadataResult.AppMetadata.InstanceId\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ImplementationMetadata`](Metadata#implementationmetadata)\n- [`AppMetadata`](Metadata#appmetadata)\n\n### `getOrCreateChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IChannel> GetOrCreateChannel(string channelId);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) GetOrCreateChannel(channelId string) <-chan Result[Channel] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nReturns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist.\n\nIf the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  myChannel.addContextListener(null, context => { /* do something with context */});\n}\ncatch (err: ChannelError) {\n  //app could not register the channel\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var myChannel = await _desktopAgent.GetOrCreateChannel(\"myChannel\");\n    await myChannel.AddContextListener<IContext>(null, (context, metadata) => { /* do something with context */});\n}\ncatch (Exception ex)\n{\n    //app could not register the channel\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nmyChannelResult := <-desktopAgent.GetOrCreateChannel(\"myChannel\")\nif myChannelResult.Err != nil {\n    //app could not register the channel\n}\nmyChannel := myChannelResult.Value\n<-myChannel.AddContextListener(\"\", func(context IContext, metadata *ContextMetadata) {\n    // do something with context\n})\n\n\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getUserChannels`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetUserChannels() : Promise<Array<Channel>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IChannel>> GetUserChannels();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) GetUserChannels() <-chan Result[[]Channel] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves a list of the User Channels available for the app to join.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst userChannels = await fdc3.getUserChannels();\nconst redChannel = userChannels.find(c => c.id === 'red');\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar userChannels = await _desktopAgent.GetUserChannels();\nvar redChannel = userChannels.First(c => c.Id == \"red\");\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nimport \"slices\" // This is for go 1.21+, before that use `golang.org/x/exp/slices` library\nuserChannelsResult := <-desktopAgent.GetUserChannels()\nif userChannelsResult.Err != nil {\n  // handle error\n}\nredChannel := slices.IndexFunc(userChannelsResult.Value, func(c Channel) bool { return c.Id == \"red\" })\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `joinUserChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\njoinUserChannel(channelId: string) : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask JoinUserChannel(string channelId);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) JoinUserChannel(channelId string) <-chan Result[any] {\n  // Implementation here\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nIf an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.\n\nIf the channel already contains context that would be passed to context listeners added via `fdc3.addContextListener` then those listeners will be called immediately with that context.\n\nAn app can only be joined to one channel at a time.\n\nIf an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// get all user channels\nconst channels = await fdc3.getUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\nfdc3.joinUserChannel(selectedChannel.id);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// get all user channels\nvar channels = await _desktopAgent.GetUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\n_desktopAgent.JoinUserChannel(selectedChannel.Id);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nuserChannelsResult := <-desktopAgent.GetUserChannels()\nif userChannelsResult.Err != nil {\n  // handle error\n}\n<-desktopAgent.JoinUserChannel(userChannelsResult.Value.Id)\n\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `leaveCurrentChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask LeaveCurrentChannel();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) LeaveCurrentChannel() <-chan Result[any] {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that removes the app from any User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nContext broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(null, context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(null, channelListener);\n\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n//desktop-agent scope context listener\nvar fdc3Listener = await _desktopAgent.AddContextListener<IContext>(null, (context, metadata) => { });\n\nawait _desktopAgent.LeaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.AddContextListener(null, channelListener);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n//desktop-agent scope context listener\nlistenerResult := <-desktopAgent.AddContextListener(\"\", func(context IContext, contextMetadata *ContextMetadata) { ... })\n\n\n<-desktopAgent.LeaveCurrentChannel()\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\n<-redChannel.AddContextListener(\"\", channelListener);\n```\n\n</TabItem>\n</Tabs>\n\n### `open`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nopen(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppIdentifier> Open(IAppIdentifier app, IContext? context = null);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) Open(appIdentifier AppIdentifier, context *IContext) <-chan Result[AppIdentifier] {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nLaunches an app, specified via an [`AppIdentifier`](Types#appidentifier) object.\n\nThe `open` method differs in use from [`raiseIntent`](#raiseintent).  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying an App Directory, `open` would be used to open an app returned in the search results.\n\n**Note**, if the intent, context and target app name are all known, it is recommended to instead use [`raiseIntent`](#raiseintent) with the `target` argument.\n\nIf a [`Context`](Types#context) object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n\nReturns an [`AppIdentifier`](Types#appidentifier) object with the `instanceId` field set to identify the instance of the application opened by this call.\n\nIf an error occurs while opening the app, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`OpenError`](Errors#openerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n ```js\n// Open an app without context, using an AppIdentifier object to specify the target\nlet appIdentifier = { appId: 'myApp-v1.0.1' };\nlet instanceIdentifier = await fdc3.open(appIdentifier);\n\n// Open an app with context\nlet instanceIdentifier = await fdc3.open(appIdentifier, context);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Open an app without context, using an AppIdentifier object to specify the target\nvar appIdentifier = new AppIdentifier(\"myApp-v1.0.1\");\nvar instanceIdentifier = await _desktopAgent.Open(appIdentifier);\n\n// Open an app with context\nvar instanceIdentifier = await _desktopAgent.Open(appIdentifier, context);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n// Open an app without context, using an AppIdentifier object to specify the target\nappIdentifier := AppIdentifier{AppId: \"myApp-v1.0.1\"}\ninstanceIdentifierResult := <-desktopAgent.Open(appIdentifier, nil)\n\n// Open an app with context \ninstanceIdentifierResult := <-desktopAgent.Open(appIdentifier, &context)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppMetadata`](Metadata#appmetadata)\n- [`OpenError`](Errors#openerror)\n\n### `raiseIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IIntentResolution> RaiseIntent(string intent, IContext context, IAppIdentifier? app = null);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) RaiseIntent(intent string, context IContext, appIdentifier *AppIdentifier) <-chan Result[IntentResolution] {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nRaises a specific intent for resolution against apps registered with the desktop agent.\n\nThe 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.\nAlternatively, 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).\n\nIf 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, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\nIf 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.\n\nReturns an [`IntentResolution`](Metadata#intentresolution) object with details of the app instance that was selected (or started) to respond to the intent.\n\nIssuing 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, Channel object or void 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 valid response (a promise or void), or (3) the returned promise resolves to an invalid type.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait fdc3.raiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Raise an intent without a context by using the null context type\nawait fdc3.raiseIntent(\"StartChat\", {type: \"fdc3.nothing\"});\n\n//Raise an intent and retrieve a result from the IntentResolution\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  if (result && result.broadcast) { //detect whether the result is Context or a Channel\n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`\n  }\n}\ncatch (error: ResultError) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait _desktopAgent.RaiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait _desktopAgent.RaiseIntent(\"StartChat\", context, appIntent.Apps.First());\n\n//Raise an intent without a context by using the null context type\nawait _desktopAgent.RaiseIntent(\"StartChat\", ContextType.Nothing);\n\n//Raise an intent and retrieve a result from the IntentResolution\nIIntentResolution resolution = await _desktopAgent.RaiseIntent(\"intentName\", context);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\n<-desktopAgent.RaiseIntent(\"StartChat\", context, nil)\n\n// or find apps to resolve an intent to start a chat with a given contact\nappIntentResult := <-desktopAgent.FindIntent(\"StartChat\", &context, nil);\nif appIntentResult.Err != nil || len(appIntentResult.Vlaue.Apps) == 0 {\n  // handle error or no apps returned\n}\n\n// use the metadata of an app or app instance to describe the target app for the intent\n<-desktopAgent.RaiseIntent(\"StartChat\", context, appIntentResult.Vlaue.Apps[0])\n\n//Raise an intent without a context by using the null context type\n<-desktopAgent.RaiseIntent(\"StartChat\", Context{Type: \"fdc3.nothing\"}, nil)\n\n//Raise an intent and retrieve a result from the IntentResolution\nresolutionResult := <-desktopAgent.RaiseIntent(\"intentName\", context, nil);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResult`](Types#intentresult)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n- [`ResultError`](Errors#resulterror)\n\n### `raiseIntentForContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IIntentResolution> RaiseIntentForContext(IContext context, IAppIdentifier? app = null);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (desktopAgent *DesktopAgent) RaiseIntentForContext(context IContext, appIdentifier *AppIdentifier) <-chan Result[IntentResolution] {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nFinds and raises an intent against apps registered with the desktop agent based purely on the type of the context data.\n\nThe desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context.\nAlternatively, the specific app or app instance to target can also be provided, in which case any method of resolution SHOULD only consider intents supported by the specified application.\n\nUsing `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app.\n\nReturns an `IntentResolution` object, see [`raiseIntent()`](#raiseintent) for details.\n\nIf a target intent and app cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// Display a resolver UI for the user to select an intent and application to resolve it\nconst intentResolution = await fdc3.raiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait fdc3.raiseIntentForContext(context, targetAppIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Display a resolver UI for the user to select an intent and application to resolve it\nvar intentResolution = await _desktopAgent.RaiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait _desktopAgent.RaiseIntentForContext(context, targetAppIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n// Display a resolver UI for the user to select an intent and application to resolve it\nintentResolutionResult := <-desktopAgent.RaiseIntentForContext(context, nil)\n\n// Resolve against all intents registered by a specific target app for the specified context\nintentResolutionResult := <-desktopAgent.RaiseIntentForContext(context, &targetAppIdentifier)\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`raiseIntent()`](#raiseintent)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming context broadcasts from the Desktop Agent. Provided for backwards compatibility with versions FDC3 standard &lt;2.0.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n\n### `getSystemChannels` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAlias to the [`getUserChannels`](#getuserchannels) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `joinChannel` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAlias to the [`joinUserChannel`](#joinuserchannel) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n\n**See also:**\n\n- [`joinUserChannel`](#joinuserchannel)\n\n### `open` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nopen(name: string, context?: Context): Promise<AppIdentifier>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `open` that launches an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`open`](#open)\n\n### `raiseIntent` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `raiseIntent` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntent`](#raiseintent)\n\n### `raiseIntentForContext` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `raiseIntentForContext` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntentForContext`](#raiseintentforcontext)\n"
  },
  {
    "path": "website/docs/api/ref/Errors.md",
    "content": "---\ntitle: Errors\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations may sometimes result in an error that is returned to the caller. Errors MUST be returned by rejecting the promise returned by the API with a JavaScript `Error` object (or equivalent for the language of the implementation). The `Error` Object's message should be chosen from the appropriate Error enumeration below.\n\n## `AgentError`\n\nContains constants representing the errors that can be encountered when calling the [`getAgent`](GetAgent) function to establish connectivity to a Desktop Agent. Primarily used with web applications, but may also be used in other language implementations.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum AgentError { \n    /** Returned if no Desktop Agent was found by any means available or \n     * if the Agent previously connected to is not contactable on a  \n     * subsequent connection attempt.*/\n    AgentNotFound = \"AgentNotFound\",\n\n    /** Returned if validation of the app identity by the Desktop Agent \n     * failed or the app is not being allowed to connect to the Desktop Agent \n     * for another reason. */ \n    AccessDenied = \"AccessDenied\",\n\n    /** Returned if an error or exception occurs while trying to set  \n     * up communication with a Desktop Agent. */ \n    ErrorOnConnect = \"ErrorOnConnect\",\n\n    /** Returned if the failover function is not a function, or it did not\n     * resolve to one of the allowed types.*/ \n    InvalidFailover = \"InvalidFailover\",\n\n    /** Returned if an API call rejects after a timeout. Used where an API call\n     * is not aligned to another error enumeration.\n     */\n    ApiTimeout = 'ApiTimeout'\n} \n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar AgentError = struct {\n  // Returned if no Desktop Agent was found by any means available or \n  // if the Agent previously connected to is not contactable on a  \n  // subsequent connection attempt.\n  AgentNotFound string\n  // Returned if validation of the app identity by the Desktop Agent \n  // failed or the app is not being allowed to connect to the Desktop Agent for another reason.\n  AccessDenied string\n  // Returned if an error or exception occurs while trying to set  \n  // up communication with a Desktop Agent.\n  ErrorOnConnect string\n  // Returned if the failover function is not a function, or it did not\n  // resolve to one of the allowed types.\n  InvalidFailover string\n}{\n\tAgentNotFound:    \"AgentNotFound\",\n\tAccessDenied:     \"AccessDenied\",\n\tErrorOnConnect:   \"ErrorOnConnect\",\n\tInvalidFailover:  \"InvalidFailover\",\n}\n```\n\n</TabItem>\n</Tabs>\n\n## `ChannelError`\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum ChannelError {\n  /** Returned if the specified channel is not found when attempting to join a\n   *  channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).\n   */\n  NoChannelFound = \"NoChannelFound\",\n\n  /** SHOULD be returned when a request to join a user channel or to a retrieve\n   *  a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods\n   *  of the DesktopAgent (`fdc3`) object is denied. \n   */\n  AccessDenied = \"AccessDenied\",\n  \n  /** SHOULD be returned when a channel cannot be created or retrieved via the\n   *  `getOrCreateChannel` method of the DesktopAgent (`fdc3`).\n   */\n  CreationFailed = \"CreationFailed\",\n\n  /** Returned if a call to the `broadcast` functions is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** Returned if a timeout occurs before any Channel related API call is resolved.\n   */\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned if invalid arugments are passed to the API call.\n   */\n  InvalidArguments = 'InvalidArguments'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ChannelError\n{\n    /// <summary>\n    /// Returned if the specified channel is not found when attempting to join a\n    /// channel via the `JoinUserChannel` function of the DesktopAgent.\n    /// </summary>\n    public static readonly string NoChannelFound = nameof(NoChannelFound);\n\n    /// <summary>\n    /// SHOULD be returned when a request to join a user channel or to a retrieve\n    /// a Channel object via the `JoinUserChannel` or `GetOrCreateChannel` methods\n    /// of the DesktopAgent is denied.\n    /// </summary>\n    public static readonly string AccessDenied = nameof(AccessDenied);\n\n    /// <summary>\n    /// SHOULD be returned when a channel cannot be created or retrieved via the\n    /// `GetOrCreateChannel` method of the DesktopAgent.\n    /// </summary>\n    public static readonly string CreationFailed = nameof(CreationFailed);\n\n    /// <summary>\n    /// Returned if a call to the `Broadcast` functions is made with an invalid\n    /// context argument.Contexts should be Objects with at least a `Type` field\n    /// that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n\n    /// <summary>\n    /// Returned if invalid arguments are passed to the api call.\n    /// </summary>\n    public static readonly string InvalidArguments = nameof(InvalidArguments);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar ChannelError = struct {\n\t// Returned if the specified channel is not found when attempting to join a\n\t// channel via the `joinUserChannel` function of the DesktopAgent.\n\tNoChannelFound string\n\t// SHOULD be returned when a request to join a user channel or to a retrieve\n\t// a Channel object via the `JoinUserChannel` or `GetOrCreateChannel` methods\n\t// of the DesktopAgent object is denied.\n\tAccessDenied string\n\t// SHOULD be returned when a channel cannot be created or retrieved via the\n\t// `GetOrCreateChannel` method of the DesktopAgent.\n\tCreationFailed string\n\t// Returned if a call to the `broadcast` functions is made with an invalid\n\t// context argument. Contexts should be Objects with at least a `type` field\n\t// that has a `string` value.\n\tMalformedContext string\n}{\n\tNoChannelFound: \"NoChannelFound\",\n\tAccessDenied:   \"AccessDenied\",\n\tCreationFailed: \"CreationFailed\",\n\tMalformedContext: \"MalformedContext\",\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n\n## `OpenError`\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum OpenError {\n  /** Returned if the specified application is not found.*/\n  AppNotFound = \"AppNotFound\",\n\n  /** Returned if the specified application fails to launch correctly.*/\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n\n  /** Returned if the specified application launches but fails to add a context\n   *  listener in order to receive the context passed to the `fdc3.open` call.\n   */\n  AppTimeout = \"AppTimeout\",\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = \"ResolverUnavailable\",\n\n  /** Returned if a call to the `open` function is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a connected \n   *  Desktop Agent Bridge. \n   * */\n  DesktopAgentNotFound = \"DesktopAgentNotFound\",\n\n  /** Returned if a timeout occurs before a call to open is resolved for any\n   *  reason other than the not adding its context listener in time.  \n   */\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned if invalid arugments are passed to the API call.\n   */\n  InvalidArguments = 'InvalidArguments'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class OpenError\n{\n    /// <summary>\n    /// Returned if the specified application is not found.\n    /// </summary>\n    public static readonly string AppNotFound = nameof(AppNotFound);\n\n    /// <summary>\n    /// Returned if the specified application fails to launch correctly.\n    /// </summary>\n    public static readonly string ErrorOnLaunch = nameof(ErrorOnLaunch);\n\n    /// <summary>\n    /// Returned if the specified application launches but fails to add a context\n    /// listener in order to receive the context passed to the `Open` call.\n    /// </summary>\n    public static readonly string AppTimeout = nameof(AppTimeout);\n\n    /// <summary>\n    /// Returned if the FDC3 desktop agent implementation is not currently able\n    /// to handle the request.\n    /// </summary>\n    public static readonly string ResolverUnavailable = nameof(ResolverUnavailable);\n\n    /// <summary>\n    /// Returned if a call to the `Open` function is made with an invalid\n    /// context argument.Contexts should be Objects with at least a `Type` field\n    /// that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n\n    /// <summary>\n    /// Returned if invalid arguments are passed to the api call.\n    /// </summary>\n    public static readonly string InvalidArguments = nameof(InvalidArguments);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar OpenError = struct {\n\t// Returned if the specified application is not found.\n\tAppNotFound string\n\t// Returned if the specified application fails to launch correctly.\n\tErrorOnLaunch string\n\t// Returned if the specified application launches but fails to add a context\n\t// listener in order to receive the context passed to the `fdc3.open` call.\n\tAppTimeout string\n\t// Returned if the FDC3 desktop agent implementation is not currently able to handle the request.\n\tResolverUnavailable string\n\t// Returned if a call to the `Open` function is made with an invalid\n\t// context argument.Contexts should be Objects with at least a `Type` field\n\t// that has a `string` value.\n\tMalformedContext string\n\t// Experimental: Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.\n\tDesktopAgentNotFound string,\n}{\n\tAppNotFound:         \"AppNotFound\",\n\tErrorOnLaunch:       \"ErrorOnLaunch\",\n\tAppTimeout:          \"AppTimeout\",\n\tResolverUnavailable: \"ResolverUnavailable\",\n\tMalformedContext:    \"MalformedContext\",\n\tDesktopAgentNotFound: \"DesktopAgentNotFound\",\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.open`](DesktopAgent#open)\n\n## `ResolveError`\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent), [`findIntentsByContext`](DesktopAgent#findintentsbycontext), [`raiseIntent`](DesktopAgent#raiseintent) or [`raiseIntentForContext`](DesktopAgent#raiseintentforcontext) methods on the [DesktopAgent](DesktopAgent).\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nexport enum ResolveError {\n  /** SHOULD be returned if no apps are available that can resolve the intent\n   *  and context combination.\n   */\n  NoAppsFound = \"NoAppsFound\",\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = \"ResolverUnavailable\",\n\n  /** Returned if the user cancelled the resolution request, for example by\n   *  closing or cancelling a resolver UI.\n   */\n  UserCancelled = \"UserCancelledResolution\",\n\n  /** SHOULD be returned if a timeout cancels an intent resolution that\n   *  required user interaction. Please use `ResolverUnavailable` instead for\n   *  situations where a resolver UI or similar fails.\n   */\n  ResolverTimeout = \"ResolverTimeout\",\n\n  /** Returned if a specified target application is not available or a new\n   *  instance of it cannot be opened. \n   */\n  TargetAppUnavailable = \"TargetAppUnavailable\",\n\n  /** Returned if a specified target application instance is not available,\n   *  for example because it has been closed. \n   */\n  TargetInstanceUnavailable = \"TargetInstanceUnavailable\",\n\n  /** Returned if the intent and context could not be delivered to the selected\n   *  application or instance, for example because it has not added an intent\n   *  handler within a timeout.\n   */\n  IntentDeliveryFailed = \"IntentDeliveryFailed\",\n\n  /** Returned if a call to one of the `raiseIntent` functions is made with an \n   *  invalid context argument. Contexts should be Objects with at least a `type`\n   *  field that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a\n   *  connected Desktop Agent Bridge.\n   */\n  DesktopAgentNotFound = \"DesktopAgentNotFound\",\n\n  /** Returned if a timeout occurs before the API call is resolved for any reason other \n   *  than the resolver timing out (use ResolverTimeout) or an app launched by a \n   *  raiseIntent function doesn't add its intent listener in time (use \n   *  IntentDeliveryFailed).\n   */\n  ApiTimeout = 'ApiTimeout',\n\n  /** Returned if invalid arugments are passed to the API call.\n   */\n  InvalidArguments = 'InvalidArguments'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ResolveError\n{\n    /// <summary>\n    /// SHOULD be returned if no apps are available that can resolve the intent\n    /// and context combination.\n    /// </summary>\n    public static readonly string NoAppsFound = nameof(NoAppsFound);\n\n    /// <summary>\n    /// Returned if the FDC3 desktop agent implementation is not currently able\n    /// to handle the request.\n    /// </summary>\n    public static readonly string ResolverUnavailable = nameof(ResolverUnavailable);\n\n    /// <summary>\n    /// SHOULD be returned if a timeout cancels an intent resolution that\n    /// required user interaction. Please use `ResolverUnavailable` instead for\n    /// situations where a resolver UI or similar fails.\n    /// </summary>\n    public static readonly string ResolverTimeout = nameof(ResolverTimeout);\n\n    /// <summary>\n    /// Returned if the user cancelled the resolution request, for example by\n    /// closing or cancelling a resolver UI.\n    /// </summary>\n    public static readonly string UserCancelledResolution = nameof(UserCancelledResolution);\n\n    /// <summary>\n    /// Returned if a specified target application is not available or a new\n    /// instance of it cannot be opened.\n    /// </summary>\n    public static readonly string TargetAppUnavailable = nameof(TargetAppUnavailable);\n\n    /// <summary>\n    /// Returned if a specified target application instance is not available,\n    /// for example because it has been closed.\n    /// </summary>\n    public static readonly string TargetInstanceUnavailable = nameof(TargetInstanceUnavailable);\n\n    /// <summary>\n    /// Returned if the intent and context could not be delivered to the selected\n    /// application or instance, for example because it has not added an intent\n    /// handler within a timeout.\n    /// </summary>\n    public static readonly string IntentDeliveryFailed = nameof(IntentDeliveryFailed);\n    \n    /// <summary>\n    /// Returned if a call to one of the `RaiseIntent` functions is made with an \n    /// invalid context argument. Contexts should be Objects with at least a `Type`\n    /// field that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n\n    /// <summary>\n    /// Returned if invalid arguments are passed to the api call.\n    /// </summary>\n    public static readonly string InvalidArguments = nameof(InvalidArguments);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar ResolveError = struct {\n\t// SHOULD be returned if no apps are available that can resolve the intent and context combination\n\tNoAppsFound string\n\t// Returned if the FDC3 desktop agent implementation is not currently able to handle the request\n\tResolverUnavailable string\n\t// Returned if the user cancelled the resolution request,\n\t// for example by closing or cancelling a resolver UI\n\tUserCancelled string\n\t// SHOULD be returned if a timeout cancels an intent resolution that required user interaction.\n\t// Please use `ResolverUnavailable` instead for situations where a resolver UI or similar fails\n\tResolverTimeout string\n\t// Returned if a specified target application is not available or\n\t// a new instance of it cannot be opened.\n\tTargetAppUnavailable string\n\t// Returned if a specified target application instance is not available,\n\t// for example because it has been closed\n\tTargetInstanceUnavailable string\n\t// Returned if the intent and context could not be delivered to the selected\n\t// application or instance, for example because it has not added an intent handler within a timeout\n\tIntentDeliveryFailed string\n\t// Returned if a call to one of the `RaiseIntent` functions is made with an \n\t// invalid context argument. Contexts should be Objects with at least a `Type`\n\t// field that has a `string` value.\n\tMalformedContext string\n}{\n\tNoAppsFound:               \"NoAppsFound\",\n\tResolverUnavailable:       \"ResolverUnavailable\",\n\tUserCancelled:             \"UserCancelledResolution\",\n\tResolverTimeout:           \"ResolverTimeout\",\n\tTargetAppUnavailable:      \"TargetAppUnavailable\",\n\tTargetInstanceUnavailable: \"TargetInstanceUnavailable\",\n\tIntentDeliveryFailed:      \"IntentDeliveryFailed\",\n\tMalformedContext:          \"MalformedContext\",\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n\n## `ResultError`\n\nContains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum ResultError {\n  /** Returned if the intent handler exited without returning a valid result \n   * (a promise resolving to a Context, Channel object or void).\n   */\n  NoResultReturned = \"NoResultReturned\",\n\n  /** Returned if the `IntentHandler` function processing the raised intent\n   *  throws an error or rejects the Promise it returned. \n   */\n  IntentHandlerRejected = \"IntentHandlerRejected\",\n\n  /** Returned if a timeout occurs before the getResult() API call is resolved.\n   */\n  ApiTimeout = 'ApiTimeout'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ResultError\n{\n    /// <summary>\n    /// Returned if the intent handler exited without returning a valid result \n    /// (a Task resolving to a Context, Channel object or void).\n    /// </summary>\n    public static readonly string NoResultReturned = nameof(NoResultReturned);\n\n    /// <summary>\n    /// Returned if the `IntentHandler` function processing the raised intent\n    /// throws an error.\n    /// </summary>\n    public static readonly string IntentHandlerRejected = nameof(IntentHandlerRejected);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar ResultError = struct {\n\t// IntentHandlerRejected Returned if the `IntentHandler` function processing the raised intent\n\t// throws an error or rejects the Promise it returned.\n\tIntentHandlerRejected string\n\t// NoResultReturned Returned if the `IntentHandler` exited without returning a Promise or that\n\t// Promise was not resolved with a Context or Channel object.\n\tNoResultReturned string\n}{\n\tIntentHandlerRejected: \"IntentHandlerRejected\",\n\tNoResultReturned:      \"NoResultReturned\",\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `BridgingError`\n\n[`@experimental`](../../fdc3-compliance#experimental-features)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum BridgingError {\n  /** @experimental Returned if a Desktop Agent did not return a response, via \n   *  Desktop Agent Bridging, within the allotted timeout. */\n  ResponseTimedOut = \"ResponseToBridgeTimedOut\",\n\n  /** @experimental Returned if a Desktop Agent that has been targeted by a \n   *  particular request has been disconnected from the Bridge before a \n   *  response has been received from it. */\n  AgentDisconnected = \"AgentDisconnected\",\n\n  /** @experimental Returned for FDC3 API calls that are specified with\n   *  arguments indicating that a remote Desktop agent should be targeted\n   *  (e.g. raiseIntent with an app on a remote DesktopAgent targeted), \n   *  when the local Desktop Agent is not connected to a bridge. */\n  NotConnectedToBridge = \"NotConnectedToBridge\",\n\n  /** @experimental Returned if a message to a Bridge deviates from the schema\n   *  for that message sufficiently that it could not be processed.\n   */\n  MalformedMessage = \"MalformedMessage\",\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nvar BridgingError = struct {\n\t// Experimental: Returned if a Desktop Agent did not return a response, via \n\t// Desktop Agent Bridging, within the allotted timeout.\n\tResponseTimedOut string\n\t// Experimental: Returned if a Desktop Agent that has been targeted by a \n\t// particular request has been disconnected from the Bridge before a \n\t// response has been received from it.\n\tAgentDisconnected string\n\t// Experimental: Returned for FDC3 API calls that are specified with\n\t// arguments indicating that a remote Desktop agent should be targeted\n\t// (e.g. raiseIntent with an app on a remote DesktopAgent targeted), \n\t// when the local Desktop Agent is not connected to a bridge. \n\tNotConnectedToBridge string\n\t// Experimental: Returned if a message to a Bridge deviates from the schema\n\t// for that message sufficiently that it could not be processed.\n\tMalformedMessage string\n}{\n\tResponseTimedOut: \"ResponseTimedOut\",\n\tAgentDisconnected:      \"AgentDisconnected\",\n\tNotConnectedToBridge: \"NotConnectedToBridge\",\n\tMalformedMessage: \"MalformedMessage\",\n}\n```\n\n</TabItem>\n</Tabs>\n\nContains constants representing the errors that can be encountered when queries are forwarded to a Desktop Agent Bridge, but one or more remote Desktop Agents connected to it disconnects, times-out or a malformed message is encountered while a particular request is in flight. These errors may be returned via the FDC3 API when a Desktop Agent is (or was) connected to a Desktop Agent Bridge.\n\n**See also:**\n\n- [Agent Bridging - Workflows broken by disconnects](../../agent-bridging/spec#workflows-broken-by-disconnects)\n"
  },
  {
    "path": "website/docs/api/ref/Events.md",
    "content": "---\ntitle: Events\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nIn addition to intent and context events, the FDC3 API and PrivateChannel API may be used to listen for other types of events via their `addEventListener()` functions.\n\n## `ApiEvent`\n\nType defining a basic event object that may be emitted by an FDC3 API interface such as DesktopAgent or PrivateChannel. There are more specific event types defined for each interface.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ApiEvent {\n  readonly type: string;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented, as ApiEvent and Fdc3Event definitions are the same, given .NET can not restrict on a string enum. Use IFdc3Event instead\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype ApiEvent struct {\n  Type string \n  Details any\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`FDC3Event`](#fdc3event)\n- [`PrivateChannelEvent`](#privatechannelevent)\n\n## `EventHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype EventHandler = (event: ApiEvent) => void;\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic delegate void Fdc3EventHandler(IFdc3Event fdc3Event);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype EventHandler func(ApiEvent)\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles non-context and non-intent events. Provides the details of the event.\n\nUsed when attaching listeners to events.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n- [`ApiEvent`](#apievent)\n\n## `FDC3EventTypes`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype FDC3EventTypes = \"userChannelChanged\" | \"contextCleared\";\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class Fdc3EventType\n{\n    public const string UserChannelChanged = \"userChannelChanged\";\n    public const string ContextCleared = \"contextCleared\";\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype FDC3EventTypes string\n\nconst (\n\tUserChannelChanged     FDC3EventTypes = \"userChannelChanged\"\n)\n```\n\n</TabItem>\n</Tabs>\n\nType defining valid type strings for DesktopAgent interface events.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n\n## `FDC3Event`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface FDC3Event extends ApiEvent{\n  readonly type: FDC3EventTypes;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3Event\n{\n    public string Type { get; }\n    public object? Details { get; }\n}\n\npublic class Fdc3Event : IFdc3Event\n{\n    public string Type { get; }\n    public object? Details { get; }\n\n    public Fdc3Event(string type, object? details = null)\n    {\n        this.Type = type ?? throw new ArgumentNullException(nameof(type));\n        this.Details = details;\n    }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype FDC3Event struct {\n  ApiEvent\n  Type FDC3EventTypes\n}\n```\n\n</TabItem>\n</Tabs>\n\nType representing the format of event objects that may be received via the FDC3 API's `addEventListener` function.\n\nEvents will always include both `type` and `details` properties, which describe the type of the event and any additional details respectively.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n- [`FDC3EventTypes`](#fdc3eventtypes)\n\n### `FDC3ChannelChangedEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface FDC3ChannelChangedEvent extends FDC3Event {\n  readonly type: \"userChannelChanged\";\n  readonly details: {\n    currentChannelId: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3ChannelChangedEventDetails\n{\n    string? CurrentChannelId { get; }\n}\npublic class Fdc3ChannelChangedEventDetails : IFdc3ChannelChangedEventDetails\n{\n    public string? CurrentChannelId { get; }\n\n    public Fdc3ChannelChangedEventDetails(string? channelId)\n    {\n        this.CurrentChannelId = channelId;\n    }\n}\n\npublic class Fdc3ChannelChangedEvent : Fdc3Event\n{\n    public Fdc3ChannelChangedEvent(string? channelId)\n        : base(Fdc3EventType.UserChannelChanged, new Fdc3ChannelChangedEventDetails(channelId))\n    {\n    }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype FDC3ChannelChangedEvent struct {\n  FDC3Event\n  Details FDC3ChannelChangedEventDetails\n}\n\ntype FDC3ChannelChangedEventDetails struct {\n  currentChannelId *string\n}\n```\n\n</TabItem>\n</Tabs>\n\nType representing the format of `userChannelChanged`  events.\n\nThe identity of the channel joined is provided as `details.currentChannelId`, which will be `null` if the app is no longer joined to any channel.\n\n### `FDC3ContextClearedEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nexport interface FDC3ContextClearedEvent extends FDC3Event {\n  readonly type: 'contextCleared';\n  readonly details: {\n    type: string | null;\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3ContextClearedEventDetails\n{\n    string? ContextType { get; }\n}\npublic class Fdc3ContextClearedEventDetails : IFdc3ContextClearedEventDetails\n{\n    public string? ContextType { get; }\n\n    public Fdc3ContextClearedEventDetails(string? contextType)\n    {\n        this.ContextType = contextType;\n    }\n}\n\npublic class Fdc3ContextClearedEvent : Fdc3Event\n{\n    public Fdc3ContextClearedEvent(string? contextType)\n        : base(Fdc3EventType.ContextCleared, new Fdc3ContextClearedEventDetails(contextType))\n    {\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\n\nType representing the format of `contextCleared`  events.\n\nThe specific type of context is defined in the contextType field, which can be empty if we are clearing all the contexts on the channel.\n\n\n## `PrivateChannelEventTypes`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype PrivateChannelEventTypes = \"addContextListener\" | \"unsubscribe\" | \"disconnect\";\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class Fdc3PrivateChannelEventType\n{\n    public const string AddContextListener = \"addContextListener\";\n    public const string Unsubscribe = \"unsubscribe\";\n    public const string Disconnect = \"disconnect\";\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype PrivateChannelEventTypes string \nconst (\n  AddContextListenerPrivateChannelEventType PrivateChannelEventTypes = \"addContextListener\"\n  UnsubscribePrivateChannelEventType PrivateChannelEventTypes = \"unsubscribe\"\n  DisconnectPrivateChannelEventType PrivateChannelEventTypes = \"disconnect\"\n)\n```\n\n</TabItem>\n</Tabs>\n\nType defining valid type strings for Private Channel events.\n\n**See also:**\n\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n\n## `PrivateChannelEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelEvent extends ApiEvent {\n  readonly type: PrivateChannelEventTypes;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3PrivateChannelEventDetails\n{\n    string? ContextType { get; }\n}\npublic class Fdc3PrivateChannelEventDetails : IFdc3PrivateChannelEventDetails\n{\n    public string? ContextType { get; }\n\n    public Fdc3PrivateChannelEventDetails(string? contextType)\n    {\n        this.ContextType = contextType;\n    }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype PrivateChannelEvent struct {\n  ApiEvent\n  Type PrivateChannelEventTypes\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of event objects that may be received via a PrivateChannel's `addEventListener` function.\n\n**See also:**\n\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n- [`PrivateChannelEventTypes`](#privatechanneleventtypes)\n\n### `PrivateChannelAddContextListenerEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelAddContextListenerEvent extends PrivateChannelEvent {\n  readonly type: \"addContextListener\";\n  readonly details: {\n    contextType: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChannelAddContextListenerEvent : Fdc3Event\n{\n    public Fdc3PrivateChannelAddContextListenerEvent(string? contextType)\n        : base(Fdc3PrivateChannelEventType.AddContextListener, new Fdc3PrivateChannelEventDetails(contextType))\n  {\n  }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype PrivateChannelAddContextListenerEvent struct {\n  PrivateChannelEvent\n  Details PrivateChannelAddContextListenerEventDetails\n}\n\ntype PrivateChannelAddContextListenerEventDetails struct {\n  contextType *string\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a context listener being added to the channel (`addContextListener`). Desktop Agents MUST fire this event for each invocation of `addContextListener` on the channel, including those that occurred before this handler was registered (to prevent race conditions).\n\nThe context type of the listener added is provided as `details.contextType`, which will be `null` if all event types are being listened to.\n\n### `PrivateChannelUnsubscribeEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelUnsubscribeEvent extends PrivateChannelEvent {\n  readonly type: \"unsubscribe\";\n  readonly details: {\n    contextType: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChannelUnsubscribeListenerEvent : Fdc3Event\n{\n    public Fdc3PrivateChannelUnsubscribeListenerEvent(string? contextType)\n            : base(Fdc3PrivateChannelEventType.Unsubscribe, new Fdc3PrivateChannelEventDetails(contextType))\n    {\n    }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype PrivateChannelUnsubscribeEvent struct {\n  PrivateChannelEvent\n  Details PrivateChannelUnsubscribeEventDetails\n}\n\ntype PrivateChannelUnsubscribeEventDetails struct {\n  contextType *string\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a context listener removed from the channel (`Listener.unsubscribe()`). Desktop Agents MUST call this when `disconnect()` is called by the other party, for each listener that they had added.\n\nThe context type of the  listener removed is provided as `details.contextType`, which will be `null` if all event types were being listened to.\n\n### `PrivateChannelDisconnectEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nexport interface PrivateChannelDisconnectEvent extends PrivateChannelEvent {\n  readonly type: \"disconnect\";\n  readonly details: null | undefined;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChanneDisconnectEvent : Fdc3Event\n{\n    public Fdc3PrivateChanneDisconnectEvent()\n        : base(Fdc3PrivateChannelEventType.Disconnect)\n    {\n    }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype PrivateChannelDisconnectEvent struct {\n  PrivateChannelEvent\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a remote app being terminated or is otherwise disconnecting from the PrivateChannel. This event is fired in addition to unsubscribe events that will also be fired for any context listeners the disconnecting app had added.\n\nNo details are provided.\n"
  },
  {
    "path": "website/docs/api/ref/GetAgent.md",
    "content": "---\nid: GetAgent\nsidebar_label: GetAgent\ntitle: GetAgent\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nThe `getAgent()` function is the recommended way for **web applications** to connect to an FDC3 Desktop Agent. The function is exported by the [`@finos/fdc3`](https://www.npmjs.com/package/@finos/fdc3) NPM module and returns a [Desktop Agent](./DesktopAgent) implementation:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript\">\n\n```ts\nimport { getAgent, DesktopAgent, AgentError } from \"@finos/fdc3\";\n\ntry {\n    const desktopAgent: DesktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e: AgentError) {\n    // Failed to connect\n}\n```\n\n</TabItem>\n<TabItem value=\"js\" label=\"JavaScript\">\n\n```js\nimport { getAgent } from \"@finos/fdc3\";\n\ntry {\n    const desktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e) {\n    // Failed to connect\n}\n```\n\n</TabItem>\n</Tabs>\n\nThe  `getAgent()` function allows web applications to retrieve an FDC3 Desktop Agent API interface to work with, whether they are running in an environment that supports a Desktop Agent Preload (a container-injected API implementation) or a Desktop Agent Proxy (a Browser-based Desktop Agent running in another window or frame). The behavior of `getAgent()` is defined by the [FDC3 Web Connection Protocol (WCP)](../specs/webConnectionProtocol) and communication with a Desktop Agent Proxy in a web-browser is defined by the [Desktop Agent Communication Protocol (DACP)](../specs/desktopAgentCommunicationProtocol). Hence, it allows applications to be written that will work in either scenario without modification or the inclusion of vendor-specific libraries.\n\nTo handle situations where no Desktop Agent is found, a failover function may be supplied by an app allowing it to start or otherwise connect to a Desktop Agent (e.g. by loading a proprietary adaptor that returns a `DesktopAgent` implementation or by creating a window or iframe of its own that will provide a Desktop Agent Proxy).\n\nThe definition of the `getAgent()` function is as follows:\n\n```ts\ntype GetAgentType = ( \n  params?: GetAgentParams,  \n) => Promise<DesktopAgent>; \n```\n\nA small number of arguments are accepted that can affect the behavior of `getAgent` and to provide a fallback in case a Desktop Agent is not found, allowing the application to start its own agent or use another mechanism (such as a proprietary adaptor) to connect to one.\n\n```ts\n/** \n * @typedef {Object} GetAgentParams Type representing parameters passed to the \n * getAgent function. \n * \n * @property {number} timeoutMs Number of milliseconds to allow for an FDC3\n * implementation to be found before calling the failover function or\n * rejecting (default 1000). Note that the timeout is cancelled as soon as a\n * Desktop Agent is detected. There may be additional set-up steps to perform\n * which will happen outside the timeout.\n * \n * @property {string} identityUrl The app's current URL is normally sent to\n * a web-based desktop agent to help establish its identity. This property\n * may be used to override the URL sent (to handle situations where an app's\n * URL is not sufficiently stable to use for identity purposes,  e.g. due to\n * client-side route changes when navigating within the app). The URL set MUST\n * match the origin of the application (scheme, hostname, and port) or it will\n * be ignored. If not specified, the app's current URL will be used.\n * \n * @property {boolean} channelSelector Flag indicating that the application\n * needs access to a channel selector UI (i.e. because it supports User Channels\n * and does not implement its own UI for selecting channels). Defaults to \n * `true`. MAY be ignored by Desktop Agent Preload (container) implementations.\n * \n * @property {boolean} intentResolver Flag indicating that the application\n * needs access to an intent resolver UI (i.e. because it supports raising one\n * or more intents and and does not implement its own UI for selecting target\n * apps). Defaults to `true`. MAY be ignored by Desktop Agent Preload (container)\n * implementations. \n * \n * @property {boolean} dontSetWindowFdc3 For backwards compatibility, `getAgent`\n * will set a reference to the Desktop Agent implementation at `window.fdc3`\n * if one does not already exist, and will fire the fdc3Ready event. Defaults to\n * `false`. Setting this flag to `true` will inhibit that behavior, leaving \n * `window.fdc3` unset.\n * \n * @property {function} failover An optional function that provides a\n * means of connecting to or starting a Desktop Agent, which will be called\n * if no Desktop Agent is detected. Must return either a Desktop Agent\n * implementation directly (e.g. by using a proprietary adaptor) or a\n * WindowProxy (e.g a reference to another window returned by `window.open`\n * or an iframe's `contentWindow`) for a window or frame in which it has loaded\n * a Desktop Agent or suitable proxy to one that works with FDC3 Web Connection\n * and Desktop Agent Communication Protocols.\n * \n * @property {GetAgentLogLevels} logLevels Settings that determine what should\n * will logged by the getAgent() implementation and DesktopAgentProxy to the \n * JavaScript console.\n */\ntype GetAgentParams = { \n    timeoutMs?: number, \n    identityUrl?: string, \n    channelSelector?: boolean, \n    intentResolver?: boolean,\n    dontSetWindowFdc3?: boolean,\n    failover?: (args: GetAgentParams) => Promise<WindowProxy | DesktopAgent>,\n    logLevels?: GetAgentLogLevels;\n};\n\n/** \n * The default timeout used by getAgent when discovering Desktop Agents.\n */\nconst DEFAULT_GETAGENT_TIMEOUT_MS = 1000;\n\n/**\n * @typedef {Object} GetAgentLogLevels Type representing log-level parameters \\\n * passed to the getAgent function that control what is logged to the JavaScript\n * console by the getAgent() implementation and any DesktopAgentProxy it creates.\n *\n * @property {boolean} connection Log-level for messages relating to establishing\n * a connection to the Desktop Agent (default INFO).\n * \n * @property {boolean} proxy Log-level for messages from a DesktopAgentProxy\n * created by getAgent. These include log of messages sent or received from the \n * DesktopAgent at the INFO level and heartbeat messages at the DEBUG level \n * (default WARN).\n * \n */\ntype GetAgentLogLevels = {\n  connection: LogLevel,\n  proxy: LogLevel\n};\n\n/**\n * Type representing the different log-levels that can be set.\n */\nenum LogLevel {\n  NONE = 0,\n  ERROR = 1,\n  WARN = 2,\n  INFO = 3,\n  DEBUG = 4,\n}\n```\n\n:::note\n\nAs web applications can navigate to or be navigated by users to different URLs and become different applications, validation of an app's identity is necessary. The web application's current URL is passed to web browser-based Desktop Agents to allow them to establish the app's identity - usually connecting it with an App Directory record already known to the Desktop Agent. For more details on identity validation see the identity validation section of the  [Web Connection Protocol (WCP)](../specs/webConnectionProtocol).\n\n:::\n\nFinally, if there is still no Desktop Agent available, or an issue prevents connection to it, the `getAgent()` function will reject its promise with a message from the [`AgentError`](./Errors#agenterror) enumeration.\n\n## Injected iframes for adaptors and user interfaces\n\nThe `getAgent()` function may try to create hidden iframes within an application window in order to load either an adaptor to a Desktop Agent, or Intent Resolver and Channel Selector user interfaces when needed. The iframes are used in order to sandbox the relevant software, and are communicated with securely via the HTML Standard's Channel Messaging API ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API), [HTML Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html)).\n\n:::warning\n\nThe [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Where these are used, please ensure that they allow the loading of content from the domains of Desktop Agents and UI implementations that you wish to work with (including [fdc3.finos.org](https://fdc3.finos.org/) where the reference Intent Resolver and Channel Selector UIs may be loaded from).\n\n:::\n\n## Failover function\n\nDesktop Agent retrieval can time out, for instance if the DA doesn't exist or is unresponsive. The default timeout of 750 milliseconds can be overridden by setting the `timeoutMs` parameter. An application may also provide a failover function which will be called if an interface cannot be retrieved or times out.\n\nExample: Decreasing the timeout and providing a failover function\n\n```js\n    const desktopAgent = await getAgent({\n        timeoutMs: 250,\n        failover: async (params: GetAgentParams) => {\n            // return WindowProxy | DesktopAgent\n        }\n    }); \n```\n\nThe failover function allows an application to provide a backup mechanism for connecting to a DA. It is called only when establishment through normal procedures fails or times out.\n\n:::note\n\nIf you wish to _completely override FDC3's standard discovery mechanisms_, then do not use a failover function. Instead, simply skip the `getAgent()` call and provide your own DesktopAgent object.\n\n:::\n\nFailover functions MUST be asynchronous and MUST resolve to one of the following types:\n\n1. [`DesktopAgent`](./DesktopAgent)\n  The application may choose to directly import or load code that provides a `DesktopAgent` implementation. `getAgent()` will then resolve to the provided `DesktopAgent`.\n2. [`WindowProxy`](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object) ([MDN](https://developer.mozilla.org/en-US/docs/Glossary/WindowProxy))\n  The application may open a window or create a hidden iframe which may then provide access to a compliant browser-resident DA. Ensure that the iframe has loaded (listen for the `load` event) or for separate windows allow a suitable timeout for the window load, then resolve to the `WindowProxy` object for the window or iframe. The `getAgent()` call will then use the supplied `WindowProxy` to establish a connection.\n\n## Persisted Connection Data\n\nThe `getAgent()` function uses [`SessionStorage`](https://html.spec.whatwg.org/multipage/webstorage.html) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)) to persist information on an instance of an app and how it connected to a Desktop Agent in order to ensure a consistent connection type and `instanceId` when reconnecting after navigation or refresh events.\n\n:::warning\nApps do not need to and SHOULD NOT interact with data persisted in SessionStorage by `getAgent` directly, rather it is set and used by the `getAgent()` implementation.\n:::\n\nSessionStorage is used as for persistence as it is scoped to a single browser window and the current origin, ensuring apps in different windows or on different origins access different storage. However, as multiple iframes from the same-domain embedded within a window can share a SessionStorage instance, and multiple applications can be hosted on the same origin and be navigated to and from within a window, additional scoping is applied.\n\nTo differentiate storage for multiple iframes the name of the browsing context (`window.name`) is used to generate the key used in SessionStorage by concatenating the string `\"FDC3-Desktop-Agent-Details-\"` with `window.name`. The `window.name` remains stable during same-origin navigation and is persisted by the browser in its [session history](https://html.spec.whatwg.org/multipage/nav-history-apis.html#nav-traversal-apis) and is appropriate for scoping to a particular browsing context (window or iframe). Desktop Agents should assign a unique name to each window and iframe when they are created to facilitate such scoping. If no name is assigned, then the `getAgent` will assign a UUID as a unique name for that browsing context.\n\nThe data persisted is structured as an object conforming to the `SessionStorageFormat` type below, with the `identityUrl` of the app used as the key (if no `identityUrl` is provided the `actualUrl` is used instead), with the value conforming to the `DesktopAgentDetails` type. Hence, the data might be retrieved as follows:\n\n```ts\nconst sessionData: SessionStorageFormat = sessionStorage.get(\"FDC3-Desktop-Agent-Details-myWindowName\");\nconst agentDetails: DesktopAgentDetails = sessionData[\"myApIdentityUrl\"];\n```\n\n### Type Definitions\n\n```ts\n/** Type representing the format of data stored by `getAgent`\n *  in Session Storage. The `identityUrl` of each app is used\n *  as the key. */\ntype SessionStorageFormat = {\n    /** */\n    [key: string]: DesktopAgentDetails\n}\n\n/** Type representing data on the Desktop Agent that an app \n *  connected to that is persisted by the getAgent function \n *  to be used when re-connecting (after a navigation or  \n *  refresh event) and to ensure a consistent instanceId.  \n */ \ntype DesktopAgentDetails = { \n    /** The type of Desktop Agent connected to. Used to  \n     *  prevent an inadvertent switch to a different agent.*/ \n    agentType: WebDesktopAgentType,\n\n    /** The URL that was previously sent to the Desktop Agent \n     * to establish the app's identity.*/ \n    identityUrl?: string,\n\n    /** The current URL at the time of the last connection to \n     * a Desktop Agent.*/ \n    actualUrl?: string,\n\n    /** Optional URL field that should be used to store any \n     *  URL that was used to connect to a Desktop Agent. URLs \n     *  may have been provided by a parent window that has since \n     *  gone away and persisting may allow re-connection in such \n     *  cases. */ \n    agentUrl?: string,\n\n    /** The appId that was identified for the application by the \n     * Desktop Agent.*/ \n    appId: string,\n\n    /** The instanceId that was issued to the app by the Desktop  \n     * Agent. */ \n    instanceId: string,\n\n    /** The instanceUuid that was issued to the app. This should be \n     *  passed when connecting to the Desktop Agent to help  \n     *  identify that this app has connected before and which  \n     *  instance it is, enabling the Desktop Agent to reissue \n     *  the same instanceId. The instanceUuid should never be shared \n     *  with other applications and is not available through the \n     *  FDC3 API, allowing it to be used as a shared secret with \n     *  the Desktop Agent that issued the associated instanceId.*/ \n    instanceUuid: string \n} \n \n/** Enumeration of values used to describe types of web-based \n *  Desktop Agent. Each 'type' refers to the means by which \n *  a connection to the agent is made and/or an interface to it \n *  received. */ \nenum WebDesktopAgentType { \n    /** Denotes Desktop Agents that inject the FDC3 interface  \n     *  at `window.fdc3`. */ \n    Preload = \"PRELOAD\",\n\n    /** Denotes Desktop Agents that run (or provide an interface) \n     *  within a parent window or frame, a reference to which  \n     *  will be found at `window.opener`, `window.parent`, \n     * `window.parent.opener` etc. */ \n    ProxyParent = \"PROXY_PARENT\",\n\n    /** Denotes Desktop Agents that are connected to by loading a URL \n     *  into a hidden iframe whose URL was returned by a parent window\n     * or frame. */ \n    ProxyUrl = \"PROXY_URL\",\n\n    /** Denotes a Desktop Agent that was returned by a failover \n     * function that was passed by the application. */ \n    Failover = \"FAILOVER\" \n}\n\nconst DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX = 'fdc3-desktop-agent-details';\n```\n"
  },
  {
    "path": "website/docs/api/ref/Metadata.md",
    "content": "---\ntitle: Metadata\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations return various types of metadata.\n\n## `AppIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppIntent {\n  /** Details of the intent whose relationship to resolving applications is\n   *  being described.\n   */\n  readonly intent: IntentMetadata;\n\n  /** Details of applications that can resolve the intent. */\n  readonly apps: Array<AppMetadata>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppIntent\n{\n  /// <summary>\n  /// Details of the intent whose relationship to resolving application is\n  /// being described.\n  /// </summary>\n  IIntentMetadata Intent { get; }\n\n  /// <summary>\n  /// Details of applications that can resolve the intent.\n  /// </summary>\n  IEnumerable<IAppMetadata> Apps { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype AppIntent struct {\n  // Details of the intent whose relationship to resolving applications is being described.\n  Intent IntentMetadata `json:\"intent\"`\n\n  // Details of applications that can resolve the intent.\n  Apps   []AppMetadata  `json:\"apps\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nAn interface that represents the binding of an intent to apps, returned as part of intent discovery.\nFor each intent, it reference the applications that support that intent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`IntentMetadata`](#intentmetadata)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `AppMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppMetadata extends AppIdentifier {\n  /**\n   *  The 'friendly' app name. This field was used with the `open` and\n   *  `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier`\n   *  with `appId` set. \n   * \n   *  Note that for display purposes the `title` field should be used, if set,\n   *  in preference to this field.\n   */\n  readonly name?: string;\n\n  /** The version of the application. */\n  readonly version?: string;\n\n  /** An optional set of, implementation specific, metadata fields that can be\n   *  used to disambiguate instances, such as a window title or screen position.\n   *  Must only be set if `instanceId` is set. \n   */\n  readonly instanceMetadata?: Record<string, any>;\n\n  /** A more user-friendly application title that can be used to render UI\n   *  elements.\n   */\n  readonly title?: string;\n\n  /** A tooltip for the application that can be used to render UI elements. */\n  readonly tooltip?: string;\n\n  /** A longer, multi-paragraph description for the application that could\n   *  include mark-up.\n   */\n  readonly description?: string;\n\n  /** A list of icon URLs for the application that can be used to render UI \n   *  elements.\n   */\n  readonly icons?: Array<Icon>;\n\n  /** Images representing the app in common usage scenarios that can be used to render UI elements */\n  readonly screenshots?: Array<Image>;\n  \n  /** The type of result returned for any intent specified during resolution. \n   *  May express a particular context type (e.g. \"fdc3.instrument\"), channel \n   *  (e.g. \"channel\") or a channel that will receive a specified type \n   *  (e.g. \"channel<fdc3.instrument>\").\n   */\n  readonly resultType?: string | null;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppMetadata : IAppIdentifier\n{\n    /// <summary>\n    /// The unique app name that can be used with the open and raiseIntent calls.\n    /// </summary>\n    string? Name { get; }\n\n    /// <summary>\n    /// The Version of the application.\n    /// </summary>\n    string? Version { get; }\n\n    /// <summary>\n    /// A more user-friendly application title that can be used to render UI elements.\n    /// </summary>\n    string? Title { get; }\n\n    /// <summary>\n    /// A tooltip for the application that can be used to render UI elements.\n    /// </summary>\n    string? Tooltip { get; }\n\n    /// <summary>\n    /// A longer, multi-paragraph description for the application that could include markup.\n    /// </summary>\n    string? Description { get; }\n\n    /// <summary>\n    /// A list of icon URLs for the application that can be used to render UI elements.\n    /// </summary>\n    IEnumerable<IIcon> Icons { get; }\n\n    /// <summary>\n    /// A list of image URLs for the application that can be used to render UI elements.\n    /// </summary>\n    IEnumerable<IImage> Screenshots { get; }\n\n    /// <summary>\n    /// The type of output returned for any intent specified during resolution. May express a particular context type,\n    /// channel, or channel with specified type\n    /// </summary>\n    string? ResultType { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype AppMetadata struct {\n  AppIdentifier\n  // The unique app name that can be used with the open and raiseIntent calls.\n  Name             string                 `json:\"name\"`\n  // The Version of the application.\n  Version          string                 `json:\"version\"`\n  // A more user-friendly application title that can be used to render UI elements.\n  Title            string                 `json:\"title\"`\n  // A tooltip for the application that can be used to render UI elements.\n  Tooltip          string                 `json:\"tooltip\"`\n  // A longer, multi-paragraph description for the application that could include markup.\n  Description      string                 `json:\"description\"`\n  // A list of icon URLs for the application that can be used to render UI elements.\n  Icons            []app_dir.Icon         `json:\"icons\"`\n  // A list of image URLs for the application that can be used to render UI elements.\n  Screenshots      []app_dir.Screenshot   `json:\"screenshots\"`\n  // The type of output returned for any intent specified during resolution. May express a particular context type,\n  // channel, or channel with specified type\n  ResultType       string                 `json:\"resultType\"`\n  // An optional set of, implementation specific, metadata fields that can be\n  // used to disambiguate instances, such as a window title or screen position.\n  // Must only be set if `instanceId` is set. \n  InstanceMetadata map[string]interface{} `json:\"instanceMetadata\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nExtends an AppIdentifier, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\n\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\n\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc..\n\n**See also:**\n\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppIntent.apps`](#appintent)\n- [`Icon`](#icon)\n- [`Image`](#image)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## `ContextMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ContextMetadata {\n  /** Identifier for the app instance that sent the context and/or intent. \n   *  @experimental \n   */\n  readonly source: AppIdentifier;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IContextMetadata\n{\n    /// <summary>\n    /// Identifier for the app instance that sent the context and/or intent.\n    /// </summary>\n    IAppIdentifier? Source { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype ContextMetadata struct {\n  // Identifier for the app instance that sent the context and/or intent.\n  Source AppIdentifier `json:\"source\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a context or intent & context received through the `addContextListener` and `addIntentListener` functions. Currently identifies the app that originated the context or intent message.\n\n[`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`ContextHandler`](Types#contexthandler)\n- [`IntentHandler`](Types#intenthandler)\n- [`addIntentListener`](DesktopAgent#addintentlistener)\n- [`addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DisplayMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface DisplayMetadata {\n  /**\n   *  A user-readable name for this channel, e.g: `\"Red\"`. */\n  readonly name?: string;\n\n  /**\n   *  The color that should be associated within this channel when displaying\n   *  this channel in a UI, e.g: `#FF0000`. May be any color value supported by\n   *  CSS, e.g. name, hex, rgba, etc.. */\n  readonly color?: string;\n\n  /**\n   *  A URL of an image that can be used to display this channel. */\n  readonly glyph?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IDisplayMetadata\n{\n    /// <summary>\n    /// A user-readable name for this channel, e.g: Red.\n    /// </summary>\n    string? Name { get; }\n\n    /// <summary>\n    /// The color that should be associated within this channel when displaying this\n    /// channein in a UI, e.g: '0xFF0000'.\n    /// </summary>\n    string? Color { get; }\n\n    /// <summary>\n    /// A URL of an image that can be used to display this channel.\n    /// </summary>\n    string? Glyph { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype DisplayMetadata struct {\n  // A user-readable name for this channel, e.g: Red.\n  Name  string `json:\"name\"`\n  // The color that should be associated within this channel when displaying\n  // this channel in a UI, e.g: `#FF0000`. May be any color value supported by\n  //  CSS, e.g. name, hex, rgba, etc..\n  Color string `json:\"color\"`\n  // A URL of an image that can be used to display this channel.\n  Glyph string `json:\"glyph\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n\n## `Icon`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Icon {\n  src: string;\n  size?: string;\n  type?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIcon\n{\n    /// <summary>\n    /// The icon url\n    /// </summary>\n    string Src { get; }\n    \n    /// <summary>\n    /// The icon dimensions, formatted as '{height}x{width}'\n    /// </summary>\n    string? Size { get; }\n    \n    /// <summary>\n    /// Icon media type. If not present, the Desktop Agent may use the src file extension.\n    /// </summary>\n    string? Type { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype Icon struct {\n  // The icon url\n  Src string  `json:\"src\"`\n  // The icon dimensions, formatted as '{height}x{width}'\n  Size string  `json:\"size\"`\n  // Icon media type. If not present, the Desktop Agent may use the src file extension.\n  Type string  `json:\"type\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a single icon image at a remote URL, used to represent an application in a user interface.\n\nAppMetadata includes an icons property allowing multiple icon types to be specified. Various properties may be used by the Desktop Agent to decide which icon is the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n\"icons\": [\n  {\n    \"src\": \"https://app.foo.icon/app_icons/lowres.webp\",\n    \"size\": \"48x48\",\n    \"type\": \"image/webp\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_icons/hd_hi.svg\",\n    \"size\": \"72x72\",\n    \"type\": \"image/svg+xml\"\n  }\n]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIIcon? icon = appMetadata?.Icons.Where(icon => icon.Size == \"48x48\").First();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nicons := []Icon{\n      {\n        Src: \"https://app.foo.icon/app_icons/lowres.webp\",\n        Size: \"48x48\",\n        Type: \"image/webp\",\n      },\n      {\n        Src: \"https://app.foo.icon/app_icons/hd_hi.svg\",\n        Size: \"72x72\",\n        Type: \"image/svg+xml\",\n      },\n    }\n```\n\n</TabItem>\n</Tabs>\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the icon.\n- **`size`:** The dimensions of the Icon formatted as `<height>x<width>`.\n- **`type`:** The media type of the icon. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `Image`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Image {\n  src: string;\n  size?: string;\n  type?: string;\n  label?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IImage\n{\n    /// <summary>\n    /// The icon url\n    /// </summary>\n    string Src { get; }\n    \n    /// <summary>\n    /// The icon dimensions, formatted as '{height}x{width}'\n    /// </summary>\n    string? Size { get; }\n    \n    /// <summary>\n    /// Icon media type.  If not present, the Desktop Agent may use the src file extension.\n    /// </summary>\n    string? Type { get; }\n\n\n    /// <summary>\n    /// Caption for the image\n    /// </summary>\n    string? Label { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype Image struct {\n  // The icon url\n  Src string `json:\"src\"`\n\t// The icon dimensions, formatted as '{height}x{width}'\n  Size string `json:\"size\"`\n  // Icon media type.  If not present, the Desktop Agent may use the src file extension.\n  Type string `json:\"type\"`\n  // Caption for the image\n  Label string `json:\"label\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a single image at a remote URL, used to represent screenshot images.\n\nAppMetadata includes a screenshots property allowing multiple images to be specified. Various properties may be used by the Desktop Agent to decide which image(s) are the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n\"screenshots\": [\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/dashboard.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Example app dashboard\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/notifications.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Order notifications view\"\n  }\n]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nforeach (IImage image in appMetadata.Screenshots)\n{\n    System.Diagnostics.Debug.WriteLine(image.Src);\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nicons := []Image{\n      {\n        Src: \"https://app.foo.icon/app_screenshots/dashboard.png\",\n        Size: \"800x600\",\n        Type: \"image/png\",\n        Label: \"Example app dashboard\",\n      },\n      {\n        Src: \"https://app.foo.icon/app_screenshots/notifications.png\",\n        Size: \"800x600\",\n        Type: \"image/png\",\n        Label: \"Order notifications view\",\n      },\n    }\n```\n\n</TabItem>\n</Tabs>\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the image.\n- **`size`:** The dimensions of the image formatted as `<height>x<width>`.\n- **`type`:** The media type of the image. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `ImplementationMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ImplementationMetadata {\n  /** The version number of the FDC3 specification that the implementation\n   *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  readonly fdc3Version: string;\n\n  /** The name of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. io.Connect, OpenFin etc.).\n   */\n  readonly provider: string;\n\n  /** The version of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. 5.3.0).\n   */\n  readonly providerVersion?: string;\n\n  /** Metadata indicating whether the Desktop Agent implements optional features of\n   *  the Desktop Agent API.\n   */\n  readonly optionalFeatures: {\n    /** Used to indicate whether the exposure of 'originating app metadata' for\n     *  context and intent messages is supported by the Desktop Agent.*/\n    readonly OriginatingAppMetadata: boolean;\n    /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n     *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n     *  the Desktop Agent.*/\n    readonly UserChannelMembershipAPIs: boolean;\n    /** Used to indicate whether the experimental Desktop Agent Bridging\n     *  feature is implemented by the Desktop Agent.*/\n    readonly DesktopAgentBridging: boolean;\n  };\n\n  /** The calling application instance's own metadata, according to the \n   *  Desktop Agent (MUST include at least the `appId` and `instanceId`).\n   */\n  readonly appMetadata: AppMetadata;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IImplementationMetadata\n{\n    /// <summary>\n    ///  The version number of the FDC3 specification that the implementation provides.\n    ///  The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n    /// </summary>\n    string Fdc3Version { get; }\n\n    /// <summary>\n    /// The name of the provider of the FDC3 Desktop Agent Implementation (e.g. Finsemble, Glue42, OpenFin etc.).\n    /// </summary>\n    string Provider { get; }\n\n    /// <summary>\n    /// The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0).\n    /// </summary>\n    string ProviderVersion { get; }\n\n    /// <summary>\n    /// Metadata indicating whether the Desktop Agent implements optional features of the Desktop Agent API.\n    /// </summary>\n    OptionalDesktopAgentFeatures OptionalFeatures { get; }\n\n    /// <summary>\n    /// The calling application instance's own metadata according to the Desktop Agent\n    /// </summary>\n    IAppMetadata AppMetadata { get; }\n}\n\nclass OptionalDesktopAgentFeatures\n{\n    /// <summary>\n    /// Used to indicate whether the exposure of 'originating app metadata' for context and intent\n    /// messages is supported by the Desktop Agent.\n    /// </summary>\n    public bool OriginatingAppMetadata { get; set; }\n    \n    /// <summary>\n    /// Used to indicate whether the optional 'JoinUserChannel', 'GetCurrentChannel', and 'LeaveCurrentChannel'\n    /// are implemented by the Desktop Agent.\n    /// </summary>\n    public bool UserChannelMembershipAPIs { get; set; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype ImplementationMetadata struct {\n  //  The version number of the FDC3 specification that the implementation provides.\n  //  The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n  Fdc3Version      string `json:\"fdc3Version\"`\n  // The name of the provider of the FDC3 Desktop Agent Implementation (e.g. Finsemble, Glue42, OpenFin etc.).\n  Provider         string `json:\"provider\"`\n  // The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0).\n  ProviderVersion  string `json:\"providerVersion\"`\n  // Metadata indicating whether the Desktop Agent implements optional features of the Desktop Agent API.\n  OptionalFeatures struct {\n    // Used to indicate whether the exposure of 'originating app metadata' for context and intent\n    // messages is supported by the Desktop Agent.\n    OriginatingAppMetadata    bool `json:\"OriginatingAppMetadata\"`\n    // Used to indicate whether the optional 'JoinUserChannel', 'GetCurrentChannel', and 'LeaveCurrentChannel'\n    // are implemented by the Desktop Agent.\n    UserChannelMembershipAPIs bool `json:\"UserChannelMembershipAPIs\"`\n\t} `json:\"optionalFeatures\"`\n  // The calling application instance's own metadata according to the Desktop Agent\n  AppMetadata AppMetadata `json:\"appMetadata\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number and the metadata of the calling application according to the desktop agent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`DesktopAgent.getInfo`](DesktopAgent#getinfo)\n\n## `IntentMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface IntentMetadata {\n  /** The unique name of the intent that can be invoked by the raiseIntent call. */\n  readonly name: string;\n\n  /** Display name for the intent.\n   * @deprecated Use the intent name for display as display name may vary for\n   * each application as it is defined in the app's AppD record.\n   */\n  readonly displayName?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentMetadata\n{\n    /// <summary>\n    /// The unique name of the intent that can be invoked by the raiseIntent call.\n    /// </summary>\n    string Name { get; }\n\n    /// <summary>\n    /// A friendly display name for the intent that should be used to render UI elements.\n    /// </summary>\n    string DisplayName { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype IntentMetadata struct {\n  // The unique name of the intent that can be invoked by the raiseIntent call.\n  Name        string `json:\"name\"`\n  \n  // A friendly display name for the intent that should be used to render UI elements.\n  DisplayName string `json:\"displayName\"`\n}\n\n```\n\n</TabItem>\n</Tabs>\n\nThe interface used to describe an intent within the platform.\n\n**See also:**\n\n- [`AppIntent.intent`](#appintent)\n\n## `IntentResolution`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface IntentResolution {\n\n  /** Identifier for the app instance that was selected (or started) to resolve\n   *  the intent. `source.instanceId` MUST be set, indicating the specific app \n   *  instance that received the intent.\n   */\n  readonly source: AppIdentifier;\n\n  /** The intent that was raised. May be used to determine which intent the user\n   *  chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  readonly intent: string;\n  \n  /** Retrieves a promise that will resolve to `Context` data returned \n   *  by the application that resolves the raised intent, a `Channel` \n   *  established and returned by the app resolving the intent or void. \n   * \n   *  A `Channel` returned MAY be of the `PrivateChannel` type. The \n   *  client can then `addContextListener()` on that channel to, for example, \n   *  receive a stream of data.\n   * \n   *  If an error occurs (i.e. an error is thrown by the handler function,\n   *  the promise it returns is rejected, or the promise resolved to an invalid \n   *  type) then the Desktop Agent MUST reject the promise returned by the \n   *  `getResult()` function of the `IntentResolution` with a string from\n   *  the `ResultError` enumeration.\n   */\n   getResult(): Promise<IntentResult>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentResolution\n{\n    /// <summary>\n    /// The application that resolved the intent.\n    /// </summary>\n    IAppIdentifier Source { get; }\n\n    /// <summary>\n    /// The intent that was raised.\n    /// </summary>\n    string Intent { get; }\n\n    /// <summary>\n    /// The version number of the Intents schema being used.\n    /// </summary>\n    string? Version { get; }\n\n    Task<IIntentResult> GetResult();\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype IntentResolution struct {\n  // The application that resolved the intent.\n  Source  AppIdentifier `json:\"source\"`\n  // The intent that was raised.\n  Intent  string        `json:\"intent\"`\n  // The version number of the Intents schema being used.\n  Version string        `json:\"version\"`\n}\n\ntype IntentResult any\n\nfunc (ir *IntentResolution) GetResult() <-chan Result[IntentResult] {\n  // implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// Resolve a \"Chain\" type intent\nlet resolution = await agent.raiseIntent(\"intentName\", context);\n\n// Use metadata about the resolving app instance to target a further intent\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //Some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err: ResolveError) { ... }                                    \n                                               \n//Resolve a \"Client-Service\" type intent with a data or channel response\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n    const result = await resolution.getResult();\n    if (result && result.broadcast) { //detect whether the result is Context or a Channel\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\n    } else if (result){\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n    } else {\n        console.error(`${resolution.source} didn't return anything`);\n    }\n} catch(error: ResultError) {\n    console.error(`${resolution.source} returned an error: ${error}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        var listener = await channel.AddContextListener<IContext>(\"price\", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote));\n\n        //if it's a PrivateChannel\n        if (channel is IPrivateChannel privateChannel)\n        {\n            privateChannel.OnDisconnect(() => {\n                System.Diagnostics.Debug.WriteLine(\"Quote feed went down\");\n            });\n\n            // Sometime later...\n            listener.Unsubscribe();\n        }\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\" {resolution.Source} did not return a channel\");\n    }\n}\ncatch (Exception ex)\n{\n    // Handle exception\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresolutionResult := <-desktopAgent.RaiseIntent(\"QuoteStream\", context, nil)\nif resolutionResult.Err != nil {\n  // handle error \n}\nif channel, ok := resolutionResult.Value.(Channel); ok {\n    log.Println(\"The result is a channel\")\n} else if context, ok := resolutionResult.Value.(Context); ok {\n    log.Println(\"The result is a context\")\n} else {\n  log.Error(\"The result is of incorrect data type!\")\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`IntentResult`](Types#intentresult)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`AppIdentifier`](Types#appidentifier)\n"
  },
  {
    "path": "website/docs/api/ref/PrivateChannel.md",
    "content": "---\nid: PrivateChannel\nsidebar_label: PrivateChannel\ntitle: PrivateChannel\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `PrivateChannel`\n\nObject representing a private context channel, which is intended to support secure communication between applications, and extends the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface  PrivateChannel extends Channel {\n  // functions\n  addEventListener(type: PrivateChannelEventTypes  | null, handler: EventHandler): Promise<Listener>;\n  disconnect(): Promise<void>;\n\n  //deprecated functions\n  onAddContextListener(handler: (contextType?: string) => void): Listener;\n  onUnsubscribe(handler: (contextType?: string) => void): Listener;\n  onDisconnect(handler: () => void): Listener;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IPrivateChannel : IChannel, IIntentResult\n{\n    //functions\n    Task<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n\n    //deprecated functions\n    IListener OnAddContextListener(Action<string?> handler);\n    IListener OnUnsubscribe(Action<string?> handler);\n    IListener OnDisconnect(Action handler);\n    void Disconnect();\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n@experimental\ntype PrivateChannel struct {\n    Channel\n}\n\n@experimental\nfunc (privateChannel *PrivateChannel) AddEventListener(eventType *PrivateChannelEventTypes, handler EventHandler) <-Result[Listener] {\n    // Implementation here\n}\n\n@experimental\nfunc (privateChannel *PrivateChannel) Disconnect() <-Result[any]  {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## Examples\n\n### 'Server-side' example\n\nThe intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextListener()` on that channel, the intent app receives notice via the handler added with `addEventListener()` and knows that the client is ready to start receiving quotes.\n\nThe Desktop Agent knows that a channel is being returned by inspecting the object returned from the handler (e.g. check constructor or look for private member).\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const channel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = channel.addEventListener(\"addContextListener\",\n        (event: PrivateChannelAddContextListenerEvent) => {\n            console.log(`remote side added a listener for ${event.contextType}`);\n            // broadcast price quotes as they come in from our quote feed\n            feed.onQuote(symbol, (price) => {\n                channel.broadcast({ type: \"price\", price});\n            });\n        }\n    );\n\n    // This gets called when the remote side calls Listener.unsubscribe()\n    const unsubscribeListener = channel.addEventListener(\"unsubscribe\",\n        (event: PrivateChannelUnsubscribeEvent) => {\n            console.log(`remote side unsubscribed a listener for ${event.contextType}`);\n            feed.stop(symbol);\n        }\n    );\n\n    // This gets called if the remote side closes\n    const disconnectListener = channel.addEventListener(\"disconnect\", \n        () => {\n            console.log(`remote side disconnected`);\n            feed.stop(symbol);\n        }\n    );\n\n    return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n_desktopAgent.AddIntentListener<Instrument>(\"QuoteStream\", async (context, metadata) => {\n  var channel = await _desktopAgent.CreatePrivateChannel();\n  var symbol = context?.ID?.Ticker;\n\n  // This gets called when the remote side adds a context listener\n  var addContextListener = channel.OnAddContextListener((contextType) => {\n      // broadcast price quotes as they come in from our quote feed\n      _feed.OnQuote(symbol, (price) => {\n          channel.Broadcast(new Price(price));\n      });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  var unsubscribeListener = channel.OnUnsubscribe((contextType) => {\n      _feed.Stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  var disconnectListener = channel.OnDisconnect(() => {\n      _feed.stop(symbol);\n  });\n  \n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\n<-desktopAgent.AddIntentListener(\"QuoteStream\", func(context types.Context, metadata *ContextMetadata) <-chan IntentResult {\n        channelResult := <-desktopAgent.CreatePrivateChannel()\n        if channelResult.Err != nil {\n            // handle error \n        }\n        var symbol string \n        var exists bool\n        if symbol, exists = context.Id[\"ticker\"]; !exists {\n            // handle not having ticker\n        }\n         // This gets called when the remote side adds a context listener\n        addContextlistenerResult := channelResult.Value.OnAddContextListener(func(contextType *string) {\n            feed.OnQuote(symbol, func(price string) {\n                channelResult.Value.Broadcast(Context{Type:price})\n            })\n        })\n\n        // This gets called when the remote side calls Listener.unsubscribe()\n        unsubscribeListenerResult := channelResult.Value.OnUnsubscribe(func(contextType *string) {\n            feed.Stop(symbol)\n        })\n\n        // This gets called if the remote side closes\n        unsubscribeListenerResult := channelResult.Value.OnDisconnect(func() {\n            feed.Stop(symbol)\n        })\n        result := make(chan types.IntentResult)\n        result <- channelResult.Value\n        return result\n    }\n)\n```\n\n</TabItem>\n</Tabs>\n\n### 'Client-side' example\n\nThe 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. The `onDisconnect()` listener may also be used to clean up when the 'server-side' disconnects the stream.\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const resolution3 = await fdc3.raiseIntent(\"QuoteStream\", { type: \"fdc3.instrument\", id : { ticker: \"AAPL\" } });\n    try {\n        const result = await resolution3.getResult();\n        //check that we got a result and that it's a channel\n        if (result && result.addContextListener) {\n            const listener = result.addContextListener(\"price\", (quote) => console.log(quote));\n                //if it's a PrivateChannel\n                if (result.type == \"private\") {\n                    result.addEventListener(\"disconnect\", () => {\n                        console.warn(\"Quote feed went down\");\n                    });\n\n                   // Sometime later...\n                   await listener.unsubscribe();\n                }\n        } else {\n            console.warn(`${resolution3.source} did not return a channel`);\n        }\n    } catch(channelError) {\n        console.log(`Error: ${resolution3.source} returned an error: ${channelError}`);\n    } catch(resultError: ResultError) {\n          console.log(`Error: ${resolution3.source} returned an error: ${resultError}`);\n    }\n} catch (resolverError: ResolveError) {\n    console.error(`Error: Intent was not resolved: ${resolverError}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        var listener = await channel.AddContextListener<IContext>(\"price\", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote));\n\n        //if it's a PrivateChannel\n        if (channel is IPrivateChannel privateChannel)\n        {\n            privateChannel.OnDisconnect(() => {\n                System.Diagnostics.Debug.WriteLine(\"Quote feed went down\");\n            });\n\n            // Sometime later...\n            listener.Unsubscribe();\n        }\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\" {resolution.Source} did not return a channel\");\n    }\n}\ncatch (Exception ex)\n{\n    // Handle exception\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nresolutionResult := <-desktopAgent.RaiseIntent(\"QuoteStream\", Context{Type:\"fdc3.instrument\", Id: map[string]string{\"ticker\": \"AAPL\"}})\nif resolutionResult.Err != nil {\n    // handle error\n}\n\nresult := resolutionResult.Value.GetResult()\nif channel, ok := result.Value.(Channel); ok {\n    listenerResult := <-channel.AddContextListener(\"price\", func(quote, metadata) => {\n        log.Printf(\"%v\", quote)\n    })\n    if channel.Type == Private {\n        if privateChannel, ok := interface{}(channel).(PrivateChannel); ok {\n            privateChannel.OnDisconnect(() {\n                log.Println(\"Quote feed went down\")\n            })\n        }\n    } else {\n         log.Printf(\"%s did not return a channel\", resolutionResult.Value.Source)\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\n## Functions\n\n### `addEventListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddEventListener(type: PrivateChannelEventTypes  | null, handler: EventHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (privateChannel *PrivateChannel) AddEventListener(eventType *PrivateChannelEventTypes, handler EventHandler) <-Result[Listener] {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nRegister a handler for events from the PrivateChannel. Whenever the handler function is called it will be passed an event object with details related to the event.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// any event type\nconst listener: Listener = await myPrivateChannel.addEventListener(null, \n    (event: PrivateChannelEvent) => {\n        console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n    }\n);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIChannel myPrivateChannel;\nvar listener = await myPrivateChannel.AddEventListener(null, (event) => {\n    System.Diagnostics.Debug.WriteLine($\"Received event ${event.Type}\\n\\tDetails: ${event.Details}\");\n});\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nlistenerResult := AddEventListener(nil, func(event PrivateChannelEvent) {\n    fmt.Printf(\"Received event %v\\n\\tDetails: %v\", event.Type, event.Details)\n})\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Events](./Events)\n- [EventHandler](./Events#eventhandler)\n- [PrivateChannelEvent](./Events#privatechannelevent)\n- [PrivateChannelAddContextListenerEvent](./Events#privatechanneladdcontextlistenerevent)\n- [PrivateChannelUnsubscribeEvent](./Events#privatechannelunsubscribeevent)\n- [PrivateChannelDisconnectEvent](./Events#privatechanneldisconnectevent)\n  \n### `disconnect`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ndisconnect(): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvoid Disconnect();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (privateChannel *PrivateChannel) Disconnect() <-Result[any] {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n  \nMay be called to indicate that a participant will no longer interact with this channel.\n\n## Deprecated Functions\n\n### `onAddContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonAddContextListener(handler: (contextType?: string) => void): Listener;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnAddContextListener(Action<string?> handler);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (privateChannel *PrivateChannel) OnAddContextListener(handler func(contextType *ContextType)) Result[Listener] {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n  \nDeprecated in favour of the async `addEventListener(\"addContextListener\", handler)` function.\n\nAdds a listener that will be called each time that the remote app invokes addContextListener on this channel.\n\n### `onUnsubscribe`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonUnsubscribe(handler: (contextType?: string) => void): Listener;\n```\n  \n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnUnsubscribe(Action<string?> handler);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (privateChannel *PrivateChannel) OnUnsubscribe(handler func(contextType *ContextType)) Result[Listener] {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nDeprecated in favour of the async `addEventListener(\"unsubscribe\", handler)` function.\n\nAdds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added.\n\n### `onDisconnect`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonDisconnect(handler: () => void): Listener;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnDisconnect(Action handler);\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (privateChannel *PrivateChannel) OnDisconnect(handler func()) Result[Listener] {\n    // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nDeprecated in favour of the async `addEventListener(\"disconnect\", handler)` function.\n\nAdds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called.\n"
  },
  {
    "path": "website/docs/api/ref/Types.md",
    "content": "---\ntitle: Types\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations make use of several type declarations.\n\n## `AppIdentifier`\n\nIdentifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.\n\nAn `AppIdentifier` will always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc.. An `appId` is intended to reference a specific record from an [App Directory](../../app-directory/overview), which it uniquely identifies within that App Directory. \n\nThe `appId` may be unqualified or fully-qualified as described in the [API overview](../spec#fully-qualified-appids) and [App Directory](../../app-directory/overview#application-identifiers) Parts of the Standard and may be resolved and used interchangeably as described in the [API overview](../spec#fully-qualified-appids). \n\nIf the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppIdentifier {\n  /** The unique application identifier located within a specific application\n   *  directory instance. An example of an appId might be 'app@sub.root'.\n   */\n  readonly appId: string;\n  \n  /** An optional instance identifier, indicating that this object represents a\n   *  specific instance of the application described.\n   */\n  readonly instanceId?: string;\n\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppIdentifier\n{\n    /// <summary>\n    /// The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\n    /// </summary>\n    string AppId { get; }\n\n    /// <summary>\n    /// An optional instance identifier, indicating that this object represents a specific instance of the application described.\n    /// </summary>\n    string? InstanceId { get; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype AppIdentifier struct {\n  // The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\n  AppId      string `json:\"appId\"`\n  // An optional instance identifier, indicating that this object represents a specific instance of the application described.\n  InstanceId string `json:\"instanceId\"`\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Context`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Context {\n  id?: { [key: string]: string };\n  name?: string;\n  type: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IContext<out T>: IIntentResult, IDynamicContext where T : class\n{\n    T? ID { get; }\n    string? Name { get; }\n    string Type { get; }\n}\n\ninterface IContext : IContext<object>\n{\n}\n\ninterface IDynamicContext\n{\n    /// <summary>\n    /// Underlying message as a dynamic type for accessing all properties without deserialization\n    /// </summary>\n    dynamic? Native { get; set; }\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype Context struct {\n  Type    string                 `json:\"type\"`\n  Name    string                 `json:\"name\"`\n  Id      map[string]string      `json:\"id\"`\n}\n\ntype IContext interface {\n  // TODO: include at least one method in here \n}\n```\n\n</TabItem>\n</Tabs>\n\nThe base interface that all contexts should extend: a context data object adhering to the [FDC3 Context Data specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n**See also:**\n\n- [`ContextHandler`](#contexthandler)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `ContextHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype ContextHandler = (context: Context, metadata?: ContextMetadata) => void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ndelegate void ContextHandler<T>(T context, IContextMetadata? metadata = null) where T : IContext;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype ContextHandler func(IContext, *ContextMetadata)\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles a context event. Optional metadata about the context message, including the app that originated the message, may be provided.\n\nUsed when attaching listeners for context broadcasts.\n\nOptional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DesktopAgentIdentifier`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n/** @experimental */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent.**/\n  readonly desktopAgent: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype DesktopAgentIdentifier struct {\n  DesktopAgent string\n}\n```\n\n</TabItem>\n</Tabs>\n\n(Experimental) Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no app details are available or are appropriate.\n\n**See also:**\n\n* [Agent Bridging - Identifying Desktop Agents Identity and Message Sources](../../agent-bridging/spec#identifying-desktop-agents-identity-and-message-sources)\n\n## `IntentHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise<IntentResult> | void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ndelegate Task<IIntentResult> IntentHandler<T>(T context, IContextMetadata? metadata = null) where T : IContext;\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype IntentHandler func(IContext, *ContextMetadata) <-chan IntentResult\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles a context event and may return a promise of a Context, Channel object or `void` to be returned to the application that raised the intent.\n\nUsed when attaching listeners for raised intents.\n\nOptional metadata about the intent & context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`PrivateChannel`](PrivateChannel)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `IntentResult`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype IntentResult = Context | Channel | void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentResult { /* Marker interface implemented by IContext and Channel */ }\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype IntentResult any\n\ntype IntentResultType string\nconst (\n  ChannelIntentResult        IntentResultType = \"Channel\"\n  ContextIntentResult        IntentResultType = \"Context\"\n  PrivateChannelIntentResult IntentResultType = \"PrivateChannel\"\n)\n```\n\n</TabItem>\n</Tabs>\n\nDescribes results that an Intent handler may return that should be communicated back to the app that raised the intent, via the [`IntentResolution`](Metadata#intentresolution).\n\nRepresented as a union type in TypeScript, however, this type may be rendered as an interface in other languages that both the `Context` and `Channel` types implement, allowing either to be returned by an `IntentHandler`.\n\n**See also:**\n\n- [`Context`](#context)\n- [`Channel`](Channel)\n- [`PrivateChannel`](PrivateChannel)\n- [`IntentHandler`](#intenthandler)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Listener`\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener), [`addContextListener`](DesktopAgent#addcontextlistener) or [`addEventListener`](DesktopAgent#addeventlistener) on the [DesktopAgent](DesktopAgent) object or (PrivateChannel#addeventlistener) on the [PrivateChannel](PrivateChannel) object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Listener {\n  unsubscribe(): Promise<void>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IListener\n{\n    Task Unsubscribe();\n}\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\ntype IListener interface {\n  Unsubscribe()\n}\ntype Listener struct {}\n```\n\n</TabItem>\n</Tabs>\n\n### `unsubscribe`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nunsubscribe(): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"golang\" label=\"Go\">\n\n```go\nfunc (l *Listener) Unsubscribe() {\n  // Implementation here\n}\n```\n\n</TabItem>\n</Tabs>\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`ContextHandler`](Types#contexthandler)\n"
  },
  {
    "path": "website/docs/api/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: API Overview (next)\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nThe role of FDC3 API is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications, standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe following sections examine the API's use-cases and core concepts. The API is fully defined in both subsequent pages of this Part and a full set of TypeScript definitions in the [src](https://github.com/finos/FDC3/tree/main/src/api) directory of the [FDC3 GitHub repository](https://github.com/finos/FDC3/).\n\n## Components\n\n### Desktop Agent\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- io.Connect\n- OpenFin\n- Refinitiv Eikon\n\nAn FDC3-compliant Desktop Agent exposes an FDC3 Standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n### Application\n\nAn application is any endpoint on the desktop that is:\n\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of endpoints include:\n\n- Native Applications\n- Web Applications\n- Headless “services” running on the desktop\n\n## Desktop Agent Implementation\n\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A Desktop Agent MUST provide implementations for the following interfaces:\n\n- [`DesktopAgent`](ref/DesktopAgent)\n- [`Channel`](ref/Channel)\n- [`PrivateChannel`](ref/PrivateChannel)\n- [`Listener`](ref/Types#listener)\n- [Utility types](ref/Types) and [Metadata Objects](ref/Metadata).\n\nThe means to access the main FDC3 API interface (a `DesktopAgent` implementation) is defined separately for each language in which FDC3 is implemented. These definitions are important as they affect whether applications can be written in a vendor agnostic format so that they run under any Standards-conformant implementation.\n\n### Implementation language\n\nFDC3 and the Desktop Agent API it defines are intended to be independent of particular programming languages and platforms and hence the original definitions, produced in TypeScript, may be translated into other languages. However, this also places limitations on the API definitions as they need to be widely implementable in other languages.\n\nSpecifically, the use of ['unions'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of primitive values in API type and metadata objects, or function parameters SHOULD be avoided as they often cannot be replicated in other languages. Unions of more complex types (such as specific [Context](../context/spec#the-context-interface) Types) may be used where a suitable interface is available or can be created to allow the required polymorphism in languages other than TypeScript.\n\nFor implementation details relating to particular languages, and how to access the API in those languages, please see [Supported Platforms](./supported-platforms).\n\n### Standards vs. Implementation\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n\n- Workspace management\n- User identity and SSO\n- Entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n### Inter-Agent Communication\n\nA goal of the FDC3 Standard is that applications running in different Desktop Agent contexts on the same desktop, or operated by the same user, would be able to interoperate and that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context. As Desktop Agent interop is supported by common standards for APIs an app in one Desktop Agent context would not need to know a different syntax to launch or interact with an app in another Desktop Agent context.\n\nInter-agent communication at the API layer may be achieved via the [Desktop Agent Bridging Part of the FDC3 Standard](../agent-bridging/spec) ([@experimental](../fdc3-compliance#experimental-features)), which defines an independent service that Desktop Agents may connect to (via the Bridge Connection Protocol or BCP), and a protocol for the exchange of messages relating to FDC3 API calls (the Bridge Messaging Protocol or BMP). Hence, by implementing support for Desktop Agent Bridging, a platform may extend interop across applications running in multiple Desktop Agent contexts.\n\nDesktop Agent Bridging provides message exchanges and a workflow for performing intent resolution across multiple agents. Hence, app discovery is supported across the agents connected to the bridge for intent-based workflows. Further, as channels are also supported by bridging, context sharing also works across multiple agents.\n\nThere is currently no method of discovering all the apps supported by a Desktop Agent in the FDC3 API nor bridging. Hence, to support launching, via `fdc3.open` across the connected Desktop Agents, application details must be known in advance. This may be achieved by connecting Desktop Agents to the same App Directories.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\n### Desktop Agent API Standard Compliance\n\nAn FDC3 Standard compliant Desktop Agent implementation **MUST**:\n\n- Be able to provide the FDC3 API to applications in accordance with with any requirements defined for that platform, as defined in [Supported Platforms](supported-platforms) and linked specifications:\n  - For web applications this includes:\n    - Implementing the [Browser-Resident Desktop Agent spec](specs/browserResidentDesktopAgents) if it is intended to support apps running in a standard web browser.\n    - Implementing the [Preload Desktop Agent spec](specs/preloadDesktopAgents) if it is intended to support apps running in a container or other environment that supports injecting a global `fdc3` object.\n- Accept as input and return as output data structures that are compatible with the interfaces defined in this Standard.\n- Include implementations of the following [Desktop Agent](ref/DesktopAgent) API functions, as defined in this Standard:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener)\n  - [`addIntentListener`](ref/DesktopAgent#addintentlistener)\n  - [`addEventListener`](ref/DesktopAgent#addeventlistener)\n  - [`broadcast`](ref/DesktopAgent#broadcast)\n  - [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel)\n  - [`findInstances`](ref/DesktopAgent#findinstances)\n  - [`findIntent`](ref/DesktopAgent#findintent)\n  - [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n  - [`getInfo`](ref/DesktopAgent#getinfo)\n  - [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel)\n  - [`getUserChannels`](ref/DesktopAgent#getuserchannels)\n  - [`open`](ref/DesktopAgent#open)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext)\n- Provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to `raiseIntentForContext` that return multiple options), such as a resolver UI.\n  - Intent resolution MUST take into account any specified input or return context types\n  - Requests for resolution to apps returning a channel MUST include any apps that are registered as returning a channel with a specific type.\n- Attempt to [resolve both fully-qualified and unqualified `appId` values](#fully-qualified-appids) received in `AppIdentifier` Objects as parameters to API functions against known fully-qualified or unqualified `appId` values, with results returned indicating the `appId` that was matched against the parameter value.\n- Return (JavaScript or platform appropriate) Error Objects with messages from the [`ChannelError`](ref/Errors#channelerror), [`OpenError`](ref/Errors#openerror), [`ResolveError`](ref/Errors#resolveerror) and [`ResultError`](ref/Errors#resulterror) enumerations as appropriate.\n- Provide an ID for each [`PrivateChannel`](ref/PrivateChannel) created via [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel) and prevent them from being retrieved via [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) by ID.\n- Only require app directories that they connect to to have implemented only the minimum requirements specified in the [App Directory API Part](../app-directory/spec) of this Standard.\n- Provide details of whether they implement optional features of the Desktop Agent API in the `optionalFeatures` property of the [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned by the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function.\n- Allow, by default, at least a 15 second timeout for an application, launched via [`fdc3.open`](../api/ref/DesktopAgent#open), [`fdc3.raiseIntent`](../api/ref/DesktopAgent#raiseintent) or [`fdc3.raiseIntentForContext`](../api/ref/DesktopAgent#raiseintentforcontext) to add any context listener (via [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener)) or intent listener (via [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener)) necessary to deliver context or intent and context to it on launch. This timeout only applies to listeners needed to receive context on launch; further intent and context listeners not required on launch MAY be added later.\n- For web applications: All public methods of FDC3 interface objects (e.g. `DesktopAgent`, `Channel`, `PrivateChannel`, `IntentResolution`) **MUST** be bound to their respective instances (e.g. using `.bind(this)` in constructors) to support correct behavior when methods are destructured in JavaScript.  See [DesktopAgentProxy implementation](../../FDC3/packages/fdc3-agent-proxy/src/DesktopAgentProxy.ts) for a reference.\n\nAn FDC3 Standard compliant Desktop Agent implementation **SHOULD**:\n\n- Support connection to one or more App Directories meeting the [FDC3 App Directory Standard](../app-directory/overview).\n- Qualify `appId` values received from an app directory with the hostname of the app directory server (e.g. `myAppId@name.domain.com`) [as defined in the app directory standard](../app-directory/overview#application-identifiers).\n- Allow applications to register an [`IntentHandler`](ref/Types#intenthandler) for particular Intent and Context type pairs by providing `interop.intents.listensFor` metadata in their AppD record.\n- Adopt the [recommended set of User channel definitions](#recommended-user-channel-set).\n- Ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.\n- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.\n- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.\n\nAn FDC3 Standard compliant Desktop Agent implementation **MAY**:\n\n- Make the Desktop Agent API available through modules, imports, or other means.\n- Support multiple routes for registration of an [`IntentHandler`](ref/Types#intenthandler) by an app to be considered during Intent resolution, including dynamic registration of apps at runtime.\n- Implement the following OPTIONAL [Desktop Agent](ref/DesktopAgent) API functions:\n  - [`joinUserChannel`](ref/DesktopAgent#joinuserchannel)\n  - [`leaveCurrentChannel`](ref/DesktopAgent#leavecurrentchannel)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n- Implement the following deprecated API functions:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener-deprecated) (without a contextType argument)\n  - [`getSystemChannels`](ref/DesktopAgent#getsystemchannels-deprecated) (renamed getUserChannels)\n  - [`joinChannel`](ref/DesktopAgent#joinchannel-deprecated) (renamed joinUserChannel)\n  - [`open`](ref/DesktopAgent#open-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext-deprecated) (deprecated version that addresses apps via `name` field)\n- Make use of a resolver user interface or other suitable procedure to resolve an ambiguous unqualified `appId` value received as part of an `AppIdentifier` passed as a paremeter to an API function. \n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Functional Use Cases\n\n### Open an Application\n\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Requesting Functionality From Another App\n\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3 and is implemented via the raising of [intents](../intents/spec), which represent a desired action, to be performed with a [context](../context/spec) supplied as input.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).  Currently, this is the primary focus in FDC3.\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client. Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n### Send/broadcast Context\n\nOn the financial desktop, applications often want to broadcast [context](../context/spec) to any number of applications.  Context sharing needs to support different groupings of applications, which is supported via the concept of 'channels', over which context is broadcast and received by other applications listening to the channel.  \n\nIn some cases, an application may want to communicate with a single application or service and to prevent other applications from participating in the communication. For single transactions, this can instead be implemented via a raised intent, which will be delivered to a single application that can, optionally, respond with data. Alternatively, it may instead respond with a [`Channel`](ref/Channel) or [`PrivateChannel`](ref/PrivateChannel) over which a stream of responses or a dialog can be supported.\n\n### Retrieve Metadata about the Desktop Agent implementation\n\nAn application may wish to retrieve information about the version of the FDC3 Standard supported by a Desktop Agent implementation and the name of the implementation provider.\n\nSince version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nimport { compareVersionNumbers, versionIsAtLeast } from \"@finos/fdc3\";\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar version = (await _desktopAgent.GetInfo()).Fdc3Version;\n```\n\n</TabItem>\n</Tabs>\n\nThe [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst implementationMetadata = await fdc3.getInfo();\nconst { appId, instanceId } = implementationMetadata.appMetadata;\n\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar implementationMetadata = await _desktopAgent.GetInfo();\nvar appId = implementationMetadata.AppMetadata.AppId;\nvar instanceId = implementationMetadata.AppMetadata.InstanceId;\n```\n\n</TabItem>\n</Tabs>\n\n### Reference apps or app instance(s) and retrieve their metadata\n\nTo construct workflows between applications, you need to be able to reference specific applications and instances of those applications.\n\nFrom version 2.0 of the FDC3 Standard, Desktop Agent functions that reference or return information about other applications do so via an [`AppIdentifier`](ref/Types#appidentifier) type. [`AppIdentifier`](ref/Types#appidentifier) references specific applications via an `appId` from an [App Directory](../app-directory/overview) record and instances of that application via an `instanceId` assigned by the Desktop Agent.\n\nAdditional metadata for an application can be retrieved via the [`fdc3.getAppMetadata(appIdentifier)`](ref/DesktopAgent#getappmetadata) function, which returns an [`AppMetadata`](ref/Metadata#appmetadata) object. The additional metadata may include a title, description, icons, etc., which may be used for display purposes.\n\nIdentifiers for instances of an application may be retrieved via the [`fdc3.findInstances(appIdentifier)`](ref/DesktopAgent#findinstances) function.\n\n#### Fully-Qualified AppIds\n\nAs an `appId` used in an [`AppIdentifier`](ref/Types#appidentifier) might be replicated in other App Directories, it may be made globally unique (fully-qualified) by appending the domain name of the app directory that it references, [as described in the App Directory Part of the Standard](../app-directory/overview#application-identifiers). Fully-qualified `appId` values may be used to resolve the location of the app directory record that defines them using the [host resolution procedure](../app-directory/overview#fully-qualified-appid-namespace-syntax-host-resolution) defined in the App Directory Part of the Standard. For example, an `appId` such as `\"myApplication\"` defined in an App Directory record at `https://appd.example.com/api/appd/v2/apps/myApplication` may be fully qualified as `\"myApplication@appd.example.com\"`. Desktop Agents MAY be configured with details of applications via either unqualified or fully-qualified appIds.\n\nWherever an `appId` is used to refer to a specific application as part of an [`AppIdentifier`](ref/Types#appidentifier), either the unqualified or fully-qualified version of the `appId` MAY be used interchangeably. Desktop Agents receiving an [`AppIdentifier`](ref/Types#appidentifier) as input to an API call such as [`open`](./ref/DesktopAgent#open), [`raiseIntent`](./ref/DesktopAgent#raiseintent), [`raiseIntentForContext`](./ref/DesktopAgent#raiseintentforcontext), [`getAppMetadata`](./ref/DesktopAgent#getappmetadata) or [`findInstances`](./ref/DesktopAgent#findinstances) MUST attempt to resolve the `appId` provided against the list of `appId` values that it is aware of by first matching the `appId` as provided. I.e. if a fully qualified id such as `myapp@appd.example.com` was provided attempt to match the whole string to known fully-qualified `appId` values, or if an unqualified `appId` was provided attempt to match it to known unqualified `appId` values.\n\nIf no exact match is found then a fully-qualified `appId` provided should be split on `@` character and an attempt made to match the unqualified portion to known unqualified `appIds`, ignoring any known fully-qualified `appId` values that were already matched against. Alternatively, if an unqualified `appId` was provided then the known fully-qualified `appId` values should be split on the `@` character and the unqualified appId matched against their unqualified part.\n\nThe matching of an unqualified `appId` value against a set of fully-qualified appIds may result in multiple matches. In such cases, Desktop Agents SHOULD attempt additional resolution via any suitable procedure. For API calls such as [`raiseIntent`](./ref/DesktopAgent#raiseintent) or [`raiseIntentForContext`](./ref/DesktopAgent#raiseintentforcontext) Desktop Agents SHOULD use the same approach as they do for resolving ambiguous intents, for example by displaying an Intent Resolver UI and allowing the user to select the desired application. Alternatively, Desktop Agents MAY apply an alternative procedure such as selecting the first matching `appId` or, in the case of `findInstances`, by returning results for all matching fully-qualified `appId` values. Each of the API calls accepting an [`AppIdentifier`](ref/Types#appidentifier) as input, returns details of the `appId` in its results (i.e. [`AppIdentifier`](ref/Types#appidentifier), [`AppMetadata`](ref/Metadata#appmetadata), [IntentResolution](ref/Metadata#intentresolution)), where the fully-qualified appId matched MUST be used.\n\n## Raising Intents\n\nRaising an Intent is a method for an application to request functionality from another application and, if desired, defer the discovery and launching of the destination app to the Desktop Agent.\n\n### Intents and Context\n\nWhen raising an intent a specific context is provided as input. The type of the provided context may determine which applications can resolve the intent.\n\nA context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents.\n\nTo raise an intent without a context, use the [`fdc3.nothing`](../context/ref/Nothing) context type. This type exists so that applications can explicitly declare that they support raising an intent without a context (when registering an `IntentHandler` or in an App Directory). This type is also used when the context is cleared for the channel. If the optional context type is provided when performing [`clearContext`](ref/Channel.md#clearcontext), that type will be recorded in the field `subType` of [`fdc3.nothing`](../context/ref/Nothing) context type.\n\nAs an alternative to raising a specific intent, you may also raise an unspecified intent with a known context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent and then to raise it with the specified context for resolution.\n\n### Intent Results\n\nAn optional [`IntentResult`](ref/Types#intentresult) may also be returned as output by an application handling an intent. Results may be a single `Context` object, a `Channel` that may be used to send a stream of responses, or `void` (no result). The [`PrivateChannel`](ref/PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via [raising an intent](ref/DesktopAgent#raiseintent).\n\nFor example, an application handling a `CreateOrder` intent might return a context representing the order and including an ID, allowing the application that raised the intent to make further calls using that ID.\n\nAn optional result type is also supported when programmatically resolving an intent via [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext).\n\n### Resolvers\n\nSuccessful delivery of an intent depends first upon the Desktop Agent's ability to \"resolve the intent\" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext) and then raise the intent with a specific target application, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// Find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Find apps to resolve an intent and return a specified context type\nconst appIntent = await fdc3.findIntent(\"ViewContact\", context, \"fdc3.contact\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  try {\n    const result = await resolution.getResult();\n    console.log(`${resolution.source} returned ${JSON.stringify(result)}`);\n  } catch(resultError: ResultError) {\n    console.error(`${resolution.source} returned an error: ${resultError.message}`);\n  }\n} catch(resolveError: ResolveError) {\n  console.error(`${JSON.stringify(appIntent.apps[0])} returned an error: ${resolveError.message}`);\n}\n\n//Find apps to resolve an intent and return a channel\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", context, \"channel\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  try {\n    const result = await resolution.getResult();\n    if (result && result.addContextListener) {\n      result.addContextListener(null, (context) => { \n        console.log(`received context: ${JSON.stringify(context)}`); \n      });\n    } else {\n      console.log(`${resolution.source} didn't return a channel! Result: ${JSON.stringify(result)}`);\n    }\n  } catch(resultError: ResultError) {\n    console.error(`${resolution.source} returned an error: ${resultError.message}`);\n  }\n} catch (resolveError: ResolveError) {\n  console.error(`${JSON.stringify(appIntent.apps[0])} returned an error: ${resolveError.message}`);\n}\n\n//Find apps that can perform any intent with the specified context\nconst appIntents = await fdc3.findIntentsByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Find apps to resolve an intent to start a chat with a given contact\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait _desktopAgent.RaiseIntent(\"StartChat\", context, appIntent.Apps.First());\n\n//Find apps to resolve an intent and return a specified context type\nvar appIntent = await _desktopAgent.FindIntent(\"ViewContact\", context, \"fdc3.contact\");\nvar resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\ntry\n{\n  var result = await resolution.GetResult();\n  System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned ${result}\");\n}\ncatch (Exception ex)\n{\n  System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned an error\");\n}\n\n//Find apps to resolve an intent and return a channel\nvar appIntent = await _desktopAgent.FindIntent(\"QuoteStream\", context, \"channel\");\ntry\n{\n  var resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\n  var result = await resolution.GetResult();\n  if (result is IChannel resolvedChannel)\n  {\n      await resolvedChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n  }\n  else\n  {\n      System.Diagnostics.Debug.WriteLine(\"Did not return a channel\");\n  }\n}\ncatch (Exception ex)\n{\n}\n\n//Find apps that can perform any intent with the specified context\nvar appIntents = await _desktopAgent.FindIntentsByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait _desktopAgent.RaiseIntent(appIntents.First().Intent.Name, context, appIntents.First().Apps.First());\n```\n\n</TabItem>\n</Tabs>\n\nResult context types requested are represented by their type name. A channel may be requested by passing the string `\"channel\"` or a channel that returns a specific type via the syntax `\"channel<contextType>\"`, e.g. `\"channel<fdc3.instrument>\"`. Requesting intent resolution to an app returning a channel MUST include apps that are registered as returning a channel with a specific type.\n\n### Intent Resolution\n\nRaising an intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n#### Resolve\n\n- Intent was resolved unambiguously and the receiving app was launched successfully (if necessary).\n- Intent was ambiguous, a resolution was chosen by the end user, and the chosen application was launched successfully.\n\n#### Reject\n\n- No app matching the intent and context (if specified) was found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n#### Resolution Object\n\nIf the raising of the intent resolves (or rejects), a standard [`IntentResolution`](ref/Metadata#intentresolution) object will be passed into the resolver function with details of the application that resolved the intent and the means to access any results subsequently returned.\n\nFor example, to raise a specific intent:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntent(\"StageOrder\", context);\n}\ncatch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntent(\"StageOrder\", context);\n}\ncatch (Exception ex) { }\n```\n\n</TabItem>\n</Tabs>\n\nor to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntentForContext(context);\n  if (resolution.data) {\n    const orderId = resolution.data.id;\n  }\n} catch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntentForContext(context);\n    if (resolution is IContext resolvedContext)\n    {\n        var orderId = resolvedContext.ID;\n    }\n}\ncatch (Exception ex) { }\n```\n\n</TabItem>\n</Tabs>\n\nUse metadata about the resolving app instance to target a further intent\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntent(\"StageOrder\", context);\n  ...\n\n  //some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntent(\"StageOrder\", context);\n\n    //some time later\n    await _desktopAgent.RaiseIntent(\"UpdateOrder\", context, resolution.Source);\n}\ncatch (Exception ex) {  }\n```\n\n</TabItem>\n</Tabs>\n\nRaise an intent and retrieve either data or a channel from the IntentResolution:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  /* Detect whether the result is Context or a Channel by checking for properties unique to Channels. */\n  if (result && result.broadcast) { \n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result) {\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`);\n  }\n} catch(err: ResultError) {\n  console.error(`${resolution.source} returned a data error: ${err.message}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned a channel with id {channel.Id}\");\n    }\n    else if (result is IContext context)\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned data {context}\");\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} didn't return anything\");\n    }\n}\ncatch (Exception ex)\n{\n    System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned an error\");\n}\n```\n\n</TabItem>\n</Tabs>\n\n### Register an Intent Handler\n\nApplications need to let the system know the intents they can support.  Typically, this SHOULD be done via registration with an [App Directory](../app-directory/spec) by providing `interop.intents.listensFor` metadata. However, Desktop Agent implementations MAY support dynamic registration of an [`IntentHandler`](ref/Types#intenthandler) by an app at runtime (for example, when they add an `IntentListener` via the API) to allow for ad-hoc registration which may be helpful at development time.  Although dynamic registration is not part of this specification, a Desktop Agent agent MAY choose to support any number of registration paths.\n\nWhen an instance of an application is launched, it is expected to add an [`IntentHandler`](ref/Types#intenthandler) function to the Desktop Agent for each intent it has registered by calling the [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) function of the Desktop Agent. Doing so allows the Desktop Agent to pass incoming intents and contexts to that instance of the application. Hence, if the application instance was spawned in response to the raised intent, then the Desktop Agent must wait for the relevant intent listener to be added by that instance before it can deliver the intent and context to it. In order to facilitate accurate error responses, calls to `fdc3.raiseIntent` should not return an `IntentResolution` until the intent handler has been added and the intent delivered to the target app.\n\nIntent handlers SHOULD be registered via [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations. Individual Desktop Agent implementations MAY support longer timeouts or configuration to control or extend timeouts.\n\nA single handler can be added for each specific intent. If the application attempts to call [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) passing the same `intent` a second time, before unsubscribing to the previously added listener, the Desktop Agent MUST reject it with an `Error` Object with the message given by [`ResolveError.IntentListenerConflict`](ref/Errors#resolveerror).\n\n### Originating App Metadata\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered intent handlers. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n\n### Compliance with Intent Standards\n\nIntents 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.\n\nIt is expected that App Directories SHOULD also curate listed apps and ensure that they are complying with declared intents.\n\n## Context Channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\n### Types of Channel\n\nThere are three types of channels, which have different visibility and discoverability semantics:\n\n1. ***User channels***, which:\n\n    - facilitate the creation of user-controlled context links between applications (often via the selection of a color channel),\n    - are created and named by the desktop agent,\n    - are discoverable (via the [`getUserChannels()`](ref/DesktopAgent#getuserchannels) API call),\n    - can be 'joined' (via the [`joinUserChannel()`](ref/DesktopAgent#joinuserchannel) API call).\n\n    :::note\n\n    Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels).\n\n    :::\n\n    :::note\n\n    Earlier versions of FDC3 included the concept of a 'global' system channel\n    which was deprecated in FDC3 1.2 and removed in FDC3 2.0.\n\n    :::\n\n2. ***App channels***, which:\n\n    - facilitate developer controlled messaging between applications,\n    - are created and named by applications (via the [`getOrCreateChannel()`](ref/DesktopAgent#getorcreatechannel) API call),\n    - are not discoverable,\n    - are interacted with via the [Channel API](ref/Channel) (accessed via the desktop agent [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API call)\n\n3. ***Private*** channels, which:\n\n    - facilitate private communication between two parties,\n    - have an auto-generated identity and can only be retrieved via a raised intent.\n\nChannels are interacted with via `broadcast` and `addContextListener` functions, allowing an application to send and receive Context objects via the channel. For User channels, these functions are provided on the Desktop Agent, e.g. [`fdc3.broadcast(context)`](ref/DesktopAgent#broadcast), and apply to channels joined via [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel). For App channels, a channel object must be retrieved, via [`fdc3.getOrCreateChannel(channelName)`](ref/DesktopAgent#getorcreatechannel), which provides the functions, i.e. [`myChannel.broadcast(context)`](ref/Channel#broadcast) and [`myChannel.addContextListener(context)`](ref/Channel#addcontextlistener). For `PrivateChannels`, a channel object must also be retrieved, but via an intent raised with [`fdc3.raiseIntent(intent, context)`](ref/DesktopAgent#raiseintent) and returned as an [`IntentResult`](ref/Types#intentresult).\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are also listening on the channel.\n\n### Joining User Channels\n\nApps can join *User channels*.  An app can only be joined to one User channel at a time.  \n\nWhen an app is joined to a User channel, calls to [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be routed to that channel and listeners added through [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will receive context broadcasts from other apps also joined to that channel. If an app is not joined to a User channel [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be a no-op and handler functions added with  [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will not receive any broadcasts. However, apps can still choose to listen and broadcast to specific channels (both User and App channels) via the methods on the [`Channel`](ref/Channel) class.\n\nWhen an app joins a User channel, or adds a context listener when already joined to a channel, it will automatically receive the current context for that channel, unless the context was cleared through [`clearContext`](ref/Channel.md#clearcontext).\n\nIt is possible that a call to join a User channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinUserChannel()`](ref/DesktopAgent#joinuserchannel), [`fdc3.getCurrentChannel()`](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).\n\nThere SHOULD always be a clear UX indicator of what channel an app is joined to.\n\n#### Examples\n\nTo find a User channel, one calls:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// returns an array of channels\nconst allChannels = await fdc3.getUserChannels();\nconst redChannel = allChannels.find(c => c.id === \"red\");\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar allChannels = await _desktopAgent.GetUserChannels();\nvar redChannel = allChannels.Single(c => c.Id == \"red\");\n```\n\n</TabItem>\n</Tabs>\n\nTo join a User channel, one calls:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfdc3.joinUserChannel(redChannel.id);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nawait _desktopAgent.JoinUserChannel(redChannel.Id);\n```\n\n</TabItem>\n</Tabs>\n\nCalling `fdc3.broadcast` will now route context to the joined channel.\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n\n  > Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels). The `joinChannel` function was also renamed to `joinUserChannel` to clarify that it is only intended to be used to join 'user', rather than 'app', channels.\n\n### Recommended User Channel Set\n\nDesktop Agent implementations SHOULD use the following set of channels, to enable a consistent user experience across different implementations. Desktop Agent implementation MAY support configuration of the user channels.\n\n:::note\nFuture versions of the FDC3 Standard may support connections between desktop agents, where differing user channel sets may cause user experience issues.\n:::\n\n```ts\nconst recommendedChannels = [\n  {\n    id: \"fdc3.channel.1\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 1\",\n      color: \"red\",\n      glyph: \"1\",\n    },\n  },\n  {\n    id: \"fdc3.channel.2\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 2\",\n      color: \"orange\",\n      glyph: \"2\",\n    },\n  },\n  {\n    id: \"fdc3.channel.3\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 3\",\n      color: \"yellow\",\n      glyph: \"3\",\n    },\n  },\n  {\n    id: \"fdc3.channel.4\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 4\",\n      color: \"green\",\n      glyph: \"4\",\n    },\n  },\n  {\n    id: \"fdc3.channel.5\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 5\",\n      color: \"cyan\",\n      glyph: \"5\",\n    },\n  },\n  {\n    id: \"fdc3.channel.6\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 6\",\n      color: \"blue\",\n      glyph: \"6\",\n    },\n  },\n  {\n    id: \"fdc3.channel.7\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 7\",\n      color: \"magenta\",\n      glyph: \"7\",\n    },\n  },\n  {\n    id: \"fdc3.channel.8\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 8\",\n      color: \"purple\",\n      glyph: \"8\",\n    },\n  },\n];\n```\n\n### Direct Listening and Broadcast on Channels\n\nWhile joining User channels (using [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel)) automates a lot of the channel behavior for an app, it has the limitation that an app can only be 'joined' to one channel at a time.  However, an app may instead retrieve an App [`Channel`](ref/Channel) Object via the [`fdc3.getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API, create a [`PrivateChannel`](ref/PrivateChannel) via the [`fdc3.createPrivateChannel`](ref/DesktopAgent#createprivatechannel) API, or by raising an intent that returns a channel created by another app. The `Channel` object may then be used to listen to and broadcast on that channel directly using the [`Channel.addContextListener`](ref/Channel#addcontextlistener) and the [`Channel.broadcast`](ref/Channel#broadcast) APIs. FDC3 imposes no restriction on adding context listeners or broadcasting to multiple channels.\n\n### App Channels\n\nApp Channels are topics dynamically created by applications connected via FDC3. For example, an app may create a named App Channel to broadcast data or status that is specific to that app to other apps that know to connect to the channel with that name.\n\nTo get (or create) a [`Channel`](ref/Channel) reference, then interact with it:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst appChannel = await fdc3.getOrCreateChannel(\"my_custom_channel\");\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nawait appChannel.addContextListener(null, context => {...});\n// broadcast to the channel\nawait appChannel.broadcast(context);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appChannel = await _desktopAgent.GetOrCreateChannel(\"my_custom_channel\");\n// get the current context of the channel\nvar current = await appChannel.GetCurrentContext(null);\n// add a listener\nawait appChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n// broadcast to the channel\nawait appChannel.Broadcast(context);\n```\n\n</TabItem>\n</Tabs>\n\nAn app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// check for current fdc3 channel\nlet joinedChannel = await fdc3.getCurrentChannel()\n//current channel is null, as the app is not currently joined to a channel\n\n//add a context listener for channels we join\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n//retrieve an App channel and add a listener that is specific to that channel\nconst myChannel = await fdc3.getOrCreateChannel(\"my_custom_channel\");\nconst myChannelListener = await myChannel.addContextListener(null, context => { ... });\n\nfdc3.joinUserChannel('blue')\njoinedChannel = await fdc3.getCurrentChannel()\n//current channel is now the 'blue' channel\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar joinedChannel = await _desktopAgent.GetCurrentChannel();\n// current channel is null, as the app is not currently joined to a channel\n\n// add a context listener for channels we join\nvar listener = await _desktopAgent.AddContextListener<IContext>(null, (context, metadata) => { });\n\n// retrieve an App Channel and add a listener that is specific to that channel\nvar myChannel = await _desktopAgent.GetOrCreateChannel(\"my_custom_channel\");\nvar myChannelListener = await myChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n\nawait _desktopAgent.JoinUserChannel(\"blue\");\njoinedChannel = await _desktopAgent.GetCurrentChannel();\n// current channel is now the \"blue\" channel\n```\n\n</TabItem>\n</Tabs>\n\nif another application broadcasts to \"my_custom_channel\" (by retrieving it and broadcasting to it via `myChannel.broadcast()`) then the broadcast will be received by the specific listener (`myChannelListener`) but NOT by the listener for joined channels (`listener`).\n\n### Private Channels\n\nA [`PrivateChannel`](ref/PrivateChannel) is created to support the return of a stream of responses from a raised intent, or private dialog between two applications.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\nThe `PrivateChannel` type also supports synchronization of data transmitted over returned channels. They do so by extending the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\n### Broadcasting and listening for multiple context types\n\nThe [Context specification](../context/spec#assumptions) recommends that complex context objects are defined using simpler context types for particular fields. For example, a `Position` is composed of an `Instrument` and a holding amount. This leads to situations where an application may be able to receive or respond to context objects that are embedded in a more complex type, but not the more complex type itself. For example, a pricing chart might respond to an `Instrument` but doesn't know how to handle a `Position`.\n\nTo facilitate context linking in such situations it is recommended that applications `broadcast` each context type that other apps (listening on a User Channel or App Channel) may wish to process, starting with the simpler types, followed by the complex type. Doing so allows applications to filter the context types they receive by adding listeners for specific context types - but requires that the application broadcasting context make multiple broadcast calls in quick succession when sharing its context.\n\n### Context clearing on channels\nChannel interface provides the ability to [`clearContext`](ref/Channel.md#clearcontext) on the channel, either for the specific context type, if provided, or for all contexts on that channel. Applications may listen to the `contextCleared` event on the channel. If a specific type was cleared, the `contextType` field of the event will be set with that type. Once cleared, any apps that join the channel, add new context listeners or call [`getCurrentContext`](ref/Channel.md#getcurrentcontext) will not return anything to the caller (other than the `fdc3.nothing` type indicating that context was cleared) until new context is broadcast to the channel. \n\n### Originating App Metadata\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered context handlers on all types of channel. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n"
  },
  {
    "path": "website/docs/api/specs/browserResidentDesktopAgents.md",
    "content": "---\nid: browserResidentDesktopAgents\nsidebar_label: Browser Desktop Agents\ntitle: Browser-Resident Desktop Agents (next)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nBrowser Resident Desktop Agents (DAs) are an experimental feature added to FDC3 in 2.2. Limited aspects of their design may change in future versions and they are exempted from the FDC3 Standard's normal versioning and deprecation policies in order to facilitate any necessary change.\n\n:::\n\nThis document specifies the required behavior for Browser-Resident Desktop Agents (DA). Such agents allow FDC3 applications running directly in a browser to participate in FDC3 interop by way of a `getAgent()` function that is provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) and a standardized communication protocol. This approach is in contrast to \"Preload DAs\" which run on technology that allows the FDC3 interface to be injected (such as Electron, WebView2 or a browser-extension based implementation).\n\nThis specification only applies to apps running in a browser and therefore assumes use of JavaScript/TypeScript and HTML APIs. Implementations in other languages such as .NET are not covered.\n\nAlong with this specification, a new general connection strategy has been established for FDC3 compliant web-applications: FDC3 compliant apps SHOULD make use of `getAgent()` function provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) to retrieve their FDC3 interface (an instance of an implementation of the [`DesktopAgent`](../ref/DesktopAgent) interface). Apps that follow these guidelines will be able to interop through either Browser-Resident DAs or [Preload DAs](./preloadDesktopAgents) without the inclusion of code or libraries specific to a particular Desktop Agent vendor or implementation. We refer to this concept as Write Once Run Anywhere (WORA).\n\n:::info\n\nPrior to FDC3 2.2, only [Preload Desktop Agents](./preloadDesktopAgents) were supported.  \n\n:::\n\n:::note\n\nThis document covers the requirements for _implementors of Browser-Resident Desktop Agents_. The `getAgent()` function that applications use to gain access to an FDC3 interface is provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3). Many behavioral details of `getAgent()` are purposefully omitted from this document in order to reduce the required scope of understanding. Please refer to the [getAgent() specification in the FDC3 Web Connection Protocol](webConnectionProtocol.md) for information on how the client side operates or [supported platforms](../supported-platforms) for details of how to access the Desktop Agent API in an application.\n\n:::\n\n:::tip\n\nWhen referencing \"DA\" in the subsequent sections of this document we will hereafter always mean a \"Browser-Resident Desktop Agent\" - code that runs in a browser page (iframe or window) and which conforms to this specification.\n\n:::\n\n## Launching apps\n\nAs a prerequisite for launching an app via FDC3 in the browser, a DA must first exist as running code in a browser window (See failover functions for an exception to this rule), although that code MAY also connect to or rely on remotely hosted services. We will refer to this window as the \"DA Window\".\n\nAs the DA typically acts as a launcher for applications, it will often be the case that the DA window is related to the application window(s) in that it may have created the application window with `window.open()` or have created an iframe and loaded the application URL into it. Hence, the DA window may be referred to as a 'parent' (window or frame) of the application frame and the relationship may be used to implement communication between the frames.\n\n:::note\n\nIt is possible to have multiple DA Windows. For instance, a DA may propagate itself into new windows. Communication and coordination between DA Windows is an implementation detail and is not covered by this specification.\n\n:::\n\nWhen an app runs `getAgent()`, it checks for the existence of `window.parent`, `window.opener` and `window.parent.opener` (and will continue up the chain of parent frames, e.g. `window.parent.parent`, `window.parent.parent.opener` until the reference to the next parent is equal to the current one (e.g. `window.parent.parent === window.parent` indicating that the frame does not have a parent). `getAgent()` will then send a standardized `WCP1Hello` message to each parent window or frame reference via [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) in order to discover a DA.\n\nHence, apps may be launched:\n\n1. By creating iframes in a DA Window\n2. By calling `window.open` from a DA Window\n3. By creating iframes in a window that was opened from a DA Window\n\nand the Desktop Agent application will be found in a 'parent' of the application frame.\n\n## Responding to app instance connections - Web Connection Protocol (WCP)\n\nBrowser Resident DAs MUST call `window.addEventListener(\"message\", ...)` to receive incoming connection requests from apps, in the form of [`\"WCP1Hello\"`](pathname:///schemas/next/api/WCP1Hello.schema.json) messages defined in the [Web Connection Protocol](./webConnectionProtocol).\n\nUpon receiving an incoming [`\"WCP1Hello\"`](pathname:///schemas/next/api/WCP1Hello.schema.json) the Desktop Agent MUST either:\n\n1. Respond with a [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json) message (as defined in the [Web Connection Protocol](./webConnectionProtocol)).\n    - This message indicates that `getAgent()` should create an iframe, load the provided URL (for an adaptor to the Desktop Agent) into it and then restart the connection process by sending [`\"WCP1Hello\"`](pathname:///schemas/next/api/WCP1Hello.schema.json) to the iframe.\n\n    :::warning\n\n    The [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Wherever these are used in app implementations, please advise app implementors to include domains from which the adaptor content is served.\n\n    :::\n2. Create a [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) with two entangled `MessagePort` instances that will be used for further communication with the application.\n    - Before returning one of `MessagePort` instances, the DA MUST set up event listeners to receive and process a [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message from the application.\n    - To deliver the `MessagePort`, the DA MUST respond to the event's `source` window by responding with a [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json) message (as defined in the [Web Connection Protocol](./webConnectionProtocol)) and append `port2` from the `MessageChannel` to the message.\n\nAll further communication is conducted over the `MessageChannel`. The Desktop Agent should consider the newly created port to be inactive until a [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message is received via the `MessagePort` and successfully processed.\n\n### Validating app identity\n\nThe first message received by the Desktop Agent on `MessagePort` `port1` from an application via a `MessageChannel` it created MUST be [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json). Once received and successfully processed, the Desktop Agent should respond with a [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json) message containing an `appId`, `instanceId` and `instanceUuid` to identify the app and this specific instance and then enable processing of [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol.md) messages for this application. If validation fails, it should instead respond with [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityFailedResponse.schema.json) and close the `MessageChannel`.\n\nApp identity is validated and an `appId` assigned by matching the application to an AppD record already known to the Desktop Agent. This is achieved by matching  `identityUrl` (supplied by the application via the `getAgent()` implementation) to the `details.url` field of the known App Directory records.\n\nAs web applications may vary their URL during use, or serve multiple applications from the same origin (differentiated by path, search params and/or hash), care must be taken in matching URLs to AppD records. Two URLs are sent to the Desktop Agent in the [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message:\n\n- `identityUrl`: the URL to match to the App Directory record.\n- `actualUrl`: the current URL of the application, which MUST be captured automatically by the `getAgent()` implementation.\n\nApplications _may_ specify the `identityUrl` value as an argument to `getAgent()`. If not specified, the `getAgent()` implementation MUST use the current URL of the application. The Desktop Agent MUST validate that the origin of the `identityUrl` is the same as the origin of _both_ the `actualUrl` and the `WCPValidateAppIdentity` message sent over the `MessagePort`. The Desktop Agent MUST then match the URL to that of applications known to the Desktop Agent.\n\nThe `actualUrl` field may be used for logging and debug purposes by the Desktop Agent and it differing from the `identityUrl` indicates that the application provided an override via `getAgent()`.\n\nOwing to the fact that the different parts of a URL (origin, path, search parameters, anchor) are used differently by web applications, matching of the `identityUrl` to known application URLs can be more complex than a simple string match. To allow application developers control the requirements of matching, Desktop Agents SHOULD consider a URL to match if all elements (origin, path, search parameters, anchor) present in the App Directory record's URL are present in the `identityUrl`. As multiple App Directory records may match a given identity URL, Desktop Agents SHOULD look for the best match that meets the requirements.\n\nFor example, given an identity URL `url`, and an array of App Directory records `appDRecords`, a Desktop Agent MAY implement matching as follows:\n\n```js\n/** Return the AppD record whose URL best matches the input URL or `null` if no\n *  match is found. To be considered a match all elements of the AppD URL \n *  (origin, path, searchParams and hash) MUST be found in the input URL.\n *  The best match is the AppD URL that contains the most elements from the\n *  input URL.\n */  \nlet matchUrlToAppD = (url, appDRecords) => {\n    //parse the URL\n    const inputUrl = new URL(url);\n\n    //fn to trim trailing / from paths\n    const trimTrailingSlash = (path) => {\n        if (path.endsWith(\"/\")) {\n            const out = path.slice(0, -1);\n            //return null if it was just a /\n            return out === \"\" ? null : out;\n        } else {\n            return path;\n        }\n    };\n                               \n    const matchScores = [];\n\n    //score AppD records based on the match of their URL to the input URL\n    // if any component of the AppD record URL is missing from input URL score 0, \n    // otherwise count the number of input elements matched.\n    appDRecords.map((record) => {\n        //record must contain a URL\n        if (!record.details?.url) { return; }\n        \n        //parse record URL\n        const parsedUrl = new URL(record.details.url);\n        \n        //origin of URL must match record\n        if (parsedUrl.origin !== inputUrl.origin) { return; }\n        let score = 1;\n        \n        //path must match if present in AppD record - Path of \"/\" is ignored\n        const appDPath = trimTrailingSlash(parsedUrl.pathname);\n        if (appDPath) {\n            if (trimTrailingSlash(inputUrl.pathname) != appDPath) {\n                return;\n            } else {\n                score++;\n            }\n        }\n        \n        //hash must match if present in AppD record\n        if (parsedUrl.hash) {\n            if (inputUrl.hash != parsedUrl.hash) {\n                return; \n            } else {\n                score++;\n            }\n        }\n        \n        if (!!parsedUrl.search) {\n            //search params present in AppD record must be present in URL\n            const recordSearchKeys = parsedUrl.searchParams.keys().toArray();\n            for (let i=0; i<recordSearchKeys.length; i++) {\n                const key = recordSearchKeys[i];\n                if (inputUrl.searchParams.get(key) !== parsedUrl.searchParams.get(key)) {\n                    return;\n                }\n            }\n            //count matched input URL search params for scoring\n            inputUrl.searchParams.keys().forEach((key) => {\n                if (parsedUrl.searchParams.get(key) === inputUrl.searchParams.get(key)) {\n                    score++;\n                } \n            });\n        }\n        \n        //everything present in the record was found in the inputUrl\n        matchScores.push([score, record]);\n    });\n    \n    //return the best scoring match (ignore ties)\n    matchScores.sort((a,b) => b[0]-a[0]);\n    return matchScores[0][1] ?? null;\n};\n```\n\n### Validating instance identity\n\nIf the [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) request message contains `instanceId` and `instanceUuid` fields then the window may represent an app instance that has navigated or refreshed and requires reconnecting with the previously assigned `instanceId`. The DA SHOULD reissue the same instanceId if the `instanceUuid`, `appId`, `WindowProxy` object and origin provided **all** match what is already on record and return details via the [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json) message.\n\nIf an `instanceId` and `instanceUuid` are not provided or do not pass the checks defined above, a new `instanceId` and `instanceUuid` should be generated by the Desktop Agent and returned in the [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json) message. All generated `instanceId` and `instanceUuid` values should be retained by the DA (for the session or other appropriate period of time), along with a reference to the `WindowProxy` (`event.source` from the initial message received), as these can later be used for comparison to help determine if a new connection request is coming from a previously connected window which may or may not represent an existing app instance. If a previously connected window is reconnecting, any existing `MessageChannel` instance created for it can be cleaned up.  \n\nDetails of the received `instanceId` and `instanceUuid` are stored by the `getAgent()` implementation in [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) within the application window and are automatically reused when reconnecting to the Desktop Agent. SessionStorage is used as it is scoped to a particular window (rather than origin, as is the case with LocalStorage), allowing separate storage for each app instance.\n\n:::warning\n\nApps launched via a call to `window.open()` from a window or app instance on the same origin can appear to be the original window. This is because browsers may clone SessionStorage for newly opened windows. When a child window calls `getAgent()` with the same `appId`, `instanceId` and `instanceUuid` as the parent window, it will appear to the DA that a navigation event occurred on the parent window. DAs therefore MUST also compare the `WindowProxy` object that is used to establish each connection to differentiate such cloned instances. If the WindowProxy objects do not match, then a new `instanceId` and `instanceUuid` MUST be assigned.\n\n:::\n\nFor more details on the connection process, please see the documentation for the [Web Connection Protocol](./webConnectionProtocol).\n\n### Disconnects\n\nDAs are responsible for tracking when app windows close or navigate, which is necessary to provide accurate responses to the `findIntent`, `findIntentsByContext` & `findInstances` API calls, and to correctly resolve raised intents.\n\n:::info\n\nThe HTML Standard specifies an [onclose event handler on `MessagePort`](https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageport-onclose) which would provide an ideal event-based solution for tracking the closing of app windows. However, this event is not currently implemented in Chrome/Chromium due to security concerns (it reveals the garbage collection activity of the process holding the other end of the pipe, see comment on [whatwg/html/issues/1766](https://github.com/whatwg/html/issues/1766#issuecomment-1958782062), see also proposals to [restrict when MessagePort's onclose event can fire](https://github.com/whatwg/html/issues/10201)).\n\n:::\n\nChecking whether an application has closed may be achieved by a number of approaches:\n\n- By checking the `closed` property of WindowProxy objects that were received via the `source` property of the original `WCP1Hello` message, or any subsequent message over the `MessageChannel`. `closed` will be true if the window or frame was closed or destroyed, or the window or frame has navigated cross-domain.\n  - However, it should be noted that the `closed` will be `false` if the window has navigated same-domain, but is no longer an FDC3 app or has become a different FDC3 app. Hence, checking the `closed` property will not catch all cases.\n  - If an equivalent `WindowProxy` object (`WindowProxy` objects can be compared with `==` and will be equivalent if they represent the same window) is received from a different application the DA should consider the original application using that `WindowProxy` to have closed.\n- By receiving a `WCP6Goodbye` message from the application when it is closing. The `getAgent()` implementation automates the sending of this message via the HTML Standard's [Page Life Cycle API](https://wicg.github.io/page-lifecycle/spec.html). Specifically, the `getAgent()` implementation MUST attempt to detect windows closing by listening for the `pagehide` event and considering a window to be closed if the event's `persisted` property is `false`.\n  - Note that the `pagehide` event may not fire if the window's render thread crashes or is closed while 'frozen'.\n- By polling the application for responses via the `heartbeatEvent` and `heartbeatAcknowledgement` messages provided in the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol#checking-apps-are-alive). These message may be used for both periodic and on-demand polling by DA implementations. On-demand polling could, for example, be used to check that all instances returned in a findIntent response or displayed in an intent resolver are still alive.\n  - Desktop Agents MAY determine their own timeout, or support configuration, to be used for considering an application to have closed as this may be affected by the implementation details of app and DAs.\n\nFinally, Desktop Agents SHOULD retain instance details for applications that have closed as they may appear to close during navigation events, or may navigate away and then navigate back. By retaining the instance data (`instanceId`, `instanceUuid` and `WindowProxy`) the same instance identity can be maintained or reissued. There is no standard length of time that such details should be retained, hence, Desktop Agents MAY determine for themselves how long to retain instance details for closed instances.\n\n## Responding to app communications with Desktop Agent Communication Protocol (DACP)\n\nAfter validating an application's identity and any instance identity to be reused, the Desktop Agent is ready to support communication with the application. This is achieved via the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol) (DACP) over the `MessageChannel` established in the previous steps.\n\n## Implementing DAs in hidden iframes\n\nAs described above, DA providers can leverage hidden iframes to establish a communication mechanism that is independent of a parent window or frame. This approach allows apps to reconnect to a DA even when the parent window or frame has closed, or to connect a DA they've started themselves via a `failover` function.\n\nThe hidden iframe URL can be provided in two ways:\n\n1. By a parent window or frame - This allows DAs to handle communication via a hidden iframe that loads a known URL. The main benefit of this approach is that it can allow a system to continue to operate even if the parent window or frame is closed.\n2. By a `failover` function - When no parent DA can be found (such as when a tab is opened directly by an end user) then a failover function can create a hidden iframe and return a reference to it (a `WindowProxy`) that is used to initiate communication via the WCP in the same way as we do with a parent window or frame. Alternatively, a `DesktopAgent` implementation may be loaded directly and returned from the `failover` function, which `getAgent()` will pass-through.\n\n## Channel Selector and Intent Resolver User Interfaces\n\nChannel Selector and Intent Resolver user-interfaces are normally provided by Desktop Agents to applications. However, when running in a web browser, a DA may not have the ability to present a channel selector in a window that has been opened with `window.open()`, and it may be challenging to display a secondary window over the application when needed (due to pop-up blocking and user preferences).\n\nThe `getAgent()` implementation can facilitate the injection and management of iframes in an application window. An app may provide the optional `channelSelector` and `intentResolver` parameters to the `getAgent()` to indicate whether or not they need these interfaces. For example, the apps may not raise intents. Some apps may also resolve intents internally by leveraging the Desktop Agent's `findIntent` or `findIntentsForContext` API functions. In these situations, the apps won't need a DA-provided interface. Once an app calls `getAgent()`, the parameters that the app provides are forwarded onto the Desktop Agent in the `WCP1Hello` connection message.\n\nDesktop Agents MAY implement their own user interfaces for channel selection and intent resolution. The URL for each interface may be returned in the `channelSelectorUrl` and `intentResolverUrl` properties of the payload of the `WCP3Handshake` message sent by the DA during the connection sequence. Alternatively, if the Desktop Agent is able to provide these user interfaces by other means (for example DAs that render applications in iframes within a window they control may use other iframes to render these UIs) or if they app indicated that it did not need them then `channelSelectorUrl` and `intentResolverUrl` MAY be set to `false`. Finally, `channelSelectorUrl` and `intentResolverUrl` MAY be set to `true` to indicate that `getAgent()` should use the default reference implementations of these UIs provided via the [https://fdc3.finos.org](https://fdc3.finos.org) website.\n\n:::warning\n\nThe [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Where these are used in app implementations, please advise app implementors to include domains from which the UI implementations are served (including [fdc3.finos.org](https://fdc3.finos.org/) if you are working with the reference Intent Resolver and Channel Selector UIs).\n\n:::\n\nUser interface iframes are initially injected into the application window with CSS that prevents their display:\n\n```css\n{\n    width: \"0\";\n    height: \"0\";\n    position: \"fixed\";\n}\n```\n\nand are always displayed with `position: \"fixed\"` so that they are not part of the document flow.\n\nImplementations of the UIs may then indicate a limited set of CSS to apply to their frame in the initial `Fdc3UserInterfaceHello` message (when the width and height will be removed if not explicitly set in that message), and later adjust that via `Fdc3UserInterfaceRestyle`. See the [Controlling injected User Interfaces section](./desktopAgentCommunicationProtocol#controlling-injected-user-interfaces) in the DACP specification for more details.\n\nCommunication between the `DesktopAgentProxy` and the iframes it injects is achieved via a similar mechanism to that used for communication between an app and the Desktop Agent: a `MessageChannel` is established between the app and iframe, via a `postMessage` sent from the iframe (`Fdc3UserInterfaceHello`) and responded to by the `DesktopAgentProxy` in the app's window (`Fdc3UserInterfaceHandshake`), with a `MessagePort` from a `MessageChannel` appended.\n\nA further set of messages are provided for working with the injected user interfaces over their `MessageChannel` as part of the DACP, these are: `Fdc3UserInterfaceRestyle`, `Fdc3UserInterfaceDrag`, `Fdc3UserInterfaceChannels`, `Fdc3UserInterfaceChannelSelected`, `Fdc3UserInterfaceResolve` and `Fdc3UserInterfaceResolveAction`.\n\nSee the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol) (DACP) for more details.\n"
  },
  {
    "path": "website/docs/api/specs/desktopAgentCommunicationProtocol.md",
    "content": "---\nid: desktopAgentCommunicationProtocol\nsidebar_label: Desktop Agent Communication Protocol \ntitle: Desktop Agent Communication Protocol (next)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nFDC3's Desktop Agent Communication Protocol (DACP) is an experimental feature added to FDC3 in 2.2. Limited aspects of its design may change in future versions and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\nThe Desktop Agent Communication Protocol (DACP) constitutes a set of standardized JSON messages or 'wire protocol' that can be used to implement an interface to a Desktop Agent, encompassing all API calls events defined in the [Desktop Agent API](../ref/DesktopAgent.md). For example, the DACP is used by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) to communicate with Browser-Resident Desktop Agents or a connection setup via the [FDC3 Web Connection Protocol](./webConnectionProtocol).\n\n## Protocol conventions\n\nDACP messages are defined in [JSON Schema](https://json-schema.org/) in the [FDC3 github repository](https://github.com/finos/FDC3/tree/fdc3-for-web/schemas/api).\n\n:::tip\n\nTypeScript types representing all DACP and WCP messages are generated from the JSON Schema source and can be imported from the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3):\n\n```ts\nimport { BrowserTypes } from \"@finos/fdc3\";\n```\n\n:::\n\nThe protocol is composed of several different classes of message, each governed by a message schema:\n\n1. **App Request Messages** ([`AppRequest` schema](pathname:///schemas/next/api/appRequest.schema.json)):\n    - Messages sent by an application representing an API call, such as [`DesktopAgent.broadcast`](../ref/DesktopAgent#broadcast), [`Channel.addContextListener`](../ref/Channel#addcontextlistener), or [`Listener.unsubscribe`](../ref/Types#listener).\n    - Message names all end in 'Request'.\n    - Each instance of a request message sent is uniquely identified by a `meta.requestUuid` field.\n\n2. **Agent Response Messages** ([`AgentResponse` schema](pathname:///schemas/next/api/agentResponse.schema.json)):\n    - Response messages sent from the DA to the application, each relating to a corresponding _App Request Message_.\n    - Message names all end in 'Response'.\n    - Each instance of an Agent Response Message is uniquely identified by a `meta.responseUuid` field.\n    - Each instance of an Agent Response Message quotes the `meta.requestUuid` value of the message it is responding to.\n\n3. **Agent Event Messages** ([`AgentEvent` schema](pathname:///schemas/next/api/agentEvent.schema.json)):\n    - Messages sent from the DA to the application that are due to actions in other applications, such as an inbound context resulting from another app's broadcast.\n    - Message names all end in 'Event'.\n    - Each instance of an Agent Response Message is uniquely identified by a `meta.eventUuid` field.\n\nEach individual message is also governed by a message schema, which is composed with the schema for the message type.\n\n:::info\n\nIn rare cases, the payload of a request or event message may quote the `requestUuid` or `eventUuid` of another message that it represents a response to, e.g. `intentResultRequest` quotes the `eventUuid` of the `intentEvent` that delivered the intent and context to the app, as well as the `requestUuid` of the `raiseIntentRequest` message that originally raised the intent.\n\n:::\n\nAll messages defined in the DACP follow a common structure:\n\n```json\n{\n    \"type\": \"string\", // string identifying the message type\n    \"payload\": {\n        //message payload fields defined for each message type \n    },\n    \"meta\": {\n        \"timestamp\": \"2024-09-17T10:15:39+00:00\"\n        //other meta fields determined by each 'class' of message\n        //  these include requestUuid, responseUuid and eventUuid\n        //  and a source field identifying an app where appropriate\n    }\n}\n```\n\n`meta.timestamp` fields are formatted as strings, according to the format defined by [ISO 8601-1:2019](https://www.iso.org/standard/70907.html), which is produced in JavaScript via the `Date` class's `toISOString()` function, e.g. `(new Date()).toISOString()`.\n\n### Routing, Registering Listeners & Multiplexing\n\nThe design of the Desktop Agent Communication Protocol is guided by the following sentence from the introduction to the Desktop Agent overview:\n\n> A Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nHence, that design is based on the assumption that all messaging between applications passes through an entity that acts as the 'Desktop Agent' and routes those messages on to the appropriate recipients (for example, a context message broadcast by an app to a channel is routed onto other apps that have added a listener to that channel, or an intent and context pair raised by an application is routed to another app chosen to resolve that intent). While implementations based on a shared bus are possible, they have not been specifically considered in the design of the DACP messages.\n\nFurther, the design of the DACP is based on the assumption that applications will interact with an implementation of the [`DesktopAgent`](../ref/DesktopAgent) interface, with the DACP used behind the scenes to support communication between the implementation of that interface and an entity acting as the Desktop Agent which is running in another process or location, necessitating the use of a 'wire protocol' for communication. For example, [Browser-Resident Desktop Agent](./browserResidentDesktopAgents) implementations use the [FDC3 Web Communication Protocol (WCP)](./webConnectionProtocol.md) to connect a 'Desktop Agent Proxy', provided by the `getAgent()` implementation in the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), and a Desktop Agent running in another frame or window which is communicated with via the DACP.\n\nAs a Desktop Agent is expected to act as a router for messages sent through the Desktop Agent API, the DACP provides message exchanges for the registration and un-registration of listeners for particular message types (e.g. events, contexts broadcast on user channels, contexts broadcast on other channel types, raised intents etc.). In most cases, apps can register multiple listeners for the same messages (often filtered for different context or event types). However, where multiple listeners are present, only a single DACP message should be sent representing the action taken in the FDC3 API (e.g. broadcasting a message to a channel) and any multiplexing to multiple listeners should be applied at the receiving end. For example, when working with the WCP, this should be handled by the Desktop Agent Proxy implementation provided by the `getAgent()` implementation.\n\n### Timeouts for Message Exchanges\n\nAs the DACP is used to communicate with a different browsing context, timeouts are applied to message exchanges allowing them to fail and for the Desktop Agent Proxy to return an error to the caller. A default timeout of 10 seconds is applied to all message exchanges, with the exception of those that may involve the launch of an application (`open()`, `raiseIntent()` and `raiseIntentForContext()`). Implementations of the FDC3 Desktop Agent API are required to allow a minimum timeout of 15 seconds for an application to launch and add any necessary context or intent listeners (see [Desktop Agent API Compliance](../spec#desktop-agent-api-standard-compliance) for further details). However, no upper bound for the timeout is currently specified. Message exchanges that involve the launch of an application use a default timeout of 100 seconds.\n\nDesktop Agents may specify custom values for both the default message exchange timeout and the timeout used for exchanges that may involve the launch of an application. Custom values are passed to the Desktop Agent proxy by setting the optional `payload.messageExchangeTimeout` and `payload.appLaunchTimeout` fields in the `WCP3Handshake` Response sent by the Desktop Agent to an application connecting to it. `payload.messageExchangeTimeout` MUST be set to a value greater than or equal to 100 ms, and `payload.appLaunchTimeout`  MUST be set to a value greater than or equal to 15,000 ms.\n\n```ts\n/** Default timeout used by a DesktopAgentProxy for all message exchanges\n * with a DesktopAgent, except those that involve the launch of an application.\n * May be overridden by a DesktopAgent by passing a value in the\n * payload.messageExchangeTimeout of a WCP3Handshake message.\n */\nexport const DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS = 10000;\n\n/** Default timeout used by a DesktopAgentProxy for message exchanges with a\n * DesktopAgent that involve launching applications. May be overridden by a \n * DesktopAgent by passing a value in the payload.appLaunchTimeout of a \n * WCP3Handshake message.\n * */\nexport const DEFAULT_APP_LAUNCH_TIMEOUT_MS = 100000;\n```\n\n:::info\n\nThe message exchange timeouts are used to detect a lack of response from the Desktop Agent, which will be reported via the `ApiTimeout` error message. However, there are also defined error messages for apps failing to add an expected context listener (`OpenError.AppTimeout`) or intent listener (`ResolveError.IntentDeliveryFailed`) after launch. To return these errors, the Desktop Agent should set a longer timeout via the `payload.appLaunchTimeout` field in its `WCP3Handshake` message than it uses internally to detect such failures. Doing so will ensure that timeouts can be separately attributed to the App or to the Desktop Agent.\n\n:::\n\n## Message Definitions Supporting FDC3 API calls\n\nThis section provides details of the messages defined in the DACP, grouped according to the FDC3 API functions that they support, and defined by JSON Schema files. Many of these message definitions make use of JSON versions of [metadata](../ref/Metadata) and other [types](../ref/Types) defined by the Desktop Agent API, the JSON versions of which can be found in [api.schema.json](pathname:///schemas/next/api/api.schema.json), while a number of DACP specific object definitions that are reused through the messages can be found in [common.schema.json](pathname:///schemas/next/api/common.schema.json).\n\n### `DesktopAgent`\n\n#### `addContextListener()`\n\nRequest and response used to implement the [`DesktopAgent.addContextListener()`](../ref/DesktopAgent#addcontextlistener) and [`Channel.addContextListener()`](../ref/Channel#addcontextlistener) API calls:\n\n- [`addContextListenerRequest`](pathname:///schemas/next/api/addContextListenerRequest.schema.json)\n- [`addContextListenerResponse`](pathname:///schemas/next/api/addContextListenerResponse.schema.json)\n\nEvent message used to deliver context objects that have been broadcast to listeners:\n\n- [`broadcastEvent`](pathname:///schemas/next/api/broadcastEvent.schema.json)\n\nRequest and response for removing the context listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`contextListenerUnsubscribeRequest`](pathname:///schemas/next/api/contextListenerUnsubscribeRequest.schema.json)\n- [`contextListenerUnsubscribeResponse`](pathname:///schemas/next/api/contextListenerUnsubscribeResponse.schema.json)\n\n#### `addEventListener()`\n\nRequest and response used to implement the [`addEventListener()`](../ref/DesktopAgent#addeventlistener) API call:\n\n- [`addEventListenerRequest`](pathname:///schemas/next/api/addEventListenerRequest.schema.json)\n- [`addEventListenerResponse`](pathname:///schemas/next/api/addEventListenerResponse.schema.json)\n\nEvent messages used to deliver events that have occurred:\n\n- [`channelChangedEvent`](pathname:///schemas/next/api/channelChangedEvent.schema.json)\n\nRequest and response for removing the event listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`eventListenerUnsubscribeRequest`](pathname:///schemas/next/api/eventListenerUnsubscribeRequest.schema.json)\n- [`eventListenerUnsubscribeResponse`](pathname:///schemas/next/api/eventListenerUnsubscribeResponse.schema.json)\n\n#### `addIntentListener()`\n\nRequest and response used to implement the [`addIntentListener()`](../ref/DesktopAgent#addintentlistener) API call:\n\n- [`addIntentListenerRequest`](pathname:///schemas/next/api/addIntentListenerRequest.schema.json)\n- [`addIntentListenerResponse`](pathname:///schemas/next/api/addIntentListenerResponse.schema.json)\n\nEvent message used to a raised intent and context object from another app to the listener:\n\n- [`intentEvent`](pathname:///schemas/next/api/intentEvent.schema.json)\n\nAn additional request and response used to deliver an [`IntentResult`](../ref/Types#intentresult) from the intent handler to the Desktop Agent, so that it can convey it back to the raising application:\n\n- [`intentResultRequest`](pathname:///schemas/next/api/intentResultRequest.schema.json)\n- [`intentResultResponse`](pathname:///schemas/next/api/intentResultResponse.schema.json)\n\nPlease note this exchange (and the `IntentResolution.getResult()` API call) support `void` results from a raised intent and hence this message exchange should occur for all raised intents, including those that do not return a result. In such cases, the void intent result allows resolution of the `IntentResolution.getResult()` API call and indicates that the intent handler has finished running.\n\nRequest and response for removing the intent listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`intentListenerUnsubscribeRequest`](pathname:///schemas/next/api/intentListenerUnsubscribeRequest.schema.json)\n- [`intentListenerUnsubscribeResponse`](pathname:///schemas/next/api/intentListenerUnsubscribeResponse.schema.json)\n\nA typical exchange of messages between an app raising an intent, a Desktop agent and an app resolving an intent is:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\nThe above flow assumes that AppB has already been launched and added an intent listener. As apps can be launched to resolve an intent a typical message exchange (that includes registration of the intent listener) is:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    break intent resolution determines a new instance of AppB should be launched\n        DesktopAgent -->> AppB: Launch\n        AppB -->> DesktopAgent: Connect via WCP\n    end\n    AppB ->> DesktopAgent: addIntentListenerRequest\n    DesktopAgent ->> AppB: addIntentListenerResponse\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\n:::tip\n\nSee [`raiseIntent`](#raiseintent) below for further examples of message exchanges involved in raising intents and intent resolution.\n\n:::\n\n#### `broadcast()`\n\nRequest and response used to implement the [`DesktopAgent.broadcast()`](../ref/DesktopAgent#broadcast) and [`Channel.broadcast()`](../ref/Channel#broadcast) API calls:\n\n- [`broadcastRequest`](pathname:///schemas/next/api/broadcastRequest.schema.json)\n- [`broadcastResponse`](pathname:///schemas/next/api/broadcastResponse.schema.json)\n\nSee [`addContextListener()`](#addcontextlistener) above for the `broadcastEvent` used to deliver the broadcast to other apps.\n\n#### `createPrivateChannel()`\n\nRequest and response used to implement the [`createPrivateChannel()`](../ref/DesktopAgent#createprivatechannel) API call:\n\n- [`createPrivateChannelRequest`](pathname:///schemas/next/api/createPrivateChannelRequest.schema.json)\n- [`createPrivateChannelResponse`](pathname:///schemas/next/api/createPrivateChannelResponse.schema.json)\n\n#### `findInstances()`\n\nRequest and response used to implement the [`findInstances()`](../ref/DesktopAgent#findinstances) API call:\n\n- [`findInstancesRequest`](pathname:///schemas/next/api/findInstancesRequest.schema.json)\n- [`findInstancesResponse`](pathname:///schemas/next/api/findInstancesResponse.schema.json)\n\n#### `findIntent()`\n\nRequest and response used to implement the [`findIntent()`](../ref/DesktopAgent#findintent) API call:\n\n- [`findIntentRequest`](pathname:///schemas/next/api/findIntentRequest.schema.json)\n- [`findIntentResponse`](pathname:///schemas/next/api/findIntentResponse.schema.json)\n\n#### `findIntentsByContext()`\n\nRequest and response used to implement the [`findIntentsByContext()`](../ref/DesktopAgent#findintentsbycontext) API call:\n\n- [`findIntentsByContextRequest`](pathname:///schemas/next/api/findIntentsByContextRequest.schema.json)\n- [`findIntentsByContextResponse`](pathname:///schemas/next/api/findIntentsByContextResponse.schema.json)\n\n#### `getAppMetadata()`\n\nRequest and response used to implement the [`getAppMetadata()`](../ref/DesktopAgent#getappmetadata) API call:\n\n- [`getAppMetadataRequest`](pathname:///schemas/next/api/getAppMetadataRequest.schema.json)\n- [`getAppMetadataResponse`](pathname:///schemas/next/api/getAppMetadataResponse.schema.json)\n\n#### `getCurrentChannel()`\n\nRequest and response used to implement the [`getCurrentChannel()`](../ref/DesktopAgent#getcurrentchannel) API call:\n\n- [`getCurrentChannelRequest`](pathname:///schemas/next/api/getCurrentChannelRequest.schema.json)\n- [`getCurrentChannelResponse`](pathname:///schemas/next/api/getCurrentChannelResponse.schema.json)\n\n#### `getInfo()`\n\nRequest and response used to implement the [`getInfo()`](../ref/DesktopAgent#getinfo) API call:\n\n- [`getInfoRequest`](pathname:///schemas/next/api/getInfoRequest.schema.json)\n- [`getInfoResponse`](pathname:///schemas/next/api/getInfoResponse.schema.json)\n\n#### `getOrCreateChannel()`\n\nRequest and response used to implement the [`getOrCreateChannel()`](../ref/DesktopAgent#getorcreatechannel) API call:\n\n- [`getOrCreateChannelRequest`](pathname:///schemas/next/api/getOrCreateChannelRequest.schema.json)\n- [`getOrCreateChannelResponse`](pathname:///schemas/next/api/getOrCreateChannelResponse.schema.json)\n\n#### `getUserChannels()`\n\nRequest and response used to implement the [`getUserChannels()`](../ref/DesktopAgent#getuserchannels) API call:\n\n- [`getUserChannelsRequest`](pathname:///schemas/next/api/getUserChannelsRequest.schema.json)\n- [`getUserChannelsResponse`](pathname:///schemas/next/api/getUserChannelsResponse.schema.json)\n\n#### `joinUserChannel()`\n\nRequest and response used to implement the [`joinUserChannel()`](../ref/DesktopAgent#joinuserchannel) API call:\n\n- [`joinUserChannelRequest`](pathname:///schemas/next/api/joinUserChannelRequest.schema.json)\n- [`joinUserChannelResponse`](pathname:///schemas/next/api/joinUserChannelResponse.schema.json)\n\n#### `leaveCurrentChannel()`\n\nRequest and response used to implement the [`leaveCurrentChannel()`](../ref/DesktopAgent#leavecurrentchannel) API call:\n\n- [`leaveCurrentChannelRequest`](pathname:///schemas/next/api/leaveCurrentChannelRequest.schema.json)\n- [`leaveCurrentChannelResponse`](pathname:///schemas/next/api/leaveCurrentChannelResponse.schema.json)\n\n#### `open()`\n\nRequest and response used to implement the [`open()`](../ref/DesktopAgent#open) API call:\n\n- [`openRequest`](pathname:///schemas/next/api/openRequest.schema.json)\n- [`openResponse`](pathname:///schemas/next/api/openResponse.schema.json)\n\nWhere a context object is passed (e.g. `fdc3.open(app, context)`) the `broadcastEvent` message described above in [`addContextListener`](#addcontextlistener) should be used to deliver it after the context listener has been added:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: openRequest<br>(with context)\n    break Desktop Agent launches AppB\n        DesktopAgent -->> AppB: Launch\n        AppB -->> DesktopAgent: Connect via WCP\n    end\n    AppB ->> DesktopAgent: addContextListenerRequest\n    DesktopAgent ->> AppB: addContextListenerResponse\n    DesktopAgent ->> AppB: broadcastEvent\n    DesktopAgent ->> AppA: openResponse<br/>(with AppIdentifier)\n```\n\nHowever, if the app opened doesn't add a context listener within a timeout (defined by the Desktop Agent) then the `openResponse` should be sent with `AppTimeout` error from the [`OpenError`](../ref/Errors#openerror) enumeration.\n\n:::tip\n\nDesktop Agents MUST allow at least 15 seconds for an app to add a context listener before timing out (see [Desktop Agent API Standard Compliance](https://fdc3.finos.org/docs/next/api/spec#desktop-agent-api-standard-compliance) for more detail) and applications SHOULD add their listeners as soon as possible to keep the delay short (see the [addContextListener reference doc](https://fdc3.finos.org/docs/next/api/ref/DesktopAgent#addcontextlistener)).\n\n:::\n\n#### `raiseIntent()`\n\nRequest and response used to implement the [`raiseIntent()`](../ref/DesktopAgent#raiseintent) API call:\n\n- [`raiseIntentRequest`](pathname:///schemas/next/api/raiseIntentRequest.schema.json)\n- [`raiseIntentResponse`](pathname:///schemas/next/api/raiseIntentResponse.schema.json)\n\nAn additional response message is provided for the delivery of an `IntentResult` from the resolving application to the raising application (which is collected via the [`IntentResolution.getResult()`](../ref/Metadata#intentresolution) API call), which should quote the `requestUuid` from the original `raiseIntentRequest`:\n\n- [`raiseIntentResultResponse`](pathname:///schemas/next/api/raiseIntentResultResponse.schema.json)\n\nThere is no request message to indicate a call to the `resolution.getResult()` function of `IntentResolution`. Hence, Desktop Agents MUST send this additional response message to indicate the status of the intent handling function and to deliver its result (or void if none was returned).\n\n:::tip\n\nSee [`addIntentListener`](#addintentlistener) above for details of the messages used for the resolving app to deliver the result to the Desktop Agent.\n\n:::\n\nWhere there are multiple options for resolving a raised intent, there are two possible versions of the resulting message exchanges. Which to use depends on whether the Desktop Agent uses an intent resolver user interface (or other suitable mechanism) that it controls, or one injected into the application (for example an iframe injected by a `getAgent()` implementation into an application window) to perform resolution.\n\nWhen working with an injected interface, the Desktop Agent should respond with a `raiseIntentResponse` containing a `RaiseIntentNeedsResolutionResponsePayload`:\n\n```mermaid\n---\ntitle: Intent resolution with injected Intent Resolver iframe\n---\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    DesktopAgent ->> AppA: raiseIntentResponse\n    Note left of DesktopAgent: raiseIntentResponse includes a<br/> RaiseIntentNeedsResolutionResponsePayload<br/>containing an AppIntent\n    break when AppIntent return with multiple options\n        DesktopAgent --> AppA: getAgent displays IntentResolver\n        AppA --> DesktopAgent: User picks an option\n    end\n    AppA ->> DesktopAgent: raiseIntentRequest\n    Note left of DesktopAgent: New request includes a<br/>specific 'app' target<br/>and new requestUuid\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\nAlternatively, if the Desktop Agent is able to provide its own user interface or another suitable means of resolving the intent, then it may do so and respond with a `raiseIntentResponse` containing a `RaiseIntentSuccessResponsePayload`:\n\n```mermaid\n---\ntitle: Intent resolution with Desktop Agent provided Intent Resolver\n---\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    break DA determines there are multiple options\n        DesktopAgent-->AppA: Desktop Agent displays an<br/>IntentResolver UI\n        AppA-->DesktopAgent: User picks an option\n    end\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    Note left of DesktopAgent: DesktopAgent responds<br/>to the original<br/>raiseIntentRequest message with<br/>a RaiseIntentSuccessResponsePayload\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\n#### `raiseIntentForContext()`\n\nRequest and response used to implement the [`raiseIntentForContext()`](../ref/DesktopAgent#raiseintentforcontext) API call:\n\n- [`raiseIntentForContextRequest`](pathname:///schemas/next/api/raiseIntentForContextRequest.schema.json)\n- [`raiseIntentForContextResponse`](pathname:///schemas/next/api/raiseIntentForContextResponse.schema.json)\n\nMessage exchanges for handling `raiseIntentForContext()` are the same as for `raiseIntent`, except for the substitution of `raiseIntentForContextRequest` for `raiseIntentRequest` and `raiseIntentForContextResponse` for `raiseIntentResponse`. Hence, please see [`raiseIntent`](#raiseintent) and [`addIntentListener`](#addintentlistener) for further details.\n\n### `Channel`\n\nOwing to the significant overlap between the FDC3 [`DesktopAgent`](../ref/DesktopAgent) and [`Channel`](../ref/Channel) interfaces, which includes the ability to retrieve and work with User channels as App Channels, most of the messaging for the `Channel` API is shared with `DesktopAgent`. Specifically, all messages defined in the the [`broadcast`](#broadcast) and [`addContextListener`](#addcontextlistener) sections above are reused, with a few minor differences to note:\n\n- When working with a specific channel, the `channelId` property in `addContextListenerRequest` should be set to the ID of the channel, where it is set to `null` to work with the current user channel.\n- When receiving a `broadcastEvent` a `channelId` that is `null` indicates that the context was sent via a call to `fdc3.open` and does not relate to a channel.\n\nThe following additional function is unique to the `Channel` interface:\n\n#### `getCurrentContext()`\n\nRequest and response used to implement the [`Channel.getCurrentContext()`](../ref/Channel#getcurrentcontext) API call:\n\n- [`getCurrentContextRequest`](pathname:///schemas/next/api/getCurrentContextRequest.schema.json)\n- [`getCurrentContextResponse`](pathname:///schemas/next/api/getCurrentContextResponse.schema.json)\n\n### `PrivateChannel`\n\nThe [`PrivateChannel`](../ref/PrivateChannel) interface extends [`Channel`](../ref/Channel) with a number of additional functions that are supported by the following messages:\n\n#### `addEventListener()`\n\nRequest and response used to implement the [`PrivateChannel.addEventListener`](../ref/PrivateChannel#addeventlistener) API call:\n\n- [`privateChanneladdEventListenerRequest`](pathname:///schemas/next/api/privateChanneladdEventListenerRequest.schema.json)\n- [`privateChanneladdEventListenerResponse`](pathname:///schemas/next/api/privateChanneladdEventListenerResponse.schema.json)\n\nEvent messages used to deliver events that have occurred:\n\n- [`privateChannelOnAddContextListenerEvent`](pathname:///schemas/next/api/privateChannelOnAddContextListenerEvent.schema.json)\n- [`privateChannelOnDisconnectEvent`](pathname:///schemas/next/api/privateChannelOnDisconnectEvent.schema.json)\n- [`privateChannelOnUnsubscribeEvent`](pathname:///schemas/next/api/privateChannelOnUnsubscribeEvent.schema.json)\n\n:::tip\n\nThe above messages may also be used to implement the deprecated [`onAddContextListener()`](../ref/PrivateChannel#onaddcontextlistener), [`onUnsubscribe`](../ref/PrivateChannel#onunsubscribe) and [`onDisconnect`](../ref/PrivateChannel#ondisconnect) functions of the `PrivateChannel` interface.\n\n:::\n\nMessage exchange for removing the event listener [`Listener.unsubscribe`](../ref/Types#listener):\n\n- [`privateChannelUnsubscribeEventListenerRequest`](pathname:///schemas/next/api/privateChannelUnsubscribeEventListenerRequest.schema.json)\n- [`privateChannelUnsubscribeEventListenerResponse`](pathname:///schemas/next/api/privateChannelUnsubscribeEventListenerResponse.schema.json)\n\n#### `disconnect()`\n\nRequest and response used to implement the [`PrivateChannel.disconnect()`](../ref/PrivateChannel#disconnect) API call:\n\n- [`privateChannelDisconnectRequest`](pathname:///schemas/next/api/privateChannelDisconnectRequest.schema.json)\n- [`privateChannelDisconnectResponse`](pathname:///schemas/next/api/privateChannelDisconnectResponse.schema.json)\n\n### Checking apps are alive\n\nDepending on the connection over which the Desktop Agent and app are connected, it may be necessary for the Desktop Agent to check whether the application is still alive. This can be done, either periodically or on demand (for example to validate options that will be provided in an [`AppIntent`](../ref/Metadata#appintent) as part of a `findIntentResponse` or `raiseIntentResponse` and displayed in an intent resolver interface), using the following message exchange:\n\n- [`heartbeatEvent`](pathname:///schemas/next/api/heartbeatEvent.schema.json)\n- [`heartbeatAcknowledgment`](pathname:///schemas/next/api/heartbeatAcknowledgment.schema.json)\n\nAs a Desktop Agent initiated exchange, it is initiated with an `AgentEvent` message and completed via an `AppRequest` message as an acknowledgement.\n\n:::tip\n\nAdditional procedures are defined in the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents#disconnects) and [Web Connection Protocol](./webConnectionProtocol#step-5-disconnection) for the detection of app disconnection or closure. Implementations will often need to make use of multiple procedures to catch all forms of disconnection in a web browser.\n\n:::\n\n### Controlling Injected User Interfaces\n\nDesktop Agent implementations, such as those based on the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents) and [Web Connection Protocol](./webConnectionProtocol), may either provide their own user interfaces (or other appropriate mechanisms) for the selection of User Channels or Intent Resolution, or they may work with implementations injected into the application (for example, as described in the [Web Connection Protocol](./webConnectionProtocol#providing-channel-selector-and-intent-resolver-uis) and implemented in [`getAgent()`](../ref/GetAgent)).\n\nWhere injected user interfaces are used, standardized messaging is needed to communicate with those interfaces. This is provided in the DACP via the following 'iframe' messages, which are governed by the [`Fdc3UserInterfaceMessage`](pathname:///schemas/next/api/fdc3UserInterface.schema.json) schema. The following messages are provided:\n\n- [`Fdc3UserInterfaceHello`](pathname:///schemas/next/api/fdc3UserInterfaceHello.schema.json): Sent by the iframe to its `window.parent` frame to initiate communication and to provide initial CSS to apply to the frame. This message should have a `MessagePort` appended over which further communication will be conducted.\n- [`Fdc3UserInterfaceHandshake`](pathname:///schemas/next/api/fdc3UserInterfaceHandshake.schema.json):  Response to the `Fdc3UserInterfaceHello` message sent by the application frame, which should be sent over the `MessagePort`. Includes details of the FDC3 version that the application is using.\n- [`Fdc3UserInterfaceDrag`](pathname:///schemas/next/api/fdc3UserInterfaceDrag.schema.json): Message sent by the iframe to indicate that it is being dragged to a new position and including offsets to indicate direction and distance.\n- [`Fdc3UserInterfaceRestyle`](pathname:///schemas/next/api/fdc3UserInterfaceRestyle.schema.json): Message sent by the iframe to indicate that its frame should have updated CSS applied to it, for example to support a channel selector interface that can be 'popped open' or an intent resolver that wishes to resize itself to show additional content.\n\nMessages are also provided that are specific to each user interface type provided by a Desktop Agent. The following messages are specific to Channel Selector user interfaces:\n\n- [`Fdc3UserInterfaceChannels`](pathname:///schemas/next/api/fdc3UserInterfaceChannels.schema.json): Sent by the parent frame to initialize a Channel Selector user interface by providing metadata for the Desktop Agent's user channels and details of any channel that is already selected. This message will typically be sent by a `getAgent()` implementation immediately after the `fdc3UserInterfaceHandshake` and before making the injected iframe visible.\n- [`Fdc3UserInterfaceChannelSelected`](pathname:///schemas/next/api/fdc3UserInterfaceChannelSelected.schema.json): Sent by the Channel Selector to indicate that a channel has been selected or deselected.\n\nMessages specific to Intent Resolver user interfaces:\n\n- [`Fdc3UserInterfaceResolve`](pathname:///schemas/next/api/fdc3UserInterfaceResolve.schema.json): Sent by the parent frame to initialize an Intent Resolver user interface to resolve a raised intent, before making the iframe visible. The message includes the context object sent with the intent and an array of one or more [`AppIntent`](../ref/Metadata#appintent) objects representing the resolution options for the intent ([`raiseIntent`](../ref/DesktopAgent#raiseintent)) or context ([`raiseIntentForContext`](../ref/DesktopAgent#raiseintentforcontext)) that was raised.\n- [`Fdc3UserInterfaceResolveAction`](pathname:///schemas/next/api/fdc3UserInterfaceResolveAction.schema.json): Sent by the Intent Resolver to indicate actions taken by the user in the interface, including hovering over an option, clicking a cancel button, or selecting a resolution option. The Intent Resolver should be hidden by the `getAgent()` implementation after a resolution option is selected to ensure that it does not interfere with user's ongoing interaction with the app's user interface.\n"
  },
  {
    "path": "website/docs/api/specs/preloadDesktopAgents.md",
    "content": "---\nid: preloadDesktopAgents\nsidebar_label: Preload Desktop Agents\ntitle: Preload Desktop Agents (next)\n---\n\n\nA Preload Desktop Agent is an FDC3 Desktop Agent (DA) supporting web applications that 'inject' or 'preload' scripts into web windows which provide access to an FDC3 Desktop Agent API implementation. This document specifies the required behavior for a Preload Desktop Agent (DA).\n\n:::info\n\n> The [getAgent() specification in the FDC3 Web Connection Protocol](webConnectionProtocol.md) relies on Preload DAs behaving as specified in this document.\n\n:::\n\n## Injecting the global FDC3 object\n\nSince FDC3 is typically available to the whole web application, Desktop Agents are expected to make the [`DesktopAgent`](../ref/DesktopAgent) interface available at a global level. Hence, a Preload Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means.\n\nThe global `window.fdc3` MUST only be available after the API is ready to use. Implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use.\n\nHowever, implementors SHOULD also ensure that the global is made available as soon as possible after the window is created to ensure that it can be detected by `getAgent()`. Queuing of requests to the API MAY be used to make the API available, while initialization is underway.\n\n:::note\n\nPrior to FDC3 2.2, apps were advised to check for the existence of the FDC3 API at `window.fdc3` and then add a listener for the `fdc3Ready` event if it was not found. This has since been superseded by the recommendation to use `getAgent()`, which handles those steps internally, alongside supporting FDC3 in web browsers ( via the [Browser Resident Desktop Agent spec](./browserResidentDesktopAgents)).\n\n:::\n"
  },
  {
    "path": "website/docs/api/specs/webConnectionProtocol.md",
    "content": "---\nid: webConnectionProtocol\nsidebar_label: Web Connection Protocol\ntitle: Web Connection Protocol (next)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nFDC3's Web Connection Protocol (WCP) is an experimental feature added to FDC3 in 2.2. Limited aspects of its design may change in future versions and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\nThe FDC3 Web Connection Protocol (WCP) defines the procedure for a web-application to connect to an FDC3 Desktop Agent. The WCP is used to implement a [`getAgent()`](../ref/GetAgent) function in the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), which is the recommended way for web applications to connect to a Desktop Agent. This specification details how it retrieves and provides the FDC3 [`DesktopAgent`](../ref/DesktopAgent) interface object and requirements that Desktop Agents MUST implement in order to support discovery and connection via `getAgent()`. Please see the [`getAgent` reference document](../ref/GetAgent.md) for its TypeScript definition and related types.\n\n:::tip\n\nThe [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) provides a `getAgent()` implementation which app can use to connect to a Desktop Agent without having to interact with or understand the WCP directly. See [Supported Platforms](../supported-platforms) and the [`getAgent()`](../ref/GetAgent) reference page for more details on using `getAgent()` in an application.\n\n:::\n\nThe WCP supports both interfaces to web-based Desktop Agents defined in the FDC3 Standard:\n\n- **Desktop Agent Preload**: An 'injected' or 'preloaded' Desktop Agent API implementation, typically provided by an [Electron](https://www.electronjs.org/) (or similar) container or browser extension, which is made available to web applications at `window.fdc3`.\n- **Desktop Agent Proxy**: An interface to a web-based Desktop Agent (implementation of the Desktop Agent API) that uses the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) to communicate with a Desktop Agent implementation running in another frame or window, via the HTML Standard's Channel Messaging API ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API), [HTML Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html)).\n\nThe WCP allows FDC3-enabled applications to detect which FDC3 web-interface is present at runtime and returns a `DesktopAgent` interface implementation that the application can use to communicate, without the import of proprietary libraries or code. Hence, the WCP enables FDC3-enabled applications to be run within the scope of any standards compliant Desktop Agent without modification, enabling their developers to Write Once Run Anywhere (WORA).\n\n:::tip\n\nSee the FDC3 [Glossary](../../fdc3-glossary) and [References](../../references.md) pages for definitions of terms and links to external APIs used throughout this document.\n\n:::\n\n:::tip\n\nFurther details for implementing Preload Desktop Agents (which use a Desktop Agent Preload interface) or a Browser Resident Desktop Agent (which use a Desktop Agent Proxy interface) are available in the [Preload Desktop Agent](./preloadDesktopAgents) or [Browser Resident Desktop Agent Specification](./browserResidentDesktopAgents), respectively.\n\n:::\n\n## WCP Message Schemas\n\nThere are a number of messages defined as part of the Web Connection Protocol. Definitions are provided in [JSON Schema](https://json-schema.org/) in the [FDC3 github repository](https://github.com/finos/FDC3/tree/fdc3-for-web/schemas/api).\n\n:::tip\n\nTypeScript types representing all DACP and WCP messages are generated from the JSON Schema source and can be imported from the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3):\n\n```ts\nimport { BrowserTypes } from \"@finos/fdc3\";\n```\n\n:::\n\nWCP messages are derived from a base schema, [`WCPConnectionStep`](pathname:///schemas/next/api/.schema.json), which defines a common structure for the messages:\n\n```json\n{\n    \"type\": \"string\", // string identifying the message type\n    \"payload\": {\n        //message payload fields defined for each message type \n    },\n    \"meta\": {\n        \"connectionAttemptUuid\": \"79be3ff9-7c05-4371-842a-cf08427c174d\",\n        \"timestamp\": \"2024-09-17T10:15:39+00:00\"\n    }\n}\n```\n\nA value for `meta.connectionAttemptUuid` should be generated as a version 4 UUID according to [IETF RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) at the start for the connection process and quoted in all subsequent messages, as described later in this document.\n\n`meta.timestamp` fields are formatted as strings, according to the format defined by [ISO 8601-1:2019](https://www.iso.org/standard/70907.html), which is produced in JavaScript via the `Date` class's `toISOString()` function, e.g. `(new Date()).toISOString()`.\n\nMessages defined as part of the Web Connection Protocol, which will be referenced later in this document, these are:\n\n- [`WCP1Hello`](pathname:///schemas/next/api/WCP1Hello.schema.json)\n- [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json)\n- [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json)\n- [`WCP4ValidateAppIdentity`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json)\n- [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityFailedResponse.schema.json)\n- [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json)\n- [`WCP6Goodbye`](pathname:///schemas/next/api/WCP6Goodbye.schema.json)\n\n## Establishing Connectivity Using the Web Connection Protocol (WCP)\n\nThe WCP algorithm (coordinated between the `getAgent()` implementation and Desktop Agent implementations) has four steps, followed by an optional disconnection step. Each step may contain sub-steps.\n\n1. Locate a Desktop Agent interface\n2. Validate app & instance identity\n3. Persist connection details to SessionStorage\n4. Return Desktop Agent interface\n5. Disconnect\n\n### Step 1: Locate a Desktop Agent interface\n\n#### 1.1 Check for a possible navigation or refresh event\n\nCheck the SessionStorage key `FDC3-Desktop-Agent-Details` for a `DesktopAgentDetails` record. If it exists, then a navigation or refresh event may have occurred and the stored data MUST be sent when attempting to establish a connection to the DA. This ensures that the window can maintain a consistent `instanceId` between navigation or refresh events within an app. If it doesn't exist then proceed to step (2).\n\nAny data stored under the `FDC3-Desktop-Agent-Details` MUST conform to the [DesktopAgentDetails](../ref/GetAgent#persisted-connection-data) type.\n\nExisting `DesktopAgentDetails` records MUST be used to limit discovery actions (in the next step) to the same mechanism as previously used or to skip the discovery step entirely if an `agentUrl` exists, indicating that the connection should be established by loading the URL into a hidden iframe and initiating communication with that instead.\n\nIf use of the persisted data fails to establish a connection to the DA then `getAgent()` should reject its promise with `AgentNotFound` error from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\n#### 1.2 Desktop Agent Discovery\n\nNext, attempt to discover whether Desktop Agent Preload or Desktop Agent Proxy interfaces are available, within a specified timeout. The optional `params.timeoutMs` argument to `getAgent()` allows an application to specify the timeout that should be used, with a default value of 750ms. Discovery of Desktop Agent Preload or Desktop Agent Proxy interfaces should be conducted in parallel where possible and the timeout cancelled as soon as an interface is discovered. If a `DesktopAgentDetails` record was found in the previous step, limit discovery to the interface specified, or, if an `agentUrl` property was specified in the `DesktopAgentDetails` record, skip the discovery step entirely and proceed to the next step.\n\nTo discover a Desktop Agent Preload interface, check for the presence of an `fdc3` object in the global scope (i.e. `window.fdc3`). If it exists return it immediately. If it does not exist then add a listener for the global `fdc3Ready` event with the the specified timeout, e.g.:\n\n```ts\nconst discoverPreloadDA = async (timeoutMs: number): Promise<DesktopAgent> => {\n  return new Promise((resolve, reject) => {\n    // if the global is already available resolve immediately\n    if (window.fdc3) {\n      resolve(window.fdc3);\n    } else {\n      // Setup a timeout to return a rejected promise\n      const timeoutId = setTimeout(\n        () => {\n          //clear the event listener to ignore a late event\n          window.removeEventListener(\"fdc3Ready\", listener);\n          if (window.fdc3){ \n            resolve(window.fdc3);\n          } else {\n            reject(\"Desktop Agent Preload not found!\");\n          }\n        }, \n        timeoutMs\n      );\n      //`fdc3Ready` event listener function\n      const listener = () => {\n        clearTimeout(timeoutId);\n        if (window.fdc3) {\n          resolve(window.fdc3);\n        } else {\n          reject(\"The `fdc3Ready` event fired, but `window.fdc3` Was not set!\");\n        }\n      };\n      \n      // listen for the fdc3Ready event\n      window.addEventListener(\"fdc3Ready\", listener, { once: true });\n    }\n  });\n};\n```\n\nTo discover a Desktop Agent Proxy interface, locate all candidates for a `parent` window or frame by first checking the values of `window.opener` and `window.parent`. If `window.opener !== null` or `window.parent !== window` then they are candidates for a parent window or frame. As iframes can be nested we can also search for candidates that are parents of a parent frame, e.g.:\n\n```ts\n/**\n * Recursive search for all possible parent frames (windows) that we may\n * target with the WCP.\n * @param startWindow window object to search\n * @param found window objects found so far\n * @return An array of Window Objects representing 'parent' frames of the\n * specified window.\n */\nfunction discoverProxyCandidates(startWindow: Window, found: Window[]) {\n  _recursePossibleTargets(startWindow, startWindow, found);\n  Logger.debug(`Possible parent windows/frames found: ${found.length}`);\n  return found;\n}\n\nfunction _recursePossibleTargets(startWindow: Window, w: Window, found: Window[]) {\n  if (w) {\n    if (found.indexOf(w) == -1 && w != startWindow) {\n      found.push(w);\n    }\n\n    if (!!w.opener) {\n      _recursePossibleTargets(startWindow, w.opener, found);\n    }\n\n    if (w.parent != w) {\n      _recursePossibleTargets(startWindow, w.parent, found);\n    }\n  }\n}\n```\n\nSetup a timer for specified timeout, and then for each `candidate` found, attempt to establish communication with it as follows:\n\n  1. Add a listener (`candidate.addEventListener(\"message\", (event) => {})`) to receive response messages from the `candidate`.\n  2. Send a [`WCP1Hello`](pathname:///schemas/next/api/WCP1Hello.schema.json) message to it via `postMessage`.\n\n  ```ts\n  const hello = {\n    type: \"WCP1Hello\",\n    payload: {\n      identityUrl: identityUrl,\n      actualUrl: actualUrl,\n      fdc3Version: \"2.2\",\n      intentResolver: true,\n      channelSelector: true\n    },\n    meta: {\n      connectionAttemptUuid: \"bc96f1db-9b2b-465f-aab3-3870dc07b072\",\n      timestamp: \"2024-09-09T11:44:39+00:00\"\n    }\n  };\n  candidate.postMessage(hello, { targetOrigin: \"*\" });\n  ```\n\n  Note that the `targetOrigin` is set to `*` as the origin of the Desktop Agent is not known at this point.\n  3. Accept the first correct response received from a candidate. Correct responses MUST correspond to either the [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json) or [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json) message schemas and MUST quote the same `meta.connectionAttemptUuid` value provided in the original `WCP1Hello` message. Stop the timeout when a correct response is received. If no response is received from any candidate, the `getAgent()` implementation MAY retry sending the `WCP1Hello` message periodically until the timeout is reached.\n  4. If a [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json) was received in the previous step, skip this step and move on to step 5. However, If a [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json) was received in the previous step:\n      - Create a hidden iframe within the page, set its URL to the URL provided by the `payload.iframeUrl` field of the message and add a handler to run when the iframe has loaded:\n          ```ts\n          const loadIframe = (url: string, loadedHandler: () => void): WindowProxy => {\n            const ifrm = document.createElement(\"iframe\");\n            iframe.onload = loadedHandler;\n            ifrm.src = url;\n            ifrm.style.width = \"0\";\n            ifrm.style.height = \"0\";\n            ifrm.style.visibility = \"0\";\n            ifrm.ariaHidden = \"true\";\n            document.body.appendChild(ifrm);\n            return ifrm.contentWindow;\n          };\n          ```\n      - Once the frame has loaded (i.e. when the `loadedHandler` in the above example runs), repeat steps 1-3 above substituting the  iframe's `contentWindow` for the candidate window objects before proceeding to step 5. A new timeout should be used to limit the amount of time that the `getAgent()` implementation waits for a response. If the event that this subsequent timeout is exceeded, reject Error with the `ErrorOnConnect` message from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\n        :::tip\n\n        To ensure that the iframe is ready to receive the `WCP1Hello` message when the `load` event fires, implementations should call `window.addEventListener` for the `message` event synchronously and as early as possible.\n\n        :::\n\n  5. At this stage, a [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json) message should have been received from either a candidate parent or a hidden iframe created in step 4 above. This message MUST have a `MessagePort` appended to it, which is used for further communication with the Desktop Agent. It MUST also contain URLs for any Intent Resolver or Channel Selector UIs to be injected into the page (or `false` to indicate that they are not in use) and MAY contain custom timeout settings to use for API message exchanges.\n\n  Add a listener (`port.addEventListener(\"message\", (event) => {})`) to receive messages from the selected `candidate`, before moving on to the next stage.\n  6. If no candidates were found or no [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json) has been received by the time that the timeout expires, then neither a Desktop Agent Preload or Desktop Agent Proxy interface has been discovered. If this occurs, the `getAgent()` implementation will run any `failover` function provided as a parameter to `getAgent()`, allowing the application to provide an alternative means of connecting to or starting up a Desktop Agent.\n  \n  An async failover function may resolve to either a `DesktopAgent` implementation or the application may create either an iframe or open a new window, load an appropriate URL for a Desktop Agent implementation and resolve to its `WindowProxy` reference (e.g. `iframe.contentWindow` or the result of a call to `window.open(...)`).\n  \n  If the failover function resolves to a `DesktopAgent` implementation it should be immediately returned in the same way as a `window.fdc3` reference was and handled as if it represents a Desktop Agent Preload interface.\n\n  If the failover function resolves to a `WindowProxy` object, repeat steps 1-3 & 5 above substituting the `WindowProxy` for the candidate window objects before proceeding to the next step.\n\n  :::tip\n\n  Where possible, iframe failover functions should wait for the iframe or window represented by a `WindowProxy` object to be ready to receive messages before resolving. For an iframe this is a case of waiting for the `load` event to fire.\n\n  :::\n\n### Step 2: Validate app & instance identity\n\nApps and instances of them identify themselves so that DAs can positively associate them with their corresponding AppD records and any existing instance identity.\n\nIn the current FDC3 version, no identity validation procedures are provided for Desktop Agent Preload interfaces. Hence, it is the responsibility of such implementations to validate the identity of apps within their scope and to ensure that they update their own record of the identity if it changes during the life of the window hosting the application (i.e. due to a navigation event). It is expected that FDC3 will adopt identity validation procedures for Desktop Agent Preload interfaces in future.\n\n#### 2.1 Determine App Identity\n\nIn Desktop Agent Proxy interfaces, identity is ascertained via the [`WCP4ValidateAppIdentity`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message, which should be the first message sent on the `MessagePort` received by the `getAgent()` implementation after receiving it via [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json). Any other messages sent via the `MessagePort` prior to successful validation of a [`WCP4ValidateAppIdentity`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message should be ignored.\n\nAn app identity is determined and an `appId` assigned by matching the application to an AppD record already known to the Desktop Agent, based on the `identityUrl` provided in the [`WCP4ValidateAppIdentity`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message. An additional `actualUrl` field MUST also be provided to indicate whether the app overrode its `identityUrl` and to allow for logging. The origin (protocol, domain and port) of the `identityUrl`, `actualUrl` and the `MessageEvent.origin` field of the original `WCP1Hello` message that started the connection flow MUST all match. See the [Browser-Resident Desktop Agent Specification](./browserResidentDesktopAgents#validating-app-identity) for details of how to match an `identityUrl` to the `details.url` field of an AppD record.\n\nIf the app identity is not recognized, the Desktop Agent MUST respond with a [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityFailedResponse.schema.json) message and stop handling further messages on the `MessagePort`. On receiving this message, the `getAgent()` implementation should reject with an Error object with the `AccessDenied` message from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\nIf the app identity is recognized the Desktop Agent will assign the appropriate appId and move on to determining the instance identity.\n\n#### 2.2 Determine Instance Identity\n\nIf this instance of the application has connected to a Desktop Agent before and is reconnecting (due to a navigation or refresh event) then the optional `instanceId` and `instanceUuid` should be set in the [`WCP4ValidateAppIdentity`](pathname:///schemas/next/api/WCP4ValidateAppIdentity.schema.json) message. The Desktop Agent MUST use these values to determine if it recognizes the app instance identity and that it was previously applied to application with the same `appId`.\n\nAn `instanceUuid` is used to validate instance identity because `instanceId` of an application is available to other apps through the FDC3 API and might be used to 'spoof' an identity. On the other hand, `instanceUuid` is only issued through the WCP to the specific app instance and is used as a shared secret to enable identity validation. However, as `SessionStorage` data may be cloned when new windows on the same origin are opened via `window.open()`, Desktop Agents MUST also compare the `WindowProxy` object (via the `==` operator) that the original `WCP1Hello` messages were received on to determine if they represent the same window.\n\nSee the [Browser-Resident Desktop Agent Specification](./browserResidentDesktopAgents#validating-instance-identity) for further details of how instance identity is assigned.\n\nIf no existing instance identity (`instanceId` and `instanceUuid`) is provided, or instance identity validation fails (as the `instanceUuid` is not known, or either the `appId` or `WindowProxy` objects don't match the previous connection), then the Desktop Agent MUST assign new `instanceId` and `instanceUuid` values.\n\nThe Desktop Agent MUST then respond with a [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/next/api/WCP5ValidateAppIdentityResponse.schema.json) message containing the assigned `appId`, `instanceId` and `instanceUuid` values and the [`ImplementationMetadata`](../ref/Metadata#implementationmetadata) object for the Desktop Agent. This message indicates that the Desktop Agent will accept the application and we can begin processing [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) messages relating to FDC3 API calls over the `MessagePort`.\n\n### Step 3: Persist DesktopAgentDetails to SessionStorage\n\nOnce a connection is established, and the app and instance identity determined, a `DesktopAgentDetails` record MUST be stored in SessionStorage under the `FDC3-Desktop-Agent-Details` key by the `getAgent()` implementation. This record includes:\n\n- The `identityUrl` and `actualUrl` passed to `getAgent()`.\n- The `appId`, `instanceId`, and `instanceUuid` assigned by the DA.\n- An `agentUrl` field with the URL provided in any [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json) message that was received\n  - Used to skip sub-steps 1-3 in the discovery process described in Step 1.2.\n  - If no [`WCP2LoadUrl`](pathname:///schemas/next/api/WCP2LoadUrl.schema.json) message was received, omit this field.\n- An `agentType` field which indicates what type of connection to the DA was established\n  - Used to limit the discovery process in Step 1.2 above to only allow agents of the same type.\n  - the `getAgent()` implementation should determine what value to set, from the `WebDesktopAgentType` enumeration for this field based on what happened during the discovery process.\n\nSee the [reference documentation for getAgent()](../ref/GetAgent#persisted-connection-data) for further details of the `DesktopAgentDetails` record that should be saved to SessionStorage.\n\n:::tip\n\nSessionStorage is ephemeral, only existing for the duration of the window's life. Hence, there is no concern with the key being overwritten or conflicting with other DAs.\n\n:::\n\n### Step 4: Resolve promise with DesktopAgent interface (step 4)\n\nResolve the `getAgent()` promise with an object containing either a `DesktopAgent` implementation (that was found at `window.fdc3` or returned by a `failover` function) or a 'Desktop Agent Proxy' implementation (a class implementing the `DesktopAgent` interface that uses the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) to communicate with a Desktop Agent over the `MessagePort`).\n\nWhere a `DesktopAgent` or 'Desktop Agent Proxy' implementation was successfully returned, any subsequent calls to `getAgent()` that are not preceded by a navigation or refresh event, should resolve to the same instance.\n\n### Step 5: Disconnection\n\nDesktop Agent Preload interfaces, as used in container-based Desktop Agent implementations, are usually able to track the lifecycle and current URL of windows that host web apps in their scope. Hence, there is currently no requirement nor means for an app to indicate that it is closing, rather it is the responsibility of the Desktop Agent to update its internal state when an app closes or changes identity.\n\nHowever, Browser Resident Desktop Agents working with a Desktop Agent Proxy interface may have more trouble tracking child windows and frames. Hence, a specific WCP message ([`WCP6Goodbye`](pathname:///schemas/next/api/WCP6Goodbye.schema.json)) is provided for the `getAgent()` implementation to indicate that an app is disconnecting from the Desktop Agent and will not communicate further unless and until it reconnects via the WCP. The `getAgent()` implementation MUST listen for the `pagehide` event from the HTML Standard's [Page Life Cycle API](https://html.spec.whatwg.org/multipage/document-lifecycle.html#document-lifecycle) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event), [Chrome for Developers](https://developer.chrome.com/docs/web-platform/page-lifecycle-api#developer-recommendations-for-each-state)) and send [`WCP6Goodbye`](pathname:///schemas/next/api/WCP6Goodbye.schema.json) if it receives an event where the `persisted` property is `false`.\n\nAs it is possible for a page to close without firing this event in some circumstances (e.g. where a browser render thread crashes), other procedures for detecting disconnection may also be used, these are described in the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents#disconnects) and [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol#checking-apps-are-alive).\n\n### `getAgent()` Workflow Diagram\n\nThe workflow defined in the Web Connection protocol for `getAgent()` is summarized in the below diagram:\n\n```mermaid\n---\ntitle: \"Web Connection Protocol Flowchart\" \n---\nflowchart TB\n    A1([DesktopAgent launches app]) --> A2[\"App calls getAgent()\"]\n    A2 --> A3\n\n    subgraph getAgent [\"getAgent()\"]\n      A3[\"Check for DesktopAgentDetails in SessionStorage\"] --> P1{\"Does window.fdc3 exist?\"}\n      P1 -->|yes|P2[\"Stop timeout\"]\n      P2 --> P21[\"Save DesktopAgentDetails to SessionStorage\"]\n      P1 -->|No|P3[\"Listen for fdc3Ready\"]\n      P3 --> P31[\"fdc3Ready event fires\"]\n      P31 --> P32[\"Stop timeout\"]\n      P32 --> P33[\"Save DesktopAgentDetails to SessionStorage\"]\n      \n      A3 --> B1{\"Do parent refs exist?\"}\n      B1 -->|yes|B11[\"Send WCP1Hello to all candidates\"]\n      B11 --> B2[\"Receive WCP2LoadUrl\"]\n      B2 --> B21[\"Stop timeout\"]\n      B21 --> B22[\"Create hidden iframe with URL\"]\n      B22 --> B23[\"Await iframe's load event\"]\n      B23 --> B24[\"Send WCP1Hello to iframe\"]\n      B24 --> B3[\"Receive WCP3Handshake with MessagePort\"]\n      B3 --> B31[\"Stop timeout\"]\n      B11 --> B3\n      B31 --> B32[\"Send WCP4ValidateIdentity on MessagePort\"]\n      B32 --> B321[\"Receive WCP5ValidateIdentityResponse\"]\n      B321 --> B3211[\"Create DesktopAgentProxy to process DACP messages\"]\n      B3211 --> B3212[\"Save DesktopAgentDetails to SessionStorage\"]\n      B32 --> B322[\"Receive WCP5ValidateIdentityFailedResponse\"]\n      \n      A3 --> T1[\"Set timeout\"]\n      T1 --> T2[\"Timeout expires\"]\n      T2 --> T3{\"Was a failover fn provided\"}\n      T3 -->|yes|T31[\"Run failover\"]\n      T31 --> T311{\"Check failover return type\"}\n      T311 -->|WindowProxy|T3111[\"Send WCP1Hello via WindowProxy\"]\n      T311 -->|DesktopAgent|T3112[\"Save DesktopAgentDetails to SessionStorage\"]\n      T3111 --> B3\n    end\n    P21 -->P22([\"Resolve with window.fdc3\"])\n    P33 -->P34([\"Resolve with window.fdc3\"])\n    B3212 --> B3213([\"Resolve with DesktopAgentProxy\"])\n    B322 --> B3221([\"Reject with AgentError.AccessDenied\"])\n    T3112 --> T31121([\"Resolve with DesktopAgent\"])\n    T3 -->|no|T32([\"Reject with AgentError.AgentNotFound\"])\n    T311 -->|other|T3113[\"Reject with AgentError.InvalidFailover\"]\n```\n\n## Providing Channel Selector and Intent Resolver UIs\n\nUsers of FDC3 Desktop Agents often need access to UI controls that allow them to select user channels or to resolve intents that have multiple resolution options. Whilst apps can implement these UIs on their own via data and API calls provided by the `DesktopAgent` API, Desktop Agents typically provide these interfaces themselves.\n\nHowever, Browser Resident Desktop Agents may have difficulty displaying user interfaces over applications for a variety of reasons (inability to inject code, lack of permissions to display popups, user gestures not following cross-origin comms, etc.), or may not (e.g. because they render applications in iframes within windows they control and can therefore display content over the iframe). The Web Connection Protocol and the `getAgent()` implementation based on it and incorporated into apps via the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), is intended to help Desktop Agents deliver these UIs where necessary.\n\n```mermaid\nflowchart LR\n  subgraph DA [Desktop Agent Window]\n    A[(Desktop Agent)]\n  end\n  A-->B[\"getAgent()\"]\n  subgraph App [App Window]\n    B\n    subgraph iframe1 [iframe 1]\n      cs[Channel Selector]\n    end\n    subgraph iframe2 [iframe 2]\n      ir[Intent Resolver]\n    end\n  end\n  B-->cs\n  B-->ir\n```\n\nThe WCP allows applications to indicate to the `getAgent()` implementation whether they need the UIs (they may not need one or the other based on their usage of the FDC3 API, or because they implement UIs themselves) and for Desktop Agents to provide custom implementations of them, or defer to reference implementations provided by the FDC3 Standard. This is achieved via the following messages:\n\n- [`WCP1Hello`](pathname:///schemas/next/api/WCP1Hello.schema.json): Sent by an application and incorporating boolean `payload.intentResolver` and `payload.channelSelector` fields, which are set to `false` if either UI is not needed (defaults to `true`).\n- [`WCP3Handshake`](pathname:///schemas/next/api/WCP3Handshake.schema.json): Response sent by the Desktop Agent and incorporating `payload.intentResolverUrl` and `payload.channelSelectorUrl` fields, which should be set to the URL for each UI implementation that should be loaded into an iframe to provide the UI (defaults to URLs for reference UI implementations provided by the FDC3 project), or set to `false` to indicate that the respective UI is not needed. Setting these fields to `true` will cause the `getAgent()` implementation to use its default URLs representing a reference implementation of each UI.\n\nWhen UI iframes are created, the user interfaces may use the `Fdc3UserInterface` messages incorporated into the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol#controlling-injected-user-interfaces) to communicate with the `getAgent()` implementation and through it the Desktop Agent.\n"
  },
  {
    "path": "website/docs/api/supported-platforms.md",
    "content": "---\nid: supported-platforms\ntitle: Supported Platforms\n---\n\nFDC3 is platform- and programming language-independent. An FDC3-capable platform requires a Desktop Agent that supports the FDC3 standard, and that agent is responsible for coordinating application interactions.\n\nThere are two main categories of platform: web and native, both of which are described below. There exists a third category, hybrid, where a web application runs within the context of a standalone native application via a web view.\n\n## Web\n\n:::tip\n\nThe recommended way to get access to the FDC3 Desktop Agent API in an application is to to import and call the `getAgent` function from the FDC3 NPM module, which supports all FDC3 Standard conformant Desktop Agents for web applications:\n\n```ts\nimport { DesktopAgent, getAgent, AgentError } from \"@finos/fdc3\";\n\n//...\n\ntry {\n    const desktopAgent: DesktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e: AgentError) {\n    //connection failed\n}\n\n//OR\n\ngetAgent().then((desktopAgent: DesktopAgent) => {\n    //do FDC3 things here\n}).catch((e: AgentError) => {\n    //connection failed\n});\n```\n\n[For more details on the getAgent() function and arguments you can pass to it, see its reference page.](ref/GetAgent)\n\n:::\n\nFor a web application to use the FDC3 API it needs to retrieve a copy of the `DesktopAgent` API interface, which it will use to communicate with the Desktop Agent (this interface is often referred to as the `fdc3` object or the \"FDC3 API\"). FDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can be used by web applications to retrieve a `DesktopAgent` interface and to provide typing. Each FDC3-compliant Desktop Agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n<Tabs>\n<TabItem value=\"npm\" label=\"npm\">\n\n```bash\nnpm install @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"yarn\" label=\"yarn\">\n\n```bash\nyarn add @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"pnpm\" label=\"pnpm\">\n\n```bash\npnpm install @finos/fdc3\n```\n\n</TabItem>\n</Tabs>\n\nThere are two standardized types of interface to a DA that a web application may use (which is appropriate depends on where the web application is run):\n\n- **Desktop Agent Preload**: Used where the Desktop Agent is able to inject the the `DesktopAgent` API at `window.fdc3` allowing an app to access it directly, for example in an Electron app or where a browser Browser Extension is in use.\n- **Desktop Agent Proxy**: Used when running in a standard web browser (without a browser extension or similar customization). The Desktop Agent will often be running in a different window or frame to the application and MUST be communicated with via cross-document messaging with `postMessage` and `MessagePorts` (see the [HTML5 Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html) for more details). A 'proxy' class implementing the Desktop Agent API is used to abstract the details of cross-document messaging, allowing the application to work with the FDC3 API directly.\n\nThe FDC3 Standard defines a [Web Connection Protocol (WCP)](specs/webConnectionProtocol) that allows apps to work with either interface, by detecting which is applicable, and [Desktop Agent Communication Protocol (DACP)](specs/desktopAgentCommunicationProtocol) that standardizes the messaging protocol used for cross-document messaging over `postMessage` and `MessagePorts` in a web browser.\n\nThe FDC3 NPM module implements the `getAgent()` function defined by WCP and can return an injected Desktop Agent, a Desktop Agent Proxy, or other Desktop Agent implementation enabled by a non-standard interface.\n\nHence, FDC3 apps SHOULD obtain access to a `DesktopAgent` object (`fdc3`) by importing or loading the `@finos/fdc3` library and then calling the provided `getAgent()` function, ensuring that they can support any of the standardized interfaces.\n\n:::info\n\nIn prior versions of FDC3 (&lt;= 2.1) Apps were required to use the 'Desktop Agent Preload' interface, i.e. they relied on the existence of the `window.fdc3` object, which meant that apps running in a standard web browser had to import libraries specific to the Desktop Agent implementation in use. From FDC3 2.2 onwards the 'Desktop Agent Proxy' interface is available, which allows apps in a standard web browser to connect to any Desktop Agent that implements that interface.\n\nHence, from FDC3 2.2 onwards apps SHOULD call `getAgent()` to retrieve a `DesktopAgent` API interface.\n\n:::\n\nAs web applications can navigate to or be navigated by users to different URLs and become different applications, validation of apps identity is often necessary. The web application's current URL is passed to web browser-based Desktop Agents to allow them to establish the app's identity - usually connecting it with an App Directory record already known to the Desktop Agent. For more details on identity validation see the Identity Validation section of the [Web Connection Protocol (WCP)](specs/webConnectionProtocol).\n\n### Usage\n\nOnce you've retrieved a `DesktopAgent` interface you may use its functions to communicate with the Desktop Agent and through it, other applications:\n\n```js\nimport { DesktopAgent, getAgent } from \"@finos/fdc3\";\n\nasync function sendData(desktopAgent: DesktopAgent) {\n  await desktopAgent.broadcast({\n    type: \"fdc3.instrument\",\n    id: { ticker: \"AAPL\" }\n  });\n}\n\nconst desktopAgent: DesktopAgent = await getAgent();\nawait sendData(desktopAgent);\n```\n\n:::caution\nFor JavaScript implementations of the FDC3 API, all public methods on objects such as `DesktopAgent`, `Channel`, `PrivateChannel`, `IntentResolution`, etc **MUST be explicitly bound to their instance** using `.bind(this)` in their constructor. This ensures proper behavior when methods are destructured, which is a common practice in modern JavaScript code.\n:::\n\n## Native\n\nThe FDC3 Standard currently only defines language specific API bindings for JavaScript/TypeScript and .NET, but is intended to be implemented in other languages (which can make use of the [Desktop Agent Communication Protocol (DACP)](specs/desktopAgentCommunicationProtocol) as a wire protocol, but need to define a suitable connection protocol, which includes a defined communication channel to do so).  \n\nHence, for a native application to be FDC3-enabled, it needs to either:\n\n- Make use of a shared library (such as a .NET DLL or JAR file) that provides it with an implementation of the FDC3 API (which ties it to a specific Desktop Agent implementation).\n- Model itself as a Desktop Agent (rather than just an app working with one) and use the Agent Bridging protocol to connect to a Desktop Agent Bridge and work through it to interoperate with apps managed by other Desktop Agents.\n\n### .NET\n\nFor a .NET application to be FDC3-enabled, it needs to run in the context of a platform provider that makes the FDC3 API available.  The manner in which you get a reference to the desktop agent can be highly dependent on the provider chosen.  For those looking to implement your own desktop agent, a recommended and typical design is to register an instance of the Desktop Agent at startup which can be injected into any class constructors that need references through inversion of control.  More details for creating your own DesktopAgent can be found in the [fdc3-dotnet repository](https://github.com/finos/fdc3-dotnet).\n\n#### Usage\n\nFDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can be used by .NET applications to target operations from the [API Specification](./spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\n### GO\n\n[`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.3 and may be refined by further changes outside the normal FDC3 versioning policy.\n\nFor a Go application to be FDC3-enabled, it needs to run in the context of a platform provider that makes the FDC3 API available to Go applications. The Go language API binding varies from the JavaScript/TypeScript implementation in a number of ways due to the specifics of the Go language. Namely:\n- A `Result` type, as described in [the Desktop Agent specs](../api/ref/DesktopAgent.md#desktopagent), is returned by API calls to accommodate for error handling via golang Channels. Channel is the closest equivalent to `Promise`. Result type has `Value` and `Err` fields, where `Value` type corresponds with the return type expected from this function, and `Err` would contain the golang `error` type error for handling:\n\n    ```go\n    type Result[T any] struct {\n        Value *T\n        Err   error\n    }\n    ```\n    \n- In order to create [additional contexts](../context/ref/), please use the provided type [Context](../api/ref/Types.md/#context) as a field in the custom contexts. This way the base fields (\"type\", \"name\", \"id\") will be embedded in the resulting json:\n\n    ```go\n    type TimeRange struct {\n        Context\n        StartTime string `json:\"startTime\"`\n        EndTime string `json:\"endTime\"`\n    }\n    ```\n    \n    However, this is a trade-off, since this is optimized for the ability to create the correct json, however, it introduces the need for each of the specific context classes to implement the interface [IContext](../api/ref/Types.md/#context) which is ultimately not required. Add at least one method in your implementation of IContext, and implement it for Context type as well as any other specific contexts you create, for example:\n\n    ```go\n    type IContext interface {\n       MarshalContext() []byte, err\n    } \n\n    func (context *Context)  MarshalContext() []byte, err {\n\n    }\n\n    func (timeRangeContext *TimeRange)  MarshalContext() []byte, err {\n      \n    }\n    ```\n\n- Golang has no strict requirement for a type to declare that it implements an interface: if a type implements a specific method, then it implements that interface implicitly. The Go language binding for FDC3 includes `interface`, `struct` and `func` types for all of the entities defined in the FDC3 API Part (i.e. `DesktopAgent`, `Channel`, `AppIdentifier`, `ContextHandler` etc.) . However, to be able to use the interfaces, specific types need to be created with the implementation of that interface, even if they are empty structs. Hence, types for these are defined alongside the interface (ex. [`DesktopAgent` is an empty struct, but it would implement methods of the IDesktopAgent interface](../api/ref/DesktopAgent.md#desktopagent)).\n- Deprecated functions with the same name as other functions are omitted in golang, as it does not allow function/method overloading. In the event that additional function/method overloads are added to FDC3 these should be handled in the Go binding with a different function name to the overloaded function.\n\n## Hybrid\n\nIn a hybrid application, a standalone native application incorporates a web view, within which a web application runs. This may be considered a special case of the web platform where all platform-provider requirements for web applications must be satisfied, but it is the responsibility of the associated native application, rather than a platform provider, to ensure they are fulfilled. This may be achieved via either of the defined web interfaces, i.e. by injecting an implementation of the DesktopAgent API at `window.fdc3` or via the FDC3 Web Connection Protocol (`postMessage`).\n\n## Compliance\n\nSupport for each platform is optional and compliance with the FDC3 standard should be assessed for each platform implemented independently of any other, with the exception of ensuring that where applications running on multiple platforms are used together, communication between them still complies with the standard.\n\nThe Web API binding is expressed using TypeScript syntax that defines the API interface (for both TypeScript and JavaScript). Adherence to the specific binding is required for Web application platforms. No specific API binding for native platforms is currently expressed in the Standard. Hence, native applications may be implemented with any programming language binding that supports the constructs required by the API specification, until such time that the FDC3 Standard introduces an appropriate language-specific binding.\n"
  },
  {
    "path": "website/docs/app-directory/overview.md",
    "content": "---\nid: overview\nsidebar_label: Overview\ntitle: App Directory Overview (next)\n---\n\nAn application directory (appD) is a structured repository of information about apps that can be used in an FDC3-enabled desktop. In other words, it’s a convenient way of storing and managing metadata about apps in your ecosystem.\n\nThis section provides a conceptual overview of the App Directory, explaining what it is, who uses it, and how it fits into an FDC3-enabled desktop. It is intended for readers who are new to App Directory concepts, before moving on to the more detailed API and specification sections.\n\nThe application metadata stored in appD records may include: the app name, type, details about how to run the application, its icons, publisher, support contact details and so on. It may also include links to or embed manifest formats defined elsewhere, such as proprietary manifests for launching the app in a container product or a Web Application Manifest (as [defined by the W3C](https://www.w3.org/TR/appmanifest/)).\n\nAll this information is readily available in one place and can be used both to populate a launcher or app catalog UI for your users, and by the Desktop Agent managing the apps on your desktop. In fact, if your desktop platform supports the FDC3 standard, appD is the primary way that the FDC3 Desktop Agent implementation should receive the details about apps available to run on your desktop. Conversely, if an app is not listed in appD, the Desktop Agent can’t ensure its participation in context sharing or use it to resolve intents.\n\n## Advantages\n\nUsing appD offers many advantages both for financial institutions running an FDC3-enabled desktop container and for vendors that provide FDC3-compliant apps:\n\n### For the user\n\n#### Easier to Find App Info\n\nYour appD is the one place to collect all the information about apps. The more apps you have, the more you’ll appreciate the convenience of not having to chase down details about each. This is particularly important for large institutions with multiple desks.\n\n#### Human Readable\n\nAppD has two types of users. One is the Desktop Agent, but the other is humans administering and using the smart desktop at your organization. Hence, an appD contains information about apps in both machine- and human-readable forms. For example, it includes both unique identifiers for apps that are used to refer to them in code and human-friendly app names, icons, descriptions and tooltips necessary to populate a launcher menu or app catalog user interface for your users.\n\n#### Apps are Discoverable\n\nFor large institutions, it can be difficult to keep track of all the apps (developed both in-house and by vendors), since a typical desktop could have many. Users can search appD to discover the apps they need. An app might already reside on their system or be available to them over the internet, but if they don’t have a way to search the apps available to them, they won’t be able to find it. An appD provides a way for users to discover the apps they need.\n\nAn appD makes it possible to discover info about apps that reside on various domains, not just the one domain the appD itself is hosted on. In addition, you can find details about how to launch the apps in multiple, diverse environments. This is a different use-case to, for example, the [W3C's Web App Manifest](https://www.w3.org/TR/appmanifest/), which is hosted on the same domain as the app, is limited to web apps, and is generally used to 'install' an app that the user has already accessed.\n\n#### Updating Apps\n\nTypically, software evolves over time. The app versions you are running today will not be the same ones you need tomorrow. Therefore, you will need to upgrade apps periodically. Very few people look forward to upgrading, but appD and web deployment can make it easier for you. To roll out a new version of your app, either update the existing entry for it in appD or add a new entry for that version (allowing users to select the version they will use).\n\n#### Agent-agnostic\n\nAs a part of the FDC3 standard, appD isn't tied to any specific vendor. This is important, as it allows you more flexibility in that you are not tied to any specific container or Desktop Agent implementation. If at any point you want to switch to a different Desktop Agent, the process won’t be prohibitively difficult. The existing appD will work without any additional effort from you, as long as your new Desktop Agent is also FDC3-compliant. This is in contrast with proprietary solutions, where you would have to produce a new configuration and integration for every application.\n\nAppD reduces fragmentation in the market and allows end-users more flexibility in what applications can be included in their desktop.\n\n#### Intent Resolution\n\nAppD provides information to the Desktop Agent on which applications can handle particular [intents](../intents/spec) and the context types they support as input to them. This allows the Desktop Agent to implement an [intent resolver](../api/spec#resolvers) that can launch applications and pass the intent and context to them to operate on, supporting workflows between applications that didn't require prior bilateral agreements between the application providers.\n\n### For an Application Provider\n\nUntil now, we've looked at appD from the perspective of a desktop owner and user. But appD also offers advantages to vendors who develop apps for the financial services desktop.\n\n#### Apps Work Well Together Out-of-the-box\n\nWhen your customers add your FDC3-compliant app to their desktop via an appD record accurately describing it, you can be sure that your app will interoperate with other apps that follow the FDC3 standard. You don’t have to do anything special, or arrange a bilateral agreement with anyone else. The benefit of the open standard is that any app that follows it will work well with any other compliant app.\n\n#### Easy Updates\n\nAs a vendor, you prefer for all your customers to run your latest software. However, many customers will postpone upgrades, sometimes for a long time, because upgrading can be a pain. An advantage of a vendor-hosted appD is that the configuration of an app can be updated at any time and, if your customers need to choose when to upgrade, multiple versions of it can be made available, each with their own configuration. By making it easier for customers to update, you can drive better adoption.\n\n### For the Industry\n\nBy hosting our own appD we can easily combine applications from various providers into one cohesive directory. Alternatively, we can connect to directories from multiple providers (in standardized format) and provide a single view over them. This reduces fragmentation in the market, allows end-users more flexibility in what apps to include in their smart desktop, and obviates the need for vendors to provide application details in diverse formats or for their customers to work out these details for themselves.\n\n## Relationship to Other Standards\n\nThe App Directory's application record is similar to application manifests defined in other standards, in particular the W3C's [Web Application Manifest](https://www.w3.org/TR/appmanifest/). However, the App Directory, and by extension the application record, serve a different set of use-cases specific to application interoperability on financial services desktops, which other standards do not fully address.\n\nWherever possible, FDC3 seeks to draw inspiration from, align itself with and reference other standards - ensuring that conventions and best practices developed by those standards are reused, along with the standard itself (e.g. data formats in ISO standard formats, external links to technology-specific manifest file formats etc.). For a list of standards that FDC3 references, see the [References](../references) page.\n\n## Use Cases\n\nAn application directory provides information about an application's identifiers, publisher details, intents that it supports, and metadata necessary to launch and integrate the application in a Desktop Agent.\n\nThe following provides a summary of use cases.\n\n### Launcher\n\nA Desktop Agent will usually include a user interface allowing the user to select from a set of launchable applications and then allow them to manually launch one. It is also responsible for launching applications necessary to resolve a raised intent. However, it must first retrieve the necessary metadata about the available applications. An app directory provides an endpoint to retrieve a list of the available applications along with their metadata, which may include or link to additional information necessary to launch the application in a specific Desktop Agent.\n\nA launcher will usually be configured with the locations of one or more AppD servers (which is necessary to implement intent resolution), however, as described in the [Service Discovery](#service-discovery) section, a fully qualified application identifier (e.g. `app1@host.appd.com`) may also be used to both locate the appD service and to retrieve the specific application data.\n\n![img](/assets/appd_launcher_embedded.png)\n\n### Aggregated View\n\nThere could be many different appD service instances in the world providing application data zoned to the provider or enterprise deployment. The appD specification allows for unique instances of the service with no requirement to aggregate data or define a structured hierarchy. With this said, a launcher might want to construct an aggregated view of applications from one or more appD instances. In this case, the launcher would be required to retrieve multiple application definitions from one or more appD instances providing a consolidated view of all applications required.\n\nToday, there is no intention to create a single registry of known AppD instances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location.\n\n![img](/assets/appd_launcher_aggregated.png)\n\n### Authentication and Entitlements\n\nThe AppD API specification defines the optional use of an access token to identify the requesting user/launcher and implement authorizations which may affect appD API responses. For example, different subsets of the full list of applications may be returned for different users depending on their role in an organization.\n\nThe specification does not define or make mandatory any authorizations or roles that a provider or enterprise can define.\n\nA key concept in the App Directory is how applications are identified and referenced across different environments. Application identifiers are used both to uniquely describe apps within a directory and, in some cases, to locate the directory instance that hosts an application’s record.\n\n## Application Identifiers\n\nApplication Records served by an app directory are each labelled with an identifier, `appId`, which should be unique within the app directory instance and may be used to refer to or retrieve the application's record via the [app directory API](spec). This identifier may be made globally unique through a nested namespace approach and email address construction (`appId@fqdn`) where `@` followed by the app directory instance's host name is appended to it. The resulting globally unique identifier is known as a 'fully qualified application identifier'.\n\nFully qualified appIds may be used to locate the appD instance hosting the application's record. See the [Service Discovery](#service-discovery) section for details.\n\n### Shrinking the URI\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID `app1@appd.foo.com` is represented as `app1` within the application directory.  As a result a launcher can use a shortened URI construct `https://appd.foo.com/api/appd/v2/apps/app1` to resolve the application data vs `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`.\n\n## Service Discovery\n\nIn order to support the discovery of applications that can be used with a Desktop Agent, it is necessary to access data stored in one or more app directory instances.\n\nBecause App Directory services may be hosted by different providers or enterprises, a Desktop Agent needs a way to determine where a given App Directory instance is located before it can retrieve application data. The FDC3 standard defines multiple discovery mechanisms to support different deployment and infrastructure models.\n\n![img](/assets/appd_service_distribution.png)\n\nHowever, in order to do so, you must first discover the location of an app directory service, which you may then use to generate URIs  (e.g. `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`) to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required.\n\nThree methods for discovering app directory services are defined in this Standard:\n\n  1. **Static configuration:** Statically defined URI records for use within client applications (typically a Desktop Agent implementation) directly.\n  2. **Fully-qualified appID namespace syntax host resolution:** Discovery of the appD location using a fully qualified application ID (appId) domain name.\n  3. **DNS lookup by domain name:** Discovery of the appD location using a domain name to lookup DNS SRV records identifying the host server location and TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782))\n\nApp directory service host discovery implementations SHOULD support each of these methods and MUST support at least static configuration.\n\n### Static configuration\n\nAs the name implies, a static configuration for an appD service location is defined within a Desktop Agent or launcher application. This is the simplest and most common approach to app directory and application data discovery.\n\n![img](/assets/appd_static_config.png)\n\n### Fully-qualified appID namespace syntax host resolution\n\nAn app directory URI can be constructed using a [fully qualified application ID](overview#application-identifiers) (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application id `app1` with a fully qualified identifier of `app1@appd.foo.com` an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" MUST resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by:\n\n1. URI protocol is defaulted to `https`, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default `https/443`, but can be overridden by the launcher\n4. URI url is by default `/api/appd/(version)/apps` . Calls that are made without version MUST automatically default to latest, i.e. `/api/appd/apps/app1` should return the same result as `/api/appd/v2/apps/app1\".\n\nThe resulting URI to retrieve application data for `app1` would be [https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com)\n\n### DNS/SRV Records\n\nAnother approach to support app directory service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an appD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well-known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```text\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *`service`*: the symbolic name of the desired service.  For AppD service, this must be identified as **`_appd`**\n- *`proto`*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *`name`*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *`TTL`*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *`class`*: standard DNS class field (this is always *IN*).\n- *`priority`*: the priority of the target host, lower value means more preferred.\n- *`weight`*: A relative weight for records with the same priority, higher value means more preferred.\n- *`port`*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *`target`*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record MUST use the following definitions:\n\n- `service` = **`_appd`**\n- `proto` = **`_tcp`**\n- `name` = must map to the domain of the application identifier . Example:  the `name` for application identifier `app1@appd.foo.com` would be `appd.foo.com`\n\n*AppD service through DNS / SRV records:*\n\n![img](/assets/appd_dns.png)\n\n#### Known domains\n\nAlthough SRV records provide the means of resolving the location of an app directory service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n"
  },
  {
    "path": "website/docs/app-directory/spec.md",
    "content": "---\nid: spec\nsidebar_label: API\ntitle: App Directory API (next)\n---\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/next/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/next/appd.schema.json\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v2/apps`         | GET    | Retrieve all application definitions\n `/v2/apps/{appId}` | GET    | Retrieve an application definition\n `/v1/apps`         | POST   | (deprecated v1 API version) Create a new application definition\n `/v1/apps/{appId}` | GET    | (deprecated v1 API version) Retrieve an application definition\n `/v1/apps/search`  | GET    | (deprecated v1 API version) Retrieve a list of applications\n\nApp Directory implementations MAY extend the list of endpoints to provide other necessary functionality. However, FDC3 Desktop Agent implementations that connect to app directories MUST support connection to app directories that only provide the minimum endpoints listed here.\n\n## App Directory Standard Compliance\n\nAn FDC3 Standard compliant App Directory implementation **MUST**:\n\n- Implement the specified `/v2` endpoints for retrieving app definitions as defined in the [app directory OpenAPI specification](pathname:///schemas/next/app-directory.html#tag/Application):\n  - `/v2/apps` (GET)\n  - `/v2/apps/{appId}` (GET)\n- Ensure that `appId` field values assigned to applications are unique within the directory.\n- Ensure that app directory records served meet the minimum requirements specified in the [app directory OpenAPI specification](pathname:///schemas/next/app-directory.html#tag/Application).\n- Support retrieval of app directory records via either the raw `appId` (e.g. `myAppId`) or fully-qualified appId (e.g. `myAppId@host.domain.com`) as defined in the [app directory overview](overview#shrinking-the-uri).\n\nAn FDC3 Standard compliant App Directory implementation **SHOULD**:\n\n- Support authentication (where required) via the HTTP Authorization header and Bearer authentication scheme (implemented via JWT tokens)\n- Select any `categories` field values from the recommended list.\n- Encourage the use of the `lang` and `localizedVersions` fields in appD records to support localization and accessibility.\n\nAn FDC3 Standard compliant App Directory implementation **MAY**:\n\n- Support filtering of application records returned by user entitlement, where authentication is enabled.\n- Implement the deprecated `/v1` endpoints provided for backwards compatibility with prior version of the standard:\n  - `/v1/apps` (POST)\n  - `/v1/apps/{appId}` (GET)\n  - `/v1/apps/search` (GET)\n- Extend the implementation with additional endpoints.\n"
  },
  {
    "path": "website/docs/context/ref/Action.md",
    "content": "---\ntitle: Action\nsidebar_label: Action\n\n---\n\n# Action\n\nA representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\n\nThe action may be completed by calling:\n- `fdc3.raiseIntent()` with the specified Intent and Context\n- `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\n- `channel.broadcast()` with the specified Context, if the `broadcast` action has been defined.\n\nAccepts an optional `app` parameter in order to specify a specific app.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/action.schema.json](pathname:///schemas/next/context/action.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/action.schema.json))\n\n## Type\n\n`fdc3.action`\n\n## Properties\n\n<details>\n  <summary><code>action</code></summary>\n\n**type**: `string` with values:\n- `broadcast`,\n- `raiseIntent`\n\nThe **action** field indicates the type of action:\n- **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent` or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if given).\n- **broadcast** : If `broadcast` and a `channelId` are specified then `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the context to it with `channel.broadcast(context)`. If no `channelId` has been specified, the context should be broadcast to the current channel (`fdc3.broadcast()`)\n\n</details>\n\n<details>\n  <summary><code>title</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA human readable display name for the action\n\n</details>\n\n<details>\n  <summary><code>intent</code></summary>\n\n**type**: `string`\n\nOptional Intent to raise to perform the actions. Should reference an intent type name, such as those defined in the FDC3 Standard. If intent is not set then `fdc3.raiseIntentForContext` should be used to perform the action as this will usually allow the user to choose the intent to raise.\n\n</details>\n\n<details>\n  <summary><code>context</code> <strong>(required)</strong></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\nA context object with which the action will be performed\n\n</details>\n\n<details>\n  <summary><code>channelId</code></summary>\n\n**type**: `string`\n\nOptional channel on which to broadcast the context. The `channelId` property is ignored unless the `action` is broadcast.\n\n</details>\n\n<details>\n  <summary><code>app</code></summary>\n\n**type**: api/AppIdentifier\n\nAn optional target application identifier that should perform the action. The `app` property is ignored unless the action is raiseIntent.\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.action\",\n  \"action\": \"raiseIntent\",\n  \"title\": \"Click to view Chart\",\n  \"intent\": \"ViewChart\",\n  \"context\": {\n    \"type\": \"fdc3.chart\",\n    \"instruments\": [\n      {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"EURUSD\"\n        }\n      }\n    ],\n    \"range\": {\n      \"type\": \"fdc3.dateRange\",\n      \"starttime\": \"2020-09-01T08:00:00.000Z\",\n      \"endtime\": \"2020-10-31T08:00:00.000Z\"\n    },\n    \"style\": \"candle\"\n  },\n  \"app\": {\n    \"appId\": \"MyChartViewingApp\",\n    \"instanceId\": \"instance1\"\n  }\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.action\",\n  \"action\": \"broadcast\",\n  \"channelId\": \"Channel 1\",\n  \"title\": \"Click to view Chart\",\n  \"context\": {\n    \"type\": \"fdc3.chart\",\n    \"instruments\": [\n      {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"EURUSD\"\n        }\n      }\n    ],\n    \"range\": {\n      \"type\": \"fdc3.dateRange\",\n      \"starttime\": \"2020-09-01T08:00:00.000Z\",\n      \"endtime\": \"2020-10-31T08:00:00.000Z\"\n    },\n    \"style\": \"candle\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/BaseContext.md",
    "content": "---\ntitle: BaseContext\nsidebar_label: BaseContext\n\n---\n\n# BaseContext\n\n## Schema\n\n[https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json](https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json)\n\n## Type\n\n`undefined`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n</details>\n"
  },
  {
    "path": "website/docs/context/ref/Chart.md",
    "content": "---\ntitle: Chart\nsidebar_label: Chart\n\n---\n\n# Chart\n\nA context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\n\n- A list of instruments for comparison\n- The time period to plot the chart over\n- The style of chart (line, bar, mountain, candle etc.)\n- Other settings such as indicators to calculate, or data representing drawings and annotations.\n\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/chart.schema.json](pathname:///schemas/next/context/chart.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chart.schema.json))\n\n## Type\n\n`fdc3.chart`\n\n## Properties\n\n<details>\n  <summary><code>instruments</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Instrument](Instrument)\n\n</details>\n\nAn array of instrument contexts whose data should be plotted.\n\n</details>\n\n<details>\n  <summary><code>range</code></summary>\n\n**type**: [TimeRange](TimeRange)\n\nThe time range that should be plotted\n\n</details>\n\n<details>\n  <summary><code>style</code></summary>\n\n**type**: `string` with values:\n- `line`,\n- `bar`,\n- `stacked-bar`,\n- `mountain`,\n- `candle`,\n- `pie`,\n- `scatter`,\n- `histogram`,\n- `heatmap`,\n- `custom`\n\nThe type of chart that should be plotted\n\n</details>\n\n<details>\n  <summary><code>otherConfig</code></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\n</details>\n\nIt is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chart\",\n  \"instruments\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"AAPL\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"GOOG\"\n      }\n    }\n  ],\n  \"range\": {\n    \"type\": \"fdc3.timeRange\",\n    \"startTime\": \"2020-09-01T08:00:00.000Z\",\n    \"endTime\": \"2020-10-31T08:00:00.000Z\"\n  },\n  \"style\": \"line\",\n  \"otherConfig\": [\n    {\n      \"type\": \"somevendor.someproduct.indicator\",\n      \"name\": \"stddev\",\n      \"parameters\": {\n        \"period\": 10,\n        \"matype\": \"exponential\"\n      }\n    },\n    {\n      \"type\": \"someothervendor.someotherproduct.formula\",\n      \"formula\": \"standard-deviation\",\n      \"fields\": {\n        \"lookback\": 10,\n        \"type\": \"ema\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/ChatInitSettings.md",
    "content": "---\ntitle: ChatInitSettings\nsidebar_label: ChatInitSettings\n\n---\n\n# ChatInitSettings\n\nA collection of settings to start a new chat conversation\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/chatInitSettings.schema.json](pathname:///schemas/next/context/chatInitSettings.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatInitSettings.schema.json))\n\n## Type\n\n`fdc3.chat.initSettings`\n\n## Properties\n\n<details>\n  <summary><code>chatName</code></summary>\n\n**type**: `string`\n\nName to apply to the chat created\n\n</details>\n\n<details>\n  <summary><code>members</code></summary>\n\n**type**: [ContactList](ContactList)\n\nContacts to add to the chat\n\n</details>\n\n<details>\n  <summary><code>message</code></summary>\n\n**One of:**\n\n- **type**: `string`\n- **type**: [Message](Message)\n\nAn initial message to post in the chat when created.\n\n</details>\n\n<details>\n  <summary><code>options</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>groupRecipients</code></summary>\n\n**type**: `boolean`\n\nif false a separate chat will be created for each member\n\n</details>\n\n<details>\n  <summary><code>isPublic</code></summary>\n\n**type**: `boolean`\n\nif true the room will be visible to everyone in the chat application\n\n</details>\n\n<details>\n  <summary><code>allowHistoryBrowsing</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to browse past messages\n\n</details>\n\n<details>\n  <summary><code>allowMessageCopy</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to copy/paste messages\n\n</details>\n\n<details>\n  <summary><code>allowAddUser</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to add other members to the chat\n\n</details>\n\nOption settings that affect the creation of the chat\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.initSettings\",\n  \"chatName\": \"Chat ABCD\",\n  \"members\": {\n    \"type\": \"fdc3.contactList\",\n    \"contacts\": [\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane@mail.com\"\n        }\n      },\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"John Doe\",\n        \"id\": {\n          \"email\": \"john@mail.com\"\n        }\n      }\n    ]\n  },\n  \"options\": {\n    \"groupRecipients\": true,\n    \"isPublic\": false,\n    \"allowHistoryBrowsing\": true,\n    \"allowMessageCopy\": true\n  },\n  \"message\": {\n    \"type\": \"fdc3.message\",\n    \"text\": {\n      \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n    },\n    \"entities\": {\n      \"0\": {\n        \"type\": \"fdc3.fileAttachment\",\n        \"data\": {\n          \"name\": \"myImage.png\",\n          \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n        }\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/ChatMessage.md",
    "content": "---\ntitle: ChatMessage\nsidebar_label: ChatMessage\n\n---\n\n# ChatMessage\n\nA context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/chatMessage.schema.json](pathname:///schemas/next/context/chatMessage.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatMessage.schema.json))\n\n## Type\n\n`fdc3.chat.message`\n\n## Properties\n\n<details>\n  <summary><code>chatRoom</code> <strong>(required)</strong></summary>\n\n**type**: [ChatRoom](ChatRoom)\n\n</details>\n\n<details>\n  <summary><code>message</code> <strong>(required)</strong></summary>\n\n**type**: [Message](Message)\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.message\",\n  \"chatRoom\": {\n    \"type\": \"fdc3.chat.room\",\n    \"providerName\": \"Symphony\",\n    \"id\": {\n      \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n    }\n  },\n  \"message\": {\n    \"type\": \"fdc3.message\",\n    \"text\": {\n      \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n    },\n    \"entities\": {\n      \"0\": {\n        \"type\": \"fdc3.fileAttachment\",\n        \"data\": {\n          \"name\": \"myImage.png\",\n          \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n        }\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/ChatRoom.md",
    "content": "---\ntitle: ChatRoom\nsidebar_label: ChatRoom\n\n---\n\n# ChatRoom\n\nReference to the chat room which could be used to send a message to the room\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/chatRoom.schema.json](pathname:///schemas/next/context/chatRoom.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatRoom.schema.json))\n\n## Type\n\n`fdc3.chat.room`\n\n## Properties\n\n<details>\n  <summary><code>providerName</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe name of the service that hosts the chat\n\n</details>\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nIdentifier(s) for the chat - currently unstandardized\n\n</details>\n\n<details>\n  <summary><code>url</code></summary>\n\n**type**: `string`\n\nUniversal url to access to the room. It could be opened from a browser, a mobile app, etc...\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nDisplay name for the chat room\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.room\",\n  \"providerName\": \"Symphony\",\n  \"id\": {\n    \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n  },\n  \"url\": \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n  \"name\": \"My new room\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/ChatSearchCriteria.md",
    "content": "---\ntitle: ChatSearchCriteria\nsidebar_label: ChatSearchCriteria\n\n---\n\n# ChatSearchCriteria\n\nA context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/chatSearchCriteria.schema.json](pathname:///schemas/next/context/chatSearchCriteria.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatSearchCriteria.schema.json))\n\n## Type\n\n`fdc3.chat.searchCriteria`\n\n## Properties\n\n<details>\n  <summary><code>criteria</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n  <summary><code>Search Criteria</code></summary>\n\n**One of:**\n\n- **type**: [Instrument](Instrument)\n- **type**: [Organization](Organization)\n- **type**: [Contact](Contact)\n- **type**: `string`\n\nAn individual criteria against which to match chat messages, based on an FDC3 context or free-text string.\n\n\n\n\n</details>\n\nAn array of criteria that should match chats returned from by a search.\n\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\n\nEmpty search criteria can be supported to allow resetting of filters.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.searchCriteria\",\n  \"criteria\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"TSLA\"\n      },\n      \"name\": \"Tesla, inc.\"\n    },\n    \"annual return\"\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Contact.md",
    "content": "---\ntitle: Contact\nsidebar_label: Contact\n\n---\n\n# Contact\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/contact.schema.json](pathname:///schemas/next/context/contact.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/contact.schema.json))\n\n## Type\n\n`fdc3.contact`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>email</code></summary>\n\n**type**: `string`\n\nThe email address for the contact\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nFactSet Permanent Identifier representing the contact\n\n</details>\n\nIdentifiers that relate to the Contact represented by this context\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the contact\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.contact\",\n  \"name\": \"Jane Doe\",\n  \"id\": {\n    \"email\": \"jane.doe@mail.com\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/ContactList.md",
    "content": "---\ntitle: ContactList\nsidebar_label: ContactList\n\n---\n\n# ContactList\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nThe contact list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/contactList.schema.json](pathname:///schemas/next/context/contactList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/contactList.schema.json))\n\n## Type\n\n`fdc3.contactList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the contact list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the contact list\n\n</details>\n\n<details>\n  <summary><code>contacts</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Contact](Contact)\n\n</details>\n\nAn array of contact contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.contactList\",\n  \"contacts\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    },\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"John Doe\",\n      \"id\": {\n        \"email\": \"john.doe@mail.com\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Context.md",
    "content": "---\nid: Context\nsidebar_label: Context\ntitle: Context\nhide_title: true\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not\nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/context.schema.json](pathname:///schemas/next/context/context.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema.\nThe FDC3 [API](../../api/spec) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/spec) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`.\nFor non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\nIdentifier values SHOULD always be of type string.\n\n## See Also\n\nFDC3 Specifications\n\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/docs/context/ref/Country.md",
    "content": "---\ntitle: Country\nsidebar_label: Country\n\n---\n\n# Country\n\nA country entity.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement is for at least one standardized identifier to be provided\n\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/country.schema.json](pathname:///schemas/next/context/country.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/country.schema.json))\n\n## Type\n\n`fdc3.country`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA2</code></summary>\n\n**type**: `string`\n\nTwo-letter ISO country code\n\n</details>\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA3</code></summary>\n\n**type**: `string`\n\nThree-letter ISO country code\n\n</details>\n\n<details>\n  <summary><code>ISOALPHA2</code></summary>\n\n**type**: `string`\n\nTwo-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\n\n</details>\n\n<details>\n  <summary><code>ISOALPHA3</code></summary>\n\n**type**: `string`\n\nThree-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\n\n</details>\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the country\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.country\",\n  \"name\": \"Sweden\",\n  \"id\": {\n    \"COUNTRY_ISOALPHA2\": \"SE\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Currency.md",
    "content": "---\ntitle: Currency\nsidebar_label: Currency\n\n---\n\n# Currency\n\nA context representing an individual Currency.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/currency.schema.json](pathname:///schemas/next/context/currency.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/currency.schema.json))\n\n## Type\n\n`fdc3.currency`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nThe name of the currency for display purposes\n\n</details>\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>CURRENCY_ISOCODE</code></summary>\n\n**type**: `string`\n\nThe `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\n\n</details>\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.currency\",\n  \"name\": \"US Dollar\",\n  \"id\": {\n    \"CURRENCY_ISOCODE\": \"USD\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/DocumentedContext.md",
    "content": "---\ntitle: DocumentedContext\nsidebar_label: DocumentedContext\n\n---\n\n# DocumentedContext\n\n## Schema\n\n[https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json](https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json)\n\n## Type\n\n`undefined`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some derived types may require the name object as mandatory, depending on use case.\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier. Identifier values SHOULD always be of type string.\n\n</details>\n\n"
  },
  {
    "path": "website/docs/context/ref/Email.md",
    "content": "---\ntitle: Email\nsidebar_label: Email\n\n---\n\n# Email\n\nA collection of information to be used to initiate an email with a Contact or ContactList.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/email.schema.json](pathname:///schemas/next/context/email.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/email.schema.json))\n\n## Type\n\n`fdc3.email`\n\n## Properties\n\n<details>\n  <summary><code>recipients</code> <strong>(required)</strong></summary>\n\n**One of:**\n\n- **type**: [Contact](Contact)\n- **type**: [ContactList](ContactList)\n\nOne or more recipients for the email.\n\n</details>\n\n<details>\n  <summary><code>subject</code></summary>\n\n**type**: `string`\n\nSubject line for the email.\n\n</details>\n\n<details>\n  <summary><code>textBody</code></summary>\n\n**type**: `string`\n\nBody content for the email.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/FileAttachment.md",
    "content": "---\ntitle: File Attachment\nsidebar_label: File Attachment\n\n---\n\n# File Attachment\n\nA File attachment encoded in the form of a data URI. Can be added to a Message.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/fileAttachment.schema.json](pathname:///schemas/next/context/fileAttachment.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/fileAttachment.schema.json))\n\n## Type\n\n`fdc3.fileAttachment`\n\n## Properties\n\n<details>\n  <summary><code>data</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>name</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe name of the attached file\n\n</details>\n\n<details>\n  <summary><code>dataUri</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA data URI encoding the content of the file to be attached\n\n</details>\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.fileAttachment\",\n  \"data\": {\n    \"name\": \"myImage.png\",\n    \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Instrument.md",
    "content": "---\ntitle: Instrument\nsidebar_label: Instrument\n\n---\n\n# Instrument\n\nA financial instrument from any asset class.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/instrument.schema.json](pathname:///schemas/next/context/instrument.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/instrument.schema.json))\n\n## Type\n\n`fdc3.instrument`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>BBG</code></summary>\n\n**type**: `string`\n\nhttps://www.bloomberg.com/\n\n</details>\n\n<details>\n  <summary><code>CUSIP</code></summary>\n\n**type**: `string`\n\nhttps://www.cusip.com/\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nhttps://www.factset.com/\n\n</details>\n\n<details>\n  <summary><code>FIGI</code></summary>\n\n**type**: `string`\n\nhttps://www.openfigi.com/\n\n</details>\n\n<details>\n  <summary><code>ISIN</code></summary>\n\n**type**: `string`\n\nhttps://www.isin.org/\n\n</details>\n\n<details>\n  <summary><code>PERMID</code></summary>\n\n**type**: `string`\n\nhttps://permid.org/\n\n</details>\n\n<details>\n  <summary><code>RIC</code></summary>\n\n**type**: `string`\n\nhttps://www.refinitiv.com/\n\n</details>\n\n<details>\n  <summary><code>SEDOL</code></summary>\n\n**type**: `string`\n\nhttps://www.lseg.com/sedol\n\n</details>\n\n<details>\n  <summary><code>ticker</code></summary>\n\n**type**: `string`\n\nUnstandardized stock tickers\n\n</details>\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match. Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified. In general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\nIt is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement is for at least one instrument identifier to be provided.\n\nTry to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define a property that makes it clear what the value represents. Doing so will make interpretation easier for the developers of target applications.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the instrument\n\n</details>\n\n<details>\n  <summary><code>market</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>MIC</code></summary>\n\n**type**: `string`\n\nhttps://en.wikipedia.org/wiki/Market_Identifier_Code\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nHuman readable market name\n\n</details>\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA2</code></summary>\n\n**type**: `string`\n\nhttps://www.iso.org/iso-3166-country-codes.html\n\n</details>\n\n<details>\n  <summary><code>BBG</code></summary>\n\n**type**: `string`\n\nhttps://www.bloomberg.com/\n\n</details>\n\nThe `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.instrument\",\n  \"name\": \"Microsoft\",\n  \"id\": {\n    \"ticker\": \"MSFT\",\n    \"RIC\": \"MSFT.OQ\",\n    \"ISIN\": \"US5949181045\"\n  },\n  \"market\": {\n    \"MIC\": \"XNAS\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/InstrumentList.md",
    "content": "---\ntitle: InstrumentList\nsidebar_label: InstrumentList\n\n---\n\n# InstrumentList\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist). However, when holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type.\n\nThe instrument list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/instrumentList.schema.json](pathname:///schemas/next/context/instrumentList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/instrumentList.schema.json))\n\n## Type\n\n`fdc3.instrumentList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the instrument list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the instrument list\n\n</details>\n\n<details>\n  <summary><code>instruments</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Instrument](Instrument)\n\n</details>\n\nAn array of instrument contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.instrumentList\",\n  \"instruments\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"AAPL\"\n      },\n      \"market\": {\n        \"MIC\": \"XNAS\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ISIN\": \"US5949181045\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Interaction.md",
    "content": "---\ntitle: Interaction\nsidebar_label: Interaction\n\n---\n\n# Interaction\n\nAn `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/interaction.schema.json](pathname:///schemas/next/context/interaction.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/interaction.schema.json))\n\n## Type\n\n`fdc3.interaction`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>URI</code></summary>\n\n**type**: `string`\n\nCan be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\n\n</details>\n\n<details>\n  <summary><code>SALESFORCE</code></summary>\n\n**type**: `string`\n\nInteractions ID in Salesforce\n\n</details>\n\n<details>\n  <summary><code>SINGLETRACK</code></summary>\n\n**type**: `string`\n\nInteraction ID in SingleTrack\n\n</details>\n\nCan be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted. An interaction ID does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\n\n</details>\n\n<details>\n  <summary><code>participants</code> <strong>(required)</strong></summary>\n\n**type**: [ContactList](ContactList)\n\nA list of contacts involved in the interaction\n\n</details>\n\n<details>\n  <summary><code>timeRange</code> <strong>(required)</strong></summary>\n\n**type**: [TimeRange](TimeRange)\n\nThe time range over which the interaction occurred\n\n</details>\n\n<details>\n  <summary><code>interactionType</code> <strong>(required)</strong></summary>\n\n**Any of:**\n\n- **type**: `string` with values:\n- `Instant Message`,\n- `Email`,\n- `Call`,\n- `Meeting`\n- **type**: `string`\n\n`interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\n\n</details>\n\n<details>\n  <summary><code>description</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA human-readable description of the interaction\n\n</details>\n\n<details>\n  <summary><code>initiator</code></summary>\n\n**type**: [Contact](Contact)\n\nThe contact that initiated the interaction\n\n</details>\n\n<details>\n  <summary><code>origin</code></summary>\n\n**type**: `string`\n\nUsed to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.interaction\",\n  \"participants\": {\n    \"type\": \"fdc3.contactList\",\n    \"contacts\": [\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"John Doe\",\n        \"id\": {\n          \"email\": \"john.doe@mail.com\"\n        }\n      }\n    ]\n  },\n  \"interactionType\": \"Instant Message\",\n  \"timeRange\": {\n    \"type\": \"fdc3.timeRange\",\n    \"startTime\": \"2022-02-10T15:12:00Z\"\n  },\n  \"description\": \"Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum\",\n  \"initiator\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@mail.com\"\n    }\n  },\n  \"origin\": \"Outlook\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Message.md",
    "content": "---\ntitle: Message\nsidebar_label: Message\n\n---\n\n# Message\n\nA chat message to be sent through an instant messaging application. Can contain one or several text bodies (organized by mime-type, plaintext or markdown), as well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/message.schema.json](pathname:///schemas/next/context/message.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/message.schema.json))\n\n## Type\n\n`fdc3.message`\n\n## Properties\n\n<details>\n  <summary><code>text</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>text/plain</code></summary>\n\n**type**: `string`\n\nPlain text encoded content.\n\n</details>\n\n<details>\n  <summary><code>text/markdown</code></summary>\n\n**type**: `string`\n\nMarkdown encoded content\n\n</details>\n\nA map of string mime-type to string content\n\n</details>\n\n<details>\n  <summary><code>entities</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**One of:**\n\n- **type**: [Action](Action)\n- **type**: [File Attachment](FileAttachment)\n\n</details>\n\nA map of string IDs to entities that should be attached to the message, such as an action to perform, a file attachment, or other FDC3 context object.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.message\",\n  \"text\": {\n    \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate\"\n  },\n  \"entities\": {\n    \"picture1\": {\n      \"type\": \"fdc3.fileAttachment\",\n      \"data\": {\n        \"name\": \"myImage.png\",\n        \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n      }\n    },\n    \"eurusd_action\": {\n      \"type\": \"fdc3.action\",\n      \"title\": \"Click to view Chart\",\n      \"intent\": \"ViewChart\",\n      \"context\": {\n        \"type\": \"fdc3.chart\",\n        \"instruments\": [\n          {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"EURUSD\"\n            }\n          }\n        ],\n        \"range\": {\n          \"type\": \"fdc3.dateRange\",\n          \"starttime\": \"2020-09-01T08:00:00.000Z\",\n          \"endtime\": \"2020-10-31T08:00:00.000Z\"\n        },\n        \"style\": \"candle\"\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Nothing.md",
    "content": "---\ntitle: Nothing\nsidebar_label: Nothing\n\n---\n\n# Nothing\n\nA type that explicitly represents a lack of context.\n\nNotes:\n\n- Intended to be used in situations where no context is desired.\n- For example:\n  - Raising an intent without context (e.g. opening a blank order form, or chat interface without a contact selected).\n  - Resetting context on a channel (e.g. when context is used to set a filter in other applications a null context might release the filter).\n- An explicit representation of a Null or empty context allows apps to declare support for a lack of context, for example in their intent metadata in an app directory.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/nothing.schema.json](pathname:///schemas/next/context/nothing.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/nothing.schema.json))\n\n## Type\n\n`fdc3.nothing`\n\n## Properties\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.nothing\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Order.md",
    "content": "---\ntitle: Order\nsidebar_label: Order\n\n---\n\n# Order\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing an order. To be used with OMS and EMS systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human readable `name` field to be used to summarize the order and an optional `details` field that may be used to provide additional detail about the order, including a context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as a unspecified Context type, but both `details` and `details.product` are expected to be standardized in future.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/order.schema.json](pathname:///schemas/next/context/order.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/order.schema.json))\n\n## Type\n\n`fdc3.order`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the order.\n\n</details>\n\n<details>\n  <summary><code>details</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>product</code></summary>\n\n**type**: [Product](Product)\n\n</details>\n\nOptional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context\n\n</details>\n\n<details>\n  <summary><code>notes</code></summary>\n\n**type**: `string`\n\nAdditional notes or comments about the order.\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.order\",\n  \"name\": \"...\",\n  \"notes\": \"...\",\n  \"id\": {\n    \"myOMS\": \"12345\"\n  },\n  \"details\": {\n    \"product\": {\n      \"type\": \"fdc3.product\",\n      \"id\": {\n        \"productId\": \"ABC123\"\n      },\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"MSFT\"\n        }\n      }\n    }\n  }\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.order\",\n  \"id\": {\n    \"myOMS\": \"ABC123\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/OrderList.md",
    "content": "---\ntitle: OrderList\nsidebar_label: OrderList\n\n---\n\n# OrderList\n\n[@experimental](/docs/fdc3-compliance#experimental-features) A list of orders. Use this type for use cases that require not just a single order, but multiple.\n\nThe OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/orderList.schema.json](pathname:///schemas/next/context/orderList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/orderList.schema.json))\n\n## Type\n\n`fdc3.orderList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the order list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the order list\n\n</details>\n\n<details>\n  <summary><code>orders</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Order](Order)\n\n</details>\n\nAn array of order contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.orderList\",\n  \"orders\": [\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"ABC123\"\n      }\n    },\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"DEF456\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Organization.md",
    "content": "---\ntitle: Organization\nsidebar_label: Organization\n\n---\n\n# Organization\n\nAn entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\n\nIt is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement is for at least one specified identifier to be provided.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/organization.schema.json](pathname:///schemas/next/context/organization.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/organization.schema.json))\n\n## Type\n\n`fdc3.organization`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>LEI</code></summary>\n\n**type**: `string`\n\nThe Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO 17442 standard developed by the International Organization for Standardization (ISO). It connects to key reference information that enables clear and unique identification of legal entities participating in financial transactions.\n\n</details>\n\n<details>\n  <summary><code>PERMID</code></summary>\n\n**type**: `string`\n\nRefinitiv Permanent Identifiers, or PermID for the organization\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nFactSet Permanent Identifier representing the organization\n\n</details>\n\nIdentifiers for the organization, at least one must be provided.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name of the organization\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.organization\",\n  \"name\": \"Cargill, Incorporated\",\n  \"id\": {\n    \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n    \"FDS_ID\": \"00161G-E\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Portfolio.md",
    "content": "---\ntitle: Portfolio\nsidebar_label: Portfolio\n\n---\n\n# Portfolio\n\nA financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe Portfolio type consists of an array of [Position](Position) types, each of which refers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nThe portfolio schema does not explicitly include identifiers in the `id` section, as there bis not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/portfolio.schema.json](pathname:///schemas/next/context/portfolio.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/portfolio.schema.json))\n\n## Type\n\n`fdc3.portfolio`\n\n## Properties\n\n<details>\n  <summary><code>positions</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Position](Position)\n\n</details>\n\nThe List of Positions which make up the Portfolio\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the portfolio in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the portfolio\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.portfolio\",\n  \"positions\": [\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"AAPL\"\n        }\n      },\n      \"holding\": 2000000\n    },\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"MSFT\"\n        }\n      },\n      \"holding\": 1500000\n    },\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"IBM\"\n        }\n      },\n      \"holding\": 3000000\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Position.md",
    "content": "---\ntitle: Position\nsidebar_label: Position\n\n---\n\n# Position\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good example of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents multiple holdings in a combination of instruments.\n\nThe position schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/position.schema.json](pathname:///schemas/next/context/position.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/position.schema.json))\n\n## Type\n\n`fdc3.position`\n\n## Properties\n\n<details>\n  <summary><code>instrument</code> <strong>(required)</strong></summary>\n\n**type**: [Instrument](Instrument)\n\n\n\n</details>\n\n<details>\n  <summary><code>holding</code> <strong>(required)</strong></summary>\n\n**type**: `number`\n\nThe amount of the holding, e.g. a number of shares\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the position in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the position\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.position\",\n  \"instrument\": {\n    \"type\": \"fdc3.instrument\",\n    \"id\": {\n      \"ticker\": \"AAPL\"\n    }\n  },\n  \"holding\": 2000000\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Product.md",
    "content": "---\ntitle: Product\nsidebar_label: Product\n\n---\n\n# Product\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing a tradable product. To be used with OMS and EMS systems.\n\nThis type is currently only loosely defined as an extensible context object, with an optional instrument field.\n\nThe Product schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/product.schema.json](pathname:///schemas/next/context/product.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/product.schema.json))\n\n## Type\n\n`fdc3.product`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nA human-readable summary of the product.\n\n</details>\n\n<details>\n  <summary><code>instrument</code></summary>\n\n**type**: [Instrument](Instrument)\n\nA financial instrument that relates to the definition of this product\n\n</details>\n\n<details>\n  <summary><code>notes</code></summary>\n\n**type**: `string`\n\nAdditional notes or comments about the product.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.product\",\n  \"notes\": \"...\",\n  \"id\": {\n    \"productId\": \"ABC123\"\n  },\n  \"instrument\": {\n    \"type\": \"fdc3.instrument\",\n    \"id\": {\n      \"ticker\": \"MSFT\"\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/TimeRange.md",
    "content": "---\ntitle: TimeRange\nsidebar_label: TimeRange\n\n---\n\n# TimeRange\n\nA context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\n\n- A pricing chart\n- A trade blotter\n- A record of client contact/activity in a CRM\n\nExample use cases:\n\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\n\nNotes:\n\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n  - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or `\"2022-05-12T16:18:03+01:00\"`\n  - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/timeRange.schema.json](pathname:///schemas/next/context/timeRange.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/timeRange.schema.json))\n\n## Type\n\n`fdc3.timeRange`\n\n## Properties\n\n<details>\n  <summary><code>startTime</code></summary>\n\n**type**: `string`\n\nThe start time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n\n</details>\n\n<details>\n  <summary><code>endTime</code></summary>\n\n**type**: `string`\n\nThe end time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"startTime\": \"2022-03-30T15:44:44Z\",\n  \"endTime\": \"2022-04-30T23:59:59Z\"\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"startTime\": \"2022-03-30T15:44:44+00:00\"\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"endTime\": \"2022-03-30T16:44:44.123Z\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Trade.md",
    "content": "---\ntitle: Trade\nsidebar_label: Trade\n\n---\n\n# Trade\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing a trade. To be used with execution systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as a unspecified Context type, but `product` is expected to be standardized in future.\n\n The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/trade.schema.json](pathname:///schemas/next/context/trade.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/trade.schema.json))\n\n## Type\n\n`fdc3.trade`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nA human-readable summary of the trade.\n\n</details>\n\n<details>\n  <summary><code>product</code> <strong>(required)</strong></summary>\n\n**type**: [Product](Product)\n\nA product that is the subject of the trade.\n\n</details>\n\n<details>\n  <summary><code>notes</code></summary>\n\n**type**: `string`\n\nAdditional notes or comments about the trade.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.trade\",\n  \"name\": \"...\",\n  \"notes\": \"...\",\n  \"id\": {\n    \"myEMS\": \"12345\"\n  },\n  \"product\": {\n    \"type\": \"fdc3.product\",\n    \"id\": {\n      \"productId\": \"ABC123\"\n    },\n    \"instrument\": {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"MSFT\"\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/TradeList.md",
    "content": "---\ntitle: TradeList\nsidebar_label: TradeList\n\n---\n\n# TradeList\n\n[@experimental](/docs/fdc3-compliance#experimental-features) A list of trades. Use this type for use cases that require not just a single trade, but multiple.\n\nThe TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/tradeList.schema.json](pathname:///schemas/next/context/tradeList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/tradeList.schema.json))\n\n## Type\n\n`fdc3.tradeList`\n\n## Properties\n\n<details>\n  <summary><code>trades</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Trade](Trade)\n\n</details>\n\nAn array of trade contexts that forms the list.\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the trade list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the trade list\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.tradeList\",\n  \"trades\": [\n    {\n      \"type\": \"fdc3.trade\",\n      \"name\": \"...\",\n      \"id\": {\n        \"myEMS\": \"12345\"\n      },\n      \"product\": {\n        \"type\": \"fdc3.product\",\n        \"id\": {\n          \"productId\": \"ABC123\"\n        },\n        \"instrument\": {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"MSFT\"\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"fdc3.trade\",\n      \"id\": {\n        \"myEMS\": \"67890\"\n      },\n      \"product\": {\n        \"type\": \"fdc3.product\",\n        \"id\": {\n          \"productId\": \"DEF456\"\n        },\n        \"instrument\": {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"TSLA\"\n          }\n        }\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/TransactionResult.md",
    "content": "---\ntitle: TransactionResult\nsidebar_label: TransactionResult\n\n---\n\n# TransactionResult\n\nA context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an `IntentResult` by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/transactionresult.schema.json](pathname:///schemas/next/context/transactionresult.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/transactionresult.schema.json))\n\n## Type\n\n`fdc3.transactionResult`\n\n## Properties\n\n<details>\n  <summary><code>status</code> <strong>(required)</strong></summary>\n\n**type**: `string` with values:\n- `Created`,\n- `Deleted`,\n- `Updated`,\n- `Failed`\n\nThe status of the transaction being reported.\n\n</details>\n\n<details>\n  <summary><code>context</code></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\nA context object returned by the transaction, possibly with updated data.\n\n</details>\n\n<details>\n  <summary><code>message</code></summary>\n\n**type**: `string`\n\nA human readable message describing the outcome of the transaction.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.transactionResult\",\n  \"status\": \"Updated\",\n  \"context\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@mail.com\"\n    }\n  },\n  \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/ref/Valuation.md",
    "content": "---\ntitle: Valuation\nsidebar_label: Valuation\n\n---\n\n# Valuation\n\nA context type representing the price and value of a holding.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/next/context/valuation.schema.json](pathname:///schemas/next/context/valuation.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/valuation.schema.json))\n\n## Type\n\n`fdc3.valuation`\n\n## Properties\n\n<details>\n  <summary><code>value</code> <strong>(required)</strong></summary>\n\n**type**: `number`\n\nThe value of the holding, expresses in the nominated currency.\n\n</details>\n\n<details>\n  <summary><code>price</code></summary>\n\n**type**: `number`\n\nThe price per unit the the valuation is based on.\n\n</details>\n\n<details>\n  <summary><code>CURRENCY_ISOCODE</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe valuation currency, which should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\n\n</details>\n\n<details>\n  <summary><code>valuationTime</code></summary>\n\n**type**: `string`\n\nThe time at which the valuation was performed, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n</details>\n\n<details>\n  <summary><code>expiryTime</code></summary>\n\n**type**: `string`\n\nThe time at which this valuation expires, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.valuation\",\n  \"value\": 500,\n  \"price\": 5,\n  \"CURRENCY_ISOCODE\": \"USD\",\n  \"expiryTime\": \"2022-05-13T16:16:24+01:00\"\n}\n```\n\n"
  },
  {
    "path": "website/docs/context/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Context Data (next)\n---\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems. FDC3 Context Data defines a standard for passing common identifiers and data, encoded in JSON, between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard JSON payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [intents](../intents/spec) and when broadcasting context to other applications.\n\nThere are two main use cases for exchanging context data:\n\n- **Transmitting reference data between applications.**\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n- **Transferring information between applications.**\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there aren't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n### Context Schemas\n\nFDC3 Context data is primarily encoded in JSON, but may also be encoded in language specific formats for use with FDC3 API implementations in those languages, although it is advisable to ensure that they can be converted to and from JSON.\n\nEach Standardized context type defined by the FDC3 Standard has an associated [JSON Schema](https://json-schema.org/) definition that should be considered the 'source of truth' for the context definition, although examples in documentation may also be given in TypeScript or JavaScript. The TypeScript definitions distributed in the FDC3 NPM module are generated from the JSON Schema files using [quicktype](https://quicktype.io/). Both documentation for fields defined (in the form of a `title` and `description` entry for each field defined) and examples SHOULD be included in JSON Schema definitions for Context types to ensure that the schema file can serve as a single source of truth, and that code generated from the schema files can also include that documentation.\n\n## The Context Interface\n\nThe Context interface defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\n\nThe Context interface can be summarized as:\n\n- Having a unique _type_ identifier, used for routing.\n- Optionally providing a name.\n- Optionally providing a map of equivalent identifiers.\n- Any other properties or metadata.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has. The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\n\nHence, the Context interface can be represented in TypeScript as:\n\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n\nor in JSON Schema as:\n\n```json\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/next/context/context.schema.json\",\n    \"type\": \"object\",\n    \"title\": \"Context\",\n    \"description\": \"The `fdc3.context` type defines the basic contract for all data exchanged by FDC3 operations.\",\n    \"properties\": {\n        \"type\": {\n            \"type\": \"string\"\n        },\n        \"name\": {\n            \"type\": \"string\"\n        },\n        \"id\": {\n            \"type\": \"object\",\n            \"unevaluatedProperties\": {\n                \"type\": \"string\"\n            }\n        }\n    },\n    \"additionalProperties\": true,\n    \"required\": [\n        \"type\"\n    ]\n}\n```\n\n:::note\n\nThis is a simplified version of the schema for illustrative purposes, the fully documented Context schema, which is composed with other FDC3 Standard context schemas, can be found at: [https://fdc3.finos.org/schemas/next/context/context.schema.json](pathname:///schemas/next/context/context.schema.json).\n\n:::\n\n### `type`\n\nThe type property is the only _required_ part of the FDC3 context data schema. The FDC3 [API](../api/spec) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../intents/spec) also register the context data types they support in an FDC3 [App Directory](../app-directory/overview), used for intent discovery and routing.\n\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`.\nFor non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\n#### Namespacing\n\nAll well-known types at FDC3 level are prefixed with `fdc3`. For private type definitions, or type definitions issued by other organizations, different namespaces MUST be used, e.g. `blackrock.fund`, etc.\n\n### `name`\n\nContext data objects may include an optional name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id`\n\nContext data objects may include a set of equivalent key-value pairs in the `id` property that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types choose to require at least one identifier.\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nIdentifier values SHOULD always be of type string.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\n\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n### Avoid union types / composition of primitive types\n\nBoth Typescript and JSON Schema allow for a type of polymorphism in types and interfaces that is hard to represent in other languages: allowing the type of a variable to be a ['union'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of other, unrelated types. E.g.: in TypeScript\n\n```ts\ntype Example = SomeOtherType | YetAnotherType;\n```\n\nSimilar constructs are allowed in JSON Schema by [combining or composing schemas](https://json-schema.org/understanding-json-schema/reference/combining) using the `anyOf` or `oneOf` keywords to specify that a value can take the form defined in one-or-more or one-of-several sub-schemas.\n\n```json\n\"recipients\": {\n    \"title\": \"Email Recipients\",\n    \"description\": \"One or more recipients for the email.\",\n    \"oneOf\": [\n        {\n            \"$ref\": \"contact.schema.json#\"\n        },\n        {\n            \"$ref\": \"contactList.schema.json#\"\n        }\n    ]\n}\n```\n\nHowever, other languages can be less flexible. In most languages, polymorphism of object types is possible via the implementation and/or extension of an interface (for example all context types are derived from the [Context](ref/Context) schema, which can be modelled as an interface). However, this approach is not possible if one of the types in the union is a primitive, meaning it's not a class and can't be modified to implement an interface, e.g.:\n\n```ts\ntype Example2 = SomeOtherType | number;\n```\n\nHence, to ensure that FDC3 context objects are implementable in other languages context schemas MUST NOT use `anyOf`/`oneOf` compositions of primitive types in JSON schema (and, hence, unions of primitive types in TypeScript) and SHOULD avoid compositions of Object types unless a concept that can be defined as an interface (such as [Context](ref/Context)) is available.\n\n### Other Field Type Conventions\n\nThis Standard defines a number of conventions for the fields of context types that all context objects SHOULD adhere to in order to reduce or prevent competing conventions from being established in both standardized types and proprietary types created by app developers.\n\n#### Times\n\nFields representing a point in time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included, e.g.:\n\n- Time in UTC: `\"2022-03-30T15:44:44Z\"`\n- Also time in UTC: `\"2022-03-30T15:44:44+00:00\"`\n- Same time in EDT: `\"2022-03-30T11:44:44-04:00\"`\n\nTimes MAY be expressed with millisecond precision, e.g.:\n\n- `\"2022-03-30T11:44:44.123-04:00\"`\n- `\"2022-03-30T11:44:44.123Z\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30T11:44:44.123-04:00\")\n```\n\n#### Dates\n\nFields representing a point in time SHOULD be string encoded using the `YYYY-MM-DD` date format from [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n\nE.g. `\"2022-03-30\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30\")\n```\n\n#### Country codes\n\nFields representing a country SHOULD be string encoded using the Alpha-2-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) and field name `COUNTRY_ISOALPHA2`. The Alpha-3-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) MAY be used in addition to the Alpha-2-code with the field name `COUNTRY_ISOALPHA3`.\n\nE.g. `\"COUNTRY_ISOALPHA2\": \"GB\"`\n\n#### Currency codes\n\nFields representing a currency SHOULD be string encoded using the Alphabetic code from [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) with the field name `CURRENCY_ISOCODE`.\n\nE.g. `\"CURRENCY_ISOCODE\": \"GBP\"`\n\n:::note\nISO 4217 only includes major currency codes, conversions to minor currencies is the responsibility of the consuming system (where required).\n:::\n\n## Context Data Standard Compliance\n\nAn FDC3 Standard compliant application that supports the use of context data **MUST**:\n\n- Ensure that any FDC3-defined standard context types used meet the interface defined for that type of context data.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers.\n- Where App or Private channels are supported, use the [`Channel.addContextListener`](../api/ref/Channel#addcontextlistener) API call to set up appropriate handlers.\n\nAn FDC3 Standard compliant application that supports the use of context data **SHOULD**:\n\n- Prefer FDC3-defined standard context types over proprietary contexts, where a suitable FDC3-defined standard context type is available.\n- Ensure that any proprietary context data types defined follow any the recommended [namespacing](#namespacing) and [field type conventions](spec#other-field-type-conventions) in the specification.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n\nAn FDC3 Standard compliant application that supports the use of context data **MAY**:\n\n- Define proprietary context data types to support use cases not currently supported via FDC3-defined standard context types.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Context Types\n\nThe following are standard FDC3 context types:\n\n- [`fdc3.action`](ref/Action) ([schema](pathname:///schemas/next/context/action.schema.json))\n- [`fdc3.chart`](ref/Chart) ([schema](pathname:///schemas/next/context/chart.schema.json))\n- [`fdc3.chat.initSettings`](ref/ChatInitSettings) ([schema](pathname:///schemas/next/context/chatInitSettings.schema.json))\n- [`fdc3.chat.message`](ref/ChatMessage) ([schema](pathname:///schemas/next/context/chatMessage.schema.json))\n- [`fdc3.chat.room`](ref/ChatRoom) ([schema](pathname:///schemas/next/context/chatRoom.schema.json))\n- [`fdc3.chat.searchCriteria`](ref/ChatSearchCriteria) ([schema](pathname:///schemas/next/context/chatSearchCriteria.schema.json))\n- [`fdc3.contact`](ref/Contact) ([schema](pathname:///schemas/next/context/contact.schema.json))\n- [`fdc3.contactList`](ref/ContactList) ([schema](pathname:///schemas/next/context/contactList.schema.json))\n- [`fdc3.country`](ref/Country) ([schema](pathname:///schemas/next/context/country.schema.json))\n- [`fdc3.currency`](ref/Currency) ([schema](pathname:///schemas/next/context/currency.schema.json))\n- [`fdc3.email`](ref/Email) ([schema](pathname:///schemas/next/context/email.schema.json))\n- [`fdc3.instrument`](ref/Instrument) ([schema](pathname:///schemas/next/context/instrument.schema.json))\n- [`fdc3.instrumentList`](ref/InstrumentList) ([schema](pathname:///schemas/next/context/instrumentList.schema.json))\n- [`fdc3.interaction`](ref/Interaction) ([schema](pathname:///schemas/next/context/interaction.schema.json))\n- [`fdc3.message`](ref/Message) ([schema](pathname:///schemas/next/context/message.schema.json))\n- [`fdc3.organization`](ref/Organization) ([schema](pathname:///schemas/next/context/organization.schema.json))\n- [`fdc3.portfolio`](ref/Portfolio) ([schema](pathname:///schemas/next/context/portfolio.schema.json))\n- [`fdc3.position`](ref/Position) ([schema](pathname:///schemas/next/context/position.schema.json))\n- [`fdc3.nothing`](ref/Nothing) ([schema](pathname:///schemas/next/context/nothing.schema.json))\n- [`fdc3.timeRange`](ref/TimeRange) ([schema](pathname:///schemas/next/context/timeRange.schema.json))\n- [`fdc3.transactionResult`](ref/TransactionResult) ([schema](pathname:///schemas/next/context/transactionresult.schema.json))\n- [`fdc3.valuation`](ref/Valuation) ([schema](pathname:///schemas/next/context/valuation.schema.json))\n\nThe following are [`@experimental`](/docs/fdc3-compliance#experimental-features) types, which are in the process of being defined:\n\n- [`fdc3.order`](ref/Order) ([schema](pathname:///schemas/next/context/order.schema.json))\n- [`fdc3.orderList`](ref/OrderList) ([schema](pathname:///schemas/next/context/orderList.schema.json))\n- [`fdc3.product`](ref/Product) ([schema](pathname:///schemas/next/context/product.schema.json))\n- [`fdc3.trade`](ref/Trade) ([schema](pathname:///schemas/next/context/trade.schema.json))\n- [`fdc3.tradeList`](ref/TradeList) ([schema](pathname:///schemas/next/context/tradeList.schema.json))\n\n### Examples\n\nThe below examples show how the base context data interface can be used to define specific context data objects.\n\n#### Contact\n\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### Email\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n#### Instrument\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### TypeScript definition\n\nThe `Instrument` type is derived from the `Context` type (note that the name becomes a required field, the type is fixed and optional `id` subfields are defined):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n}\n```\n"
  },
  {
    "path": "website/docs/fdc3-charter.md",
    "content": "---\nid: fdc3-charter\ntitle: FDC3 Charter\n---\n\n## Scope\n\nThe FDC3 Standard specifies protocols and taxonomies to enable applications in financial services workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements between app developers.\n\nFinancial applications include any type of application used in common financial workflows, including:\n\n- Containerized Web applications - Interoperability platforms extending Chromium (e.g. Electron, OpenFin, interop.io's io.Connect)\n- PWAs & Web applications running in a commercial browser\n- Traditional native applications implemented in C++, .NET, Java, Python, etc.\n- Hybrid web/native applications - stand alone native apps embedding a WebView (e.g. Electron, CEF, WebView2, NW.js etc.)\n- Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, Slack, etc.\n\nThis standards group is focused specifically on establishing and promoting standards for the interoperability of front-end applications, hence, its activities are focused on:\n\n- The discovery, configuration, identity and use of financial services applications (e.g. the FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview)),\n- APIs for communication and interaction between applications (e.g. the [Desktop Agent API](https://fdc3.finos.org/docs/api/spec) and [Agent Bridging API](https://fdc3.finos.org/docs/agent-bridging/spec)),\n- Message formats used for communication (e.g. [Context Data](https://fdc3.finos.org/docs/context/spec))\n- Names for requested functionality and workflow steps (e.g. [Intents](https://fdc3.finos.org/docs/intents/spec))\n- Creating and promoting tests for conformance to these standards (e.g. the FDC3 Conformance Framework) and training & certification programs that relate to them (e.g. [Introduction to FDC3](https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/))\n\nThe group's activities do not include:\n\n- Interoperability or communication between back-end platforms.\n- Defining financial objects - where existing standards are well established and can be reused.\n\n## Licensing\n\n- Version 1.0 of the FDC3 specification is licensed under the [FDC3 1.0 Final Specification License](https://github.com/finos/FDC3/blob/17892008c26a73ff1fd9f6e40ceb8c8bfd58c610/PATENTS-FDC3-1.0.md).\n\n- Versions 1.1 - 2.1 of the FDC3 specification are subject to the [FINOS IP Policy](https://github.com/finos/community/blob/fdd059c93b6ceefadd8cf60c4bef995366695337/website/static/governance-docs/IP-Policy.pdf), which authorizes implementation of FDC3 specifications without charge, on a RAND basis, subject to the terms of the policy. For details of the IP commitments made by contributors to FDC3, please refer to the policy.\n\n- Versions of the FDC3 specification following 2.1 and subsequent draft specifications are licensed under the [Community Specification License 1.0](https://github.com/finos/FDC3/blob/4ce90d45ca8e0c4f8f2c5bd73f51304278783d87/LICENSE.md)\n\n- All code in the FDC3 specification (including JSON Schema) are licensed under [Apache 2.0](https://github.com/finos/FDC3/blob/main/LICENSE)\n\n### Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/docs/fdc3-compliance.md",
    "content": "---\nid: fdc3-compliance\ntitle: Compliance\n---\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>    Imperatives of the type defined in this memo must be used with care\n>    and sparingly.  In particular, they MUST only be used where it is\n>    actually required for interoperation or to limit behavior which has\n>    potential for causing harm (e.g., limiting retransmissions)  For\n>    example, they must not be used to try to impose a particular method\n>    on implementors where the method is not required for\n>    interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers the API, App Directory, Context Data, and Intents specifications.\n\n## Personas\n\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation(s) of the FDC3 APIs (The Desktop Agent API and Application Directory) for applications to use.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.\n\nDepending on persona, implementation compliance with FDC3 will mean different things.\n\n### Platform Provider\n\nFor platform providers FDC3 compliance requires that they meet the requirements of the APIs that they implement:\n\n- [Desktop Agent API compliance requirements](api/spec#desktop-agent-api-standard-compliance).\n- [App Directory compliance requirements](app-directory/spec#app-directory-standard-compliance).\n\n### Application Provider\n\nFor application providers FDC3 compliance requires that they interact with the FDC3 APIs as intended and meet the requirements of the Intents and Context Data Standards. Specifically:\n\n- [Intents Standard compliance requirements](intents/spec#intents-standard-compliance)\n- [Context Data Standard compliance requirements](context/spec#context-data-standard-compliance)\n\n## Versioning\n\nTypically, a Standard that has marketplace relevance is revised from time to time, to correct errors and/or to add functionality to support new use cases. Hence, there exist multiple versions of the standard. As FDC3 is a standards project, we don't follow semver, which is meant for libraries. We use the versioning scheme `<major>.<minor>`, e.g. `1.1` or `2.3`.\n\n## Deprecation Policy\n\nOver time, it is not uncommon for certain things in a standard to be marked for removal in a future version, possibly being replaced by an alternative. That is, they are deprecated. Often, they are retained in the standard because of their widespread use, but their use in new projects is discouraged.\n\nFDC3 adopts the following deprecation policy:\n\n1. A feature can be deprecated by any major or minor version. Newly deprecated features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n2. A feature shall only be removed by a major version. Newly removed features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n3. Deprecated features are clearly marked with an `@deprecated` tag and comment in both the documentation and jsDocs applied to the TypeScript sources.\n4. Where possible, changes to the behavior of an existing feature should be avoided; consider deprecating it and replacing it with something with a different name/syntax.\n5. Breaking change should only be made in a major version of the Standard.\n\n## Experimental Features\n\nOccasionally, a change to FDC3 may be proposed where the design is tentative, and because of this, we need feedback from the community to finalize its inclusion in the Standard. In such cases, a feature may be designated as _experimental_ to indicate that its design may change in future and that it is exempted from the normal versioning and deprecation polices in order to facilitate that change.  However, designating a feature as experimental is likely to reduce its uptake by the community, hence, this designation should be used sparingly.\n\nFDC3 adopts the following experimental features policy:\n\n1. A feature may be designated as experimental where feedback is needed to confirm the final design of that feature, with the goal of including it as a full part of the Standard without the experimental label.\n2. A feature should only be designated as experimental where there is a reasonable chance that breaking changes to its design may be applied, based on feedback received; non-breaking changes (refinements) may already be applied to features defined in the Standard without the experimental designation.\n3. Experimental features are clearly marked with an `@experimental` tag and comment in both the documentation and docs applied to the TypeScript sources.\n4. Unless otherwise stated, experimental features should be considered optional for compliance purposes, but recommended for implementation (i.e. the SHOULD keyword is implied).\n5. Experimental features are exempted from the normal versioning and deprecation policies that govern changes to FDC3. I.e. breaking changes may be made to experimental features between versions of the Standard without a major version release.\n6. The experimental designation may be removed from a feature in a minor version release (as this will be considered an additive change).\n\n## Conformance testing\n\nThe FDC3 Standards include a set of [definitions for conformance tests](api/conformance/Conformance-Overview) that may be used to determine if a Desktop Agent API implementation conforms to a particular Standard version, to help disambiguate complex parts of the FDC3 Standard and to enable test-driven development of a Desktop Agent implementation.\n\nThe current set of tests focus on the Desktop Agent API and the interface to it. Tests are not yet defined for the App Directory API or Bridging API Parts of the FDC3 Standard, hence, conformance to those parts of the Standard must be determined manually.\n\nThe FDC3 Conformance tests are implemented for JavaScript/TypeScript web applications by the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework). Desktop Agent implementors working with web interfaces (Desktop Agent Preload or Desktop Agent Proxy) can clone the conformance framework and run the tests locally to determine if their agent is compliant with the Standard.\n\nOnce a Desktop Agent has passed the conformance tests locally, its authors can [apply for a formal certification of compliance with the Standard from FINOS](https://github.com/finos/FDC3-conformance-framework/blob/main/instructions.md). Please note the [Terms and Conditions](https://github.com/finos/FDC3-conformance-framework/blob/main/terms-conditions/FDC3-Certified-Terms.md) of the Conformance Program.\n\nimport badge_12 from '/img/community/certified-1.2.png';\nimport badge_20 from '/img/community/certified-2.0.png';\n\n<img src={badge_12} alt=\"Certified conformant with FDC3 1.2 badge\" style={{width: 200}} />\n<img src={badge_20} alt=\"Certified conformant with FDC3 2.0 badge\" style={{width: 200}} />\n\n## Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/docs/fdc3-glossary.md",
    "content": "---\nid: fdc3-glossary\ntitle: Glossary of Terms\nsidebar_label: Glossary\n---\n\nFor the purposes of this Standard, the following definitions apply. Other terms are defined when first used, at which place they appear in bold and italic type. Terms explicitly defined in this Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined are assumed to be well-known in the financial services or software industries.\n\n- **Agent Bridge**: Shorthand for Desktop Agent Bridge.\n- **app**: Shorthand for application.\n- **app directory**: A repository of application metadata supporting discovery, for example via name or intent, and retrieval of metadata necessary to launch an application.\n- **app directory record**: Metadata relating to a single application, encoded in JSON.\n- **appD**: Shorthand for app directory.\n- **appD record**: Shorthand for app directory record.\n- **application**: Any endpoint on the desktop that is registered with/known by a Desktop Agent, launchable by a Desktop Agent, addressable by a Desktop Agent or otherwise able to interact with the Desktop Agent.\n- **application, hybrid**: Any web application running within the context of a standalone native application that embeds a web view, typically based on Chromium.\n- **application, native**: A non-web-based application; i.e., one that runs outside the context of web browser, web view or web container. A user-written program, typically implemented in a language such as C++, C#, Java, or Python, rather than JavaScript or TypeScript.\n- **application, web**: An application written in TypeScript or JavaScript, HTML and CSS, which runs within the context of a web browser or a web container.\n- **Application Provider**: A downstream consumer of FDC3 Standards that can understand and use the FDC3 API (supplied by a Platform Provider), context data, and/or intents.\n- **application-specific intent**: A custom intent defined by an application or applications, independent of the Standard.\n- **Bridge**: Shorthand for Desktop Agent Bridge.\n- **bridging**: Shorthand for the exchange of messages across a Desktop Agent Bridge for the purposes of extending interop between apps managed by different Desktop Agents.\n- **Bridge Connection Protocol (BCP)**: A defined set of steps for a Desktop Agent to connect to a Desktop Agent Bridge.\n- **Bridge Messaging Protocol (BMP)**: Protocol for Desktop Agents to communicate with each other over a Desktop Agent Bridge.\n- **Browser Resident Desktop Agent**: A Desktop Agent loaded in a window or frame within a web browser (in contrast to a Desktop Agent that \"injects\" a global fdc3 object) that is communicated with via a Desktop Agent Proxy.\n- **Channel**: A grouping of apps for the purposes of sharing stateful pieces of data. A secondary interface of the FDC3 API.\n- **context channels**: A mechanism to allow sets of apps to share stateful pieces of data among themselves, and to be alerted when that data changes.\n- **context**: Shorthand for context data.\n- **context data**: Objects encoding common identifiers and data in a standardized format that can be passed between apps via context channels or used in conjunction with intents to invoke actions creating a seamless cross-application workflow. Diverse context data types are created to encode different types of data, each having their own _type_ field and unique set of data fields.\n- **Desktop Agent**: A desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain. The primary interface of the FDC3 API.\n- **Desktop Agent Bridge (DAB)**: An independent service that Desktop Agents connect to which allows them to relay requests to other Desktop Agents also connected to the bridge, allowing FDC3-based interop to extend across multiple Desktop Agents and machines.\n- **Desktop Agent Communication Protocol (DACP)**: JSON communication protocol for the Desktop Agent API. Used by a Desktop Agent Proxy interface over the Channel Messaging API (as specified by the Web Connection Protocol) to communicate with a Desktop Agent running in another window/frame.\n- **Desktop Agent Preload**: An 'injected' or 'preloaded' Desktop Agent API implementation, typically provided by an electron (or similar) container or browser extension, which is made available to web applications at `window.fdc3` and may be returned by the `getAgent()` function defined in the FDC3 Web Connection Protocol.\n- **Desktop Agent Proxy**: An interface to a web-based Desktop Agent (implementation of the Desktop Agent API) that uses the Web Connection Protocol and Desktop Agent Communication protocol to communicate with a Desktop Agent implementation running in another frame or window. Returned by the `getAgent()` function provided by the FDC3 NPM module where a browser-based Desktop Agent is detected.\n- **FDC3 API**: A baseline, consistent developer interface for interoperability between applications.\n- **GUID**: Globally Unique IDentifier, synonymous with UUID. Defined by [IETF RFC4122](references).\n- **interop**: Shorthand for interoperability.\n- **interoperability**: the ability of software applications to exchange and make use of information and invoke specified actions.\n- **intent**: A verb, with a pre-agreed meaning (expected behavior), used to invoke an action between applications. A set of such verbs can, in conjunction with Context Data acting as nouns, be used to put together common cross-application workflows on the financial desktop.\n- **Listener**: API interface which allows unsubscribing from Intents or Context Channels.\n- **MessageChannel**: An interface defined by the [HTML Standard's Channel Messaging API](https://html.spec.whatwg.org/multipage/web-messaging.html#channel-messaging) for a two-way pipe with a `MessagePort` at each end, used to implement communication between code running in different browsing contexts. Used by the Web Connection Protocol.\n- **MessagePort**: An interface defined by the [HTML Standard's Channel Messaging API](https://html.spec.whatwg.org/multipage/web-messaging.html#channel-messaging) used to transmit and receive messages over a `MessageChannel`. Each channel has two message ports. Data sent through one port is received by the other port, and vice versa. Used by the Web Connection Protocol.\n- **Originating App**: The application that sent a particular context message or raised an intent.\n- **Parent frame**: A browser window or frame that creates the window or iframe in which an application runs. (The parent provides a `WindowProxy` object which is used by Web Connection Protocol).\n- **Platform Provider**: An environment that provides an implementation of the FDC3 API that applications can use.\n- **raising an intent**: The act of requesting, via the FDC3 API/Desktop Agent that a specified action be performed by another application, using specified context data as input.\n- **resolver**: A facility of a Desktop Agent used to map a raised intent and associated context object to an application that will perform the action represented by the intent, using the context object as input. Where multiple applications can resolve the intent, a resolver will often display a user-interface allowing a user to pick from the available applications that support the intent and type of context supplied.\n- **resolving an intent**: The act of mapping a specified intent and context object to an application.\n- **SessionStorage**: A JavaScript storage API defined by the [HTML Standard's Web Storage API](https://html.spec.whatwg.org/multipage/webstorage.html#webstorage) that persists data for web apps within the scope of a specific window or tab. SessionStorage is identical to the LocalStorage API but is scoped to a particular window/tab, as defined by the [HTML Standard](https://html.spec.whatwg.org/multipage/webstorage.html#dom-sessionstorage)\n- **standard intent**: An intent defined by this Standard.\n- **UUID**: Universally Unique IDentifier, synonymous with GUID. Defined by [IETF RFC4122](references).\n- **Web Connection Protocol (WCP)**: A defined set of steps for a web application to connect to Desktop Agents that implement any of the interfaces defined for web applications in the FDC3 Standard, including both preloaded Desktop Agent interfaces and Browser-based Desktop Agents that work with a Desktop Agent Proxy.\n- **WindowProxy**: An interface defined by the HTML standard that proxies a remote Window object: [https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object). WindowProxy objects are used for communication via `postMessage` as part of the Web Connection Protocol.\n"
  },
  {
    "path": "website/docs/fdc3-intro.md",
    "content": "---\nid: fdc3-intro\ntitle: Welcome to FDC3 2.3 (pre-draft)\nsidebar_label: Introduction\n---\n\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\nFDC3 provides an **open standard for interoperability** between applications on the financial desktop.\n\nThis includes standardized verbs to invoke actions between applications (**intents**), a standardized **context data** format, a REST-based **App Directory** standard, and standardized API operations for a **Desktop Agent**.\n\n## Motivation\n\nFDC3 codifies standard patterns that application developers have been using for cross-application workflows between web and native applications in the financial industry.\n\nFor more information, see [Why FDC3?](why-fdc3)\n\n## Parts of the Standard\n\nThe [Standard](fdc3-standard) currently consists of five complementary parts:\n\n- [API](api/spec)\n- [Intents](intents/spec)\n- [Context Data](context/spec)\n- [App Directory](app-directory/spec)\n- [Agent Bridging](agent-bridging/spec)\n\n## Use Cases\n\nFrom its inception, the standards have been informed by real-world [business use cases](use-cases/overview), which you can view on this website, and form an important part of FDC3.\n\n## Who is using FDC3?\n\nThe Financial Desktop Connectivity and Collaboration Consortium (FDC3) standards are created and used by [leading organizations across the financial industry](/users). For more detail on who's using FDC3, developer tools, training and examples, see the [community page](/community).\n\n## How is FDC3 governed?\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services.\n\n- See the [FDC3 Governance document](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md) for details of how FDC3 is governed.\n- See the [FDC3 Contribution Guide](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for details of how to contribute to FDC3.\n- See the [FDC3 Charter](fdc3-charter#licensing) for details of how deliverables are licensed.\n\n## Where should I go next?\n\n- Have a look at the [API's supported platforms](api/supported-platforms) or [common use cases](use-cases/overview).\n- Visit FDC3 [on GitHub](https://github.com/finos/FDC3).\n- Download and install our [npm package](https://www.npmjs.com/package/@finos/fdc3).\n- Try out an FDC3-compliant implementation, e.g. this [browser extension](https://github.com/finos/fdc3-desktop-agent).\n- Join us in the [mailing list](mailto:fdc3+subscribe@finos.org) or on [Slack](https://app.slack.com/client/T01E7QRQH97/C01R0P7H5LH).\n- [Participate](https://github.com/finos/FDC3#getting-involved) in the evolution of the standard.\n"
  },
  {
    "path": "website/docs/fdc3-standard.md",
    "content": "---\nid: fdc3-standard\ntitle: FDC3 2.3 (pre-draft)\nsidebar_label: Abstract\n---\n\n**Status:** pre-draft  \n_**adopted:** ..._  \n_**released:** ..._\n\n## Abstract\n\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of five complementary parts:\n\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain.\n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n- **[Agent Bridging](agent-bridging/spec)**: An [@experimental](fdc3-compliance#experimental-features) API interface for the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can interoperate.\n\n## Versioning\n\nThis Standard defines FDC3 Version (next). The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n\nFor more details on FDC3's versioning, deprecation and experimental features policies see the [Compliance page](./fdc3-compliance#versioning).\n\n## Table of Contents\n\n- [Compliance information](fdc3-compliance)\n- [Glossary](fdc3-glossary)\n- [References](references)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part](app-directory/spec)\n- [Agent Bridging Part](agent-bridging/spec)\n"
  },
  {
    "path": "website/docs/guides/submit-new-intent.md",
    "content": "---\nid: SubmitNewIntent\nsidebar_label: How To Submit New Intent\ntitle: How to Submit a New Intent PR\n---\n\n## Getting Started\n\nPrepare to submit a patch as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch) in CONTRIBUTING.md. Use the issue number and issue title as the branch name, e.g.\n\n```git checkout -b 587-intent-proposal-view-research```\n\nTo install all the necessary packages to run the website locally, change to the website directory and run yarn\n\n```bash\ncd website\nyarn\n```\n\nTo run the website locally\n\n```yarn start```\n\nThis will open the home page or browse to [https://localhost:3000](https://localhost:3000)\n\nNote that the page opens on the current release version of the docs and you will be changing the latest version. Click the version selector in the top left hand corner\n\n![Version Selector](/assets/version_selector.png)\n\nand then select 'Documentation' under 'Latest Version'\n\n![Latest Version Selector](/assets/latest_version_selector.png)\n\nThe 'next' version will be indicated in the header:\n\n![Next Version](/assets/next_version.png)\n\n## Create Intent File\n\nAdd the new intent markdown file to docs/intents/ref. Use one of the existing intent markdown files as a template. E.g. the [ViewResearch](../intents/ref/ViewResearch) intent was created using [ViewProfile](../intents/ref/ViewProfile) as an example:\n\n![View Research](/assets/view_research.png)\n\n## Link to Intent File\n\nAdd links to your Intent File to the following:\n\n- [src/intents/Intents.ts](https://github.com/finos/FDC3/blob/main/src/intents/Intents.ts)\n- [src/intents/standard intents.json](https://github.com/finos/FDC3/blob/main/src/intents/standard%20intents.json)\n- [website/sidebars.json](https://github.com/finos/FDC3/blob/main/website/sidebars.json) (look for the 'Intents' property and the 'ids' property within it)\n\nAt this point your new Intent should appear on the sidebar (you may need to restart yarn to get this).\n\nAlso add to:\n\n- [docs/intents/spec.md](https://github.com/finos/FDC3/blob/main/docs/intents/spec.md) in the 'Standard Intents' section (also add the summary from your Intent page)\n- Any of the Context documents in [docs/context/ref](https://github.com/finos/FDC3/blob/main/docs/context/ref) that are utilized by the Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent, each of the [Contact](../context/ref/Contact), [Instrument](../context/ref/Instrument) and [Organization](../context/ref/Organization) Contexts are valid and so links were added to their Context pages)\n- Any of the Intents documents in [docs/intents/ref](https://github.com/finos/FDC3/blob/main/docs/intents/ref) that are related or relevant to the new Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent a link was added to the [ViewAnalysis](../intents/ref/ViewAnalysis) document)\n\n## Finishing Off\n\nCommit your changes and push as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch). Then submit the branch as a Pull Request (in github, go to the Branches tab and click 'New Pull Request')\n"
  },
  {
    "path": "website/docs/intents/ref/CreateInteraction.md",
    "content": "---\nid: CreateInteraction\nsidebar_label: CreateInteraction\ntitle: CreateInteraction\nhide_title: true\n---\n# `CreateInteraction`\n\nCreate a record documenting an interaction (calls, meetings, etc.) between a list of contacts.\n\n## Intent Name\n\n`CreateInteraction`\n\n## Display Name\n\n`Create Interaction`\n\n## Possible Contexts\n\n- [ContactList](../../context/ref/ContactList)\n- [Interaction](../../context/ref/Interaction)\n\nSHOULD return context as a result:\n\n- [TransactionResult](../../context/ref/TransactionResult)\n\n## Example\n\n```js\nconst interaction = {\n    type: 'fdc3.interaction',\n    participants: {\n        type: 'fdc3.contactList',\n        contacts: [\n            {\n                type: 'fdc3.contact',\n                name: 'Jane Doe',\n                id: {\n                    email: 'jane.doe@mail.com'\n                }\n             },\n            {\n                type: 'fdc3.contact',\n                name: 'John Doe',\n                id: {\n                    email: 'john.doe@mail.com'\n                }\n            },\n        ]\n    },\n    interactionType: 'Instant Message',\n    timeRange: {\n        type: 'fdc3.timeRange',\n        startTime: '2022-02-10T15:12:00Z'\n    },\n    description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n    initiator:  {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n            email: 'jane.doe@mail.com'\n        }\n    },\n    origin: 'Outlook'\n}\n\nconst intentResolution = await fdc3.raiseIntent('CreateInteraction', interaction);\nconst result = await intentResolution.getResult();\nconsole.log(result);\n```\n\nConsole log will display:\n\n```js\n{\n    type: 'fdc3.transactionResult',\n    status: 'Created',\n    context: {\n        type: 'fdc3.interaction',\n        participants: {\n            type: 'fdc3.contactList',\n            contacts: [\n                {\n                    type: 'fdc3.contact',\n                    name: 'Jane Doe',\n                    id: {\n                        email: 'jane.doe@mail.com'\n                    }\n                 },\n                {\n                    type: 'fdc3.contact',\n                    name: 'John Doe',\n                    id: {\n                        email: 'john.doe@mail.com'\n                    }\n                },\n            ]\n        },\n        interactionType: 'Instant Message',\n        timeRange: {\n            type: 'fdc3.timeRange',\n            startTime: '2022-02-10T15:12:00Z'\n        },\n        description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n        initiator:  {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        origin: 'Outlook'\n        id:  {\n            Singletrack: 'a0S8d000000uO05EAE'\n        }\n    },\n    message: 'record with id \"a0S8d000000uO05EAE\" was created'\n}\n```\n\n## See Also\n\nContext\n- [Interaction](../../context/ref/Interaction)\n- [TransactionResult](../../context/ref/TransactionResult)"
  },
  {
    "path": "website/docs/intents/ref/CreateOrUpdateProfile.md",
    "content": "---\nid: CreateOrUpdateProfile\nsidebar_label: CreateOrUpdateProfile\ntitle: CreateOrUpdateProfile\nhide_title: true\n---\n# `CreateOrUpdateProfile`\n\nCreate a record or update an existing profile record with information for the individual or organization provided as context.\n\n## Intent Name\n\n`CreateOrUpdateProfile`\n\n## Display Name\n\n`Create or Update Profile`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\nSHOULD return context as a result:\n\n- [TransactionResult](../../context/ref/TransactionResult)\n\n## Example\n\n```js\nconst organization = {\n  \"type\": \"fdc3.organization\",\n  \"name\": \"Cargill, Incorporated\",\n  \"id\": {\n    \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n    \"FDS_ID\": \"00161G-E\"\n  }\n};\n\nconst intentResolution = await fdc3.raiseIntent('CreateOrUpdateProfile', organization);\nconst result = await intentResolution.getResult();\nconsole.log(result);\n```\n\nConsole log might display:\n\n```js\n{\n    type: 'fdc3.transactionResult',\n    status: 'Created',\n    context: {\n        \"type\": \"fdc3.organization\",\n        \"name\": \"Cargill, Incorporated\",\n        \"id\": {\n            \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n            \"FDS_ID\": \"00161G-E\",\n            \"internalId\": \"al983020303a_23\"\n        }\n    },\n    message: 'record with id \"al983020303a_23\" was created'\n}\n```\n\n## See Also\n\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n- [TransactionResult](../../context/ref/TransactionResult)"
  },
  {
    "path": "website/docs/intents/ref/SendChatMessage.md",
    "content": "---\nid: SendChatMessage\nsidebar_label: SendChatMessage\ntitle: SendChatMessage\nhide_title: true\n---\n# `SendChatMessage`\n\nSend a message to an existing chat room.\n\n## Intent Name\n\n`SendChatMessage`\n\n## Display Name\n\n`Send Chat Message`\n\n## Possible Contexts\n\n- [ChatMessage](../../context/ref/ChatMessage)\n\n## Example\n\n```js\n// Start a chat and retrieve a reference to the chat room created\nconst intentResolution = await fdc3.raiseIntent(\"StartChat\", context);\nconst chatRoom = intentResolution.getResult();\n\n//Some time later\n\nlet chatMessage: ChatMessage = {\n    type: \"fdc3.chat.message\",\n    chatRoom,\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nawait fdc3.raiseIntent(\"SendChatMessage\", context, intentResolution.source);\n```\n\n## See Also\n\nContext\n- [ChatMessage](../../context/ref/ChatMessage)\n- [ChatRoom](../../context/ref/ChatRoom)\n\nIntents\n- [StartChat](StartChat)\n- [StartCall](StartCall)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/docs/intents/ref/StartCall.md",
    "content": "---\nid: StartCall\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n\n- [StartChat](StartChat)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/docs/intents/ref/StartChat.md",
    "content": "---\nid: StartChat\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\n---\n# `StartChat`\n\nInitiate a chat with a contact, a list of contacts or detailed initialization settings.  This could be launched from within another application. For example initiating a chat from a research or OMS application.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n\n// chat with initialization settings\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Chat ABCD',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane@mail.com'\n            }\n        },{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true\n    }\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nconst resolution = fdc3.raiseIntent('StartChat', initSettings);\n\n// Return a reference to the room\nconst chatRoom = await resolution.getResult();\n```\n\n## See Also\n\nContext\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\nIntents\n\n- [SendChatMessage](SendChatMessage)\n- [StartCall](StartCall)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/docs/intents/ref/StartEmail.md",
    "content": "---\nid: StartEmail\nsidebar_label: StartEmail\ntitle: StartEmail\nhide_title: true\n---\n# `StartEmail`\n\nInitiate an email with a contact or list of contacts provided as part of an Email context.\n\n## Intent Name\n\n`StartEmail`\n\n## Display Name\n\n`Start Email`\n\n## Possible Contexts\n\n- [Email](../../context/ref/Email)\n\n## Example\n\n```js\nwindow.fdc3.raiseIntent('fdc3.StartEmail', {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n})\n```\n\n## See Also\n\nContext\n\n- [Email](../../context/ref/Email)\n\nIntents\n\n- [StartCall](StartCall)\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewAnalysis.md",
    "content": "---\nid: ViewAnalysis\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewChart.md",
    "content": "---\nid: ViewChart\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\n---\n# `ViewChart`\n\nDisplay a chart for the provided context.\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n## Example\n\nRequest a chart for an instrument:\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\nRequest a specific chart:\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: {\n        indicators: [\n            {\n                name: \"ma\",\n                parameters: {\n                    period: 14,\n                    type: \"ema\"\n                }\n            },\n            {\n                name: \"volume\"\n            }\n        ]\n    }\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nContext\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewQuote](ViewQuote)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewChat.md",
    "content": "---\nid: ViewChat\nsidebar_label: ViewChat\ntitle: ViewChat\nhide_title: true\n---\n# `ViewChat`\n\nOpen an existing chat room.\n\n## Intent Name\n\n`ViewChat`\n\n## Display Name\n\n`View Chat`\n\n## Possible Contexts\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact): It will open the **direct** chat where there is the current user and the contact\n- [ContactList](../../context/ref/ContactList): It will open the **room** where there is the current user and the listed contacts. Contact List may need to display search results if there are multiple matches.\n\n## Output\n\nThis intent returns as output:\n- If the chat doesn't exist, will display a modal to create a chat\n- if the chat gets created, return its ChatRoom context\n- if none is created return void\n\n## Example: ChatRoom\n\n```js\nconst chatRoom = {\n    type: 'fdc3.chat.room',\n    providerName: \"Symphony\",\n    id: {\n        streamId: \"j75xqXy25NBOdacUI3FNBH\"\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', chatRoom);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## Example: Contact\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contact);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the direct chat was found\n```\n\n## Example: ContactList\n\n```js\nconst contacts = {\n    type: 'fdc3.contactList',\n    contacts: [\n        {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john.doe@mail.com'\n            }\n        },\n    ]\n}\n\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contacts);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## See Also\n\nContext\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n\n- [StartChat](StartChat)"
  },
  {
    "path": "website/docs/intents/ref/ViewContact.md",
    "content": "---\nid: ViewContact\nsidebar_label: ViewContact (deprecated)\ntitle: ViewContact\nhide_title: true\n---\n# `ViewContact`\n\n:::caution\nViewContact has been deprecated in FDC3 2.0 in favour of the more general [ViewProfile](ViewProfile) intent.\n:::\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n\nIntents\n\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewHoldings.md",
    "content": "---\nid: ViewHoldings\nsidebar_label: ViewHoldings\ntitle: ViewHoldings\nhide_title: true\n---\n# `ViewHoldings`\n\nDisplay any holdings for the provided instrument, list of instruments, or organization.\n\n## Intent Name\n\n`ViewHoldings`\n\n## Display Name\n\n`View Holdings`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewHoldings', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewInstrument](ViewInstrument)\n- [ViewAnalysis](ViewAnalysis)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewInstrument.md",
    "content": "---\nid: ViewInstrument\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewInteractions.md",
    "content": "---\nid: ViewInteractions\nsidebar_label: ViewInteractions\ntitle: ViewInteractions\nhide_title: true\n---\n# `ViewInteractions`\n\nDisplay interactions (calls, meetings, etc.) related to an individual, an instrument or organization provided as context.\n\n## Intent Name\n\n`ViewInteractions`\n\n## Display Name\n\n`View Interactions`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewInteractions', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewProfile](ViewProfile)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewMessages.md",
    "content": "---\nid: ViewMessages\nsidebar_label: ViewMessages\ntitle: ViewMessages\nhide_title: true\n---\n# `ViewMessages`\n\nSearch and display a list of messages (for example in a chat application or CRM) to the user. \n\n## Intent Name\n\n`ViewMessages`\n\n## Display Name\n\n`View Messages`\n\n## Possible Contexts\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n\n## Example\n\nRequest display of messages relating to a specific `fdc3.instrument` (representing a ticker):\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.contact`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.organization`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific **phrase**:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages matching _multiple_ criteria:\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        },\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\n## See Also\n\nContext\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n* [Instrument](../../context/ref/Instrument)\n* [Contact](../../context/ref/Contact)\n* [Organization](../../context/ref/Organization)\n\nIntents\n\n* [ViewChat](ViewChat)"
  },
  {
    "path": "website/docs/intents/ref/ViewNews.md",
    "content": "---\nid: ViewNews\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'IBM'\n    },\n    market: {\n        MIC: \"XNYS\"\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewOrders.md",
    "content": "---\nid: ViewOrders\nsidebar_label: ViewOrders\ntitle: ViewOrders\nhide_title: true\n---\n# `ViewOrders`\n\nDisplay any orders related to the provided contact, instrument, or organization.\n\n## Intent Name\n\n`ViewOrders`\n\n## Display Name\n\n`View Orders`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewOrders', instrument)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInstrument](ViewInstrument)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewProfile.md",
    "content": "---\nid: ViewProfile\nsidebar_label: ViewProfile\ntitle: ViewProfile\nhide_title: true\n---\n# `ViewProfile`\n\nDisplay basic profile information for the individual or organization provided as context.\n\n## Intent Name\n\n`ViewProfile`\n\n## Display Name\n\n`View Profile`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewProfile', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInteractions](ViewInteractions)\n"
  },
  {
    "path": "website/docs/intents/ref/ViewQuote.md",
    "content": "---\nid: ViewQuote\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\n---\n# `ViewQuote`\n\nDisplay pricing for an [Instrument](../../context/ref/Instrument).\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/docs/intents/ref/ViewResearch.md",
    "content": "---\nid: ViewResearch\nsidebar_label: ViewResearch\ntitle: ViewResearch\nhide_title: true\n---\n# `ViewResearch`\n\nShow research related to an instrument, an individual or organization provided as context.\n\n## Intent Name\n\n`ViewResearch`\n\n## Display Name\n\n`View Research`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewResearch', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/docs/intents/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Intents Overview (next)\n---\n\nFDC3 Intents define a standard set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n\n- Applications register the intents and [context data](../context/spec) combinations they support in the [App Directory](../app-directory/spec).\n- The App Directory supports application discovery by intents and/or context data.\n- Intents are not full RPC, apps don’t need to enumerate every function with an intent.\n- FDC3 standard intents are a limited set, organizations can create their own intents.\n\n## Naming Conventions\n\nNaming of Intents SHOULD follow the below guidelines:\n\n- Intent names should be free of non-alphanumeric characters.\n- ‘.’ will be used to namespace the intent (see below).\n- Intent names should be in UpperCamelCase.\n\n:::note\nThe naming guidelines should be adhered to when creating future Intents.  This is to ensure they meet the criteria for addition to the FDC3 standard and to provide a consistent user experience.\n:::\n\n### Characteristics\n\nWhen creating Intents they should be:\n\n- Recognizable\n  - Generally self-evident what the thing is\n- Repeatable\n  - Many instances across the industry\n- Stateless\n  - Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n- Specific\n  - Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n- Distinct\n  - Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces\n\nAll standard intent names are reserved. Applications may use their own intents ad hoc.\nHowever, there is occasionally a need for applications to ensure that their intents avoid collision, for example, where a workflow is highly specific to or internal to an application. The recommended approach is to namespace the intent with the application name. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary intent.\n\n### Intent Name Prefixes\n\nEarly versions of the FDC3 standard included 8 intents, which used one of two different prefixes ( `View___` and `Start___`) that are focused on UI interactions.  The prefixes are used to help define the expected behavior of an app when resolving an intent with that prefix. The list of intent name prefixes was expanded in FDC3 2.0 to include prefixes that indicate that CRUD operations should be performed on data.\n\n#### `View___`\n\n- Expected behavior: Content should be displayed to the user.\n\n#### `Start___`\n  \n- Expected behavior: An interaction, such as a chat room or email thread, should be initiated.\n\nAs more use cases were identified it was clear further Intents were required.  FDC3 2.0 expanded this set to include the following:\n\n#### `Create___`\n\n- Expected behavior: A new record or entity should be created. The operation should fail if it already exists.\n\n#### `Update___`\n\n- Expected behavior: An existing record or entity should be updated. The operation should fail if it does not exist.\n\n#### `CreateOrUpdate___`\n\n- Expected behavior: A new record or entity should be created, or an existing one updated if it exists.\n\n#### `Delete___`\n\n- Expected behavior: An existing record or entity should be deleted. The operation should fail if it does not exist.\n\n#### `Get___`\n\n- Expected behavior: A record or entity should be retrieved and returned as an intent result. The operation should fail if the record does not exist.\n\n#### `Share___`\n\n- Expected behavior: A record or entity should shared. The operation should fail if it does not exist\n\n## Using Intents\n\nCombined with [context data](../context/spec) and [App Directory](../app-directory/overview) standards, intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.contact\",\n  name: \"Jane Doe\",\n  id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n\n## Intents that return data\n\nFrom FDC3 2.0, intents raised through the Desktop Agent API may return results in the form of a `Context` object or a `Channel`. Where an intent implements a transaction with another application, for example for a CRUD operation, the [`fdc3.transactionResult` context type](../context/ref/TransactionResult) SHOULD be used to provide a result status for the transaction and may wrap a context object that would otherwise be returned.\n\nFor more details on retrieving a result from a raised intent, see the [documentation for `raiseIntent`](../api/ref/DesktopAgent#raiseintent).\n\n## Intents Standard Compliance\n\nAn FDC3 Standard compliant application that supports intents **MUST**:\n\n- Meet the expected context and behavior defined for any FDC3-defined standard intents used.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) after it is launched. This facilitates delivery of raised intents to the application.\n\nAn FDC3 Standard compliant application that supports intents **SHOULD**:\n\n- Prefer FDC3-defined standard intents over proprietary intents, where a suitable standardized intent is available.\n- Ensure that proprietary intents follow the recommended naming conventions in the specification.\n- Apply [namespacing](#namespaces) to proprietary intent names, where it is necessary to avoid collision with those created by other applications.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n- Use the `fdc3.transactionResult` context type to return a status for any transactions relating to CRUD operations.\n\nAn FDC3 Standard compliant application that supports intents **MAY**:\n\n- Define proprietary intents to support use cases not currently supported via FDC3-defined standard intents.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Intents\n\nA list of standardized intents are defined in the following pages:\n\n- [`CreateInteraction`](ref/CreateInteraction)\n- [`CreateOrUpdateProfile`](ref/CreateOrUpdateProfile)\n- [`StartCall`](ref/StartCall)\n- [`StartChat`](ref/StartChat)\n- [`StartEmail`](ref/StartEmail)\n- [`ViewAnalysis`](ref/ViewAnalysis)\n- [`ViewChat`](ref/ViewChat)\n- [`ViewChart`](ref/ViewChart)\n- [`ViewHoldings`](ref/ViewHoldings)\n- [`ViewInstrument`](ref/ViewInstrument)\n- [`ViewInteractions`](ref/ViewInteractions)\n- [`ViewMessages`](ref/ViewMessages)\n- [`ViewNews`](ref/ViewNews)\n- [`ViewOrders`](ref/ViewOrders)\n- [`ViewProfile`](ref/ViewProfile)\n- [`ViewQuote`](ref/ViewQuote)\n- [`ViewResearch`](ref/ViewResearch)\n\n### Deprecated Intents\n\n- [`ViewContact`](ref/ViewContact)\n\n## Using Intents without a context\n\nAs the [Desktop Agent API](../api/ref/DesktopAgent) and [App Directory](../app-directory/overview) both require a context to be specified wherever intents are used, using an intent without a context is achieved through the use of the explicit `null` context type [`fdc3.nothing`](../context/ref/Nothing). By using an explicit type to represent an absence of context we allow applications to declare their support for an absence of context.\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.nothing\",\n});\n\nconst result = await fdc3.raiseIntent(\"StartChat\", {\n  type: \"fdc3.nothing\"\n});\n```\n"
  },
  {
    "path": "website/docs/references.md",
    "content": "---\nid: references\ntitle: References & Bibliography\nsidebar_label: References\n---\n\n\nThe following normative documents contain provisions, which, through reference in this text, constitute provisions of this Standard. For dated references, subsequent amendments to, or revisions of, any of these publications do not apply. However, parties to agreements based on this Standard are encouraged to investigate the possibility of applying the most recent editions of the normative documents indicated below. For undated references, the latest edition of the normative document referred to applies:\n\n- **Apache 2.0 open-source license**, [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0).\n- **Community Specification license**, [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0)\n- **ISO 3166-1**, _Codes for the representation of names of countries and their subdivisions – Part 1: Country codes_, [https://www.iso.org/iso-3166-country-codes.html](https://www.iso.org/iso-3166-country-codes.html).\n- **ISO 8601-1:2019**, _Date and time — Representations for information interchange — Part 1: Basic rules_, [https://www.iso.org/standard/70907.html](https://www.iso.org/standard/70907.html)\n- **JSON Schema**, [https://json-schema.org/](https://json-schema.org/).\n- **OpenAPI Standard v3.0**, [https://www.openapis.org/](https://www.openapis.org/).\n- **quicktype**, [https://quicktype.io/](https://quicktype.io/).\n- **RFC 2119**, _Keywords for use in RFCs to Indicate Requirement Levels, March 1997_, [https://datatracker.ietf.org/doc/html/rfc2119](https://datatracker.ietf.org/doc/html/rfc2119).\n- **RFC 2782**, _A DNS RR for specifying the location of services (DNS SRV), February 2000_, [https://datatracker.ietf.org/doc/html/rfc2782](https://datatracker.ietf.org/doc/html/rfc2782).\n- **RFC 4122**, _A Universally Unique IDentifier (UUID) URN Namespace, July 2005_, [https://datatracker.ietf.org/doc/html/rfc4122](https://datatracker.ietf.org/doc/html/rfc4122).\n- **RFC 5646**, _Tags for Identifying Languages, September 2009_, [https://datatracker.ietf.org/doc/html/rfc5646](https://datatracker.ietf.org/doc/html/rfc5646).\n- **TypeScript Programming Language**, [https://www.typescriptlang.org/](https://www.typescriptlang.org/).\n- **Web Application Manifest**, _W3C Working Draft_, February 2022 [https://www.w3.org/TR/appmanifest/](https://www.w3.org/TR/appmanifest/)\n\nThe following documents may be useful in understanding certain aspects of this Standard; however, knowledge of them is not essential to the creation of a compliant implementation of this Standard:\n\n- **CUSIP**, _Committee on Uniform Security Identification Procedures_, [https://www.cusip.com/identifiers.html#/CUSIP](https://www.cusip.com/identifiers.html#/CUSIP).\n- **FIGI**, _Financial Instrument Global Identifier_, [https://www.openfigi.com/about/figi](https://www.openfigi.com/about/figi).\n- **ISIN**, _International Securities Identification Number_, [https://www.isin.org/isin/](https://www.isin.org/isin/)\n- **LEI**, _Legal Entity Identifier based on the ISO 17442 standard_, [https://www.legalentityidentifier.co.uk/what-is-lei-code/](https://www.legalentityidentifier.co.uk/what-is-lei-code/).\n- **npm**,  [https://docs.npmjs.com/about-npm](https://docs.npmjs.com/about-npm).\n- **PermID**, _Permanent Identifiers_, [https://permid.org/](https://permid.org/).\n- **pnpm**, [https://pnpm.io/motivation](https://pnpm.io/motivation).\n- **REST**, [https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm), [https://restfulapi.net/](https://restfulapi.net/).\n- **SEDOL**, _Stock Exchange Daily Official List_, [https://www.lseg.com/sedol](https://www.lseg.com/sedol).\n- **yarn**, [https://yarnpkg.com/getting-started](https://yarnpkg.com/getting-started).\n"
  },
  {
    "path": "website/docs/trademarks.md",
    "content": "---\nid: trademarks\ntitle: Trademarks\n---\n\nThe trademarks, logos, and service marks not owned on behalf of FDC3 and FINOS and that are displayed on the Site are the registered and unregistered marks of their respective owners. No rights are granted by the FDC3 or FINOS to use such marks, whether by implication, estoppel, or otherwise.\n\nTrademarks used within this site and the FDC3 Standard include, but are not limited to:\n\n- Autobahn is a registered trademark of DEUTSCHE BANK AG, LONDON\n- Chromium is a trademark of Google LLC\n- Eikon is a registered trademark of Refinitiv\n- FDC3 is a registered trademark and brand of The Linux Foundation\n- Excel is a Microsoft Corporation product name\n- Finsemble is a registered trademark and product name of interop.io, Inc.\n- Glue42 is a trademark and product name of interop.io, Inc.\n- io.Connect is a trademark and product name of interop.io, Inc.\n- Java is a registered trademark of Oracle America, Inc.\n- JavaScript  is a registered trademark of Oracle America, Inc.\n- .NET is a trademark of Microsoft Corporation\n- npm is a trademark of npm, Inc.\n- OpenFin is a registered trademark of OpenFin Inc.\n- Outlook is a registered trademark of Microsoft Corporation\n- Python is a registered trademark of the Python Software Foundation\n"
  },
  {
    "path": "website/docs/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\n---\n\n![A diagrammatic representation of the applications available to the trader](/img/use-cases/1.png)\n\nOn their desktop, this user has:\n\n- Their firm's internal research & analytics platform, providing liquidity tools and internal research. The product is running and the **liquidity tool** is open.\n- An installed **chat application** is running.\nA **Watchlist** of stocks the trader is interested in\nA third-party **Charting Application** is available that the user accesses via a browser window. This is not open. \nAn **Overview** which gives pricing and fundamental data for stocks\n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/docs/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/docs/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/docs/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/docs/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/docs/use-cases/006-call-transcription-to-crm.md",
    "content": "---\nid: uc-6\ntitle: \"Use Case 6: Call Transcription to CRM\"\nsidebar_label: 6. Call Transcription to CRM\nlayout: use_case\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/docs/use-cases/007-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-7\ntitle: \"Use Case 7: Real-Time voice trades -> trade ticket population\"\nsidebar_label: \"7. Real-Time voice trades -> trade ticket population\"\nlayout: use_case\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/docs/use-cases/008-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-8\ntitle: \"Use Case 8: User launches multiple apps from a single container\"\nsidebar_label: 8. User launches multiple apps from a single container\nlayout: use_case\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/docs/use-cases/009-sales-floor-base-workflow.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Sales Floor Base Workflow\"\nsidebar_label: 9. Sales Floor Base Workflow\nlayout: use_case\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/docs/use-cases/010-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Quantifying FDC3 Interactions\"\nsidebar_label: 10. Quantifying FDC3 Interactions\nlayout: use_case\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/docs/use-cases/011-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-11\ntitle: \"Use Case 11: Fine-tuning InterOp with Channels\"\nsidebar_label: 11. Fine-tuning InterOp with Channels\nlayout: use_case\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/docs/use-cases/meeting-minutes/2020-01-16 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n\n\n## Agenda\n### 1. 2020 Move to GitHub - JT (15 min)\n- Goal: manage all new UCWG content in GitHub in 2020\n\n**Proposal:** how to manage the UCWG content \n- Meeting Minutes \n  - legacy [keep them on confluence and link to them] AGREED - link to be added\n  - new [in github, [this folder](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases/meeting-minutes), we also could create a GitHub Issue template] AGREED - link to be updated\n- Governance Docs [to be refreshed and moved to the [use cases intro](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/use-cases-intro.md) page]  - AGREED to move to intro doc, but need to be reviewed and cleaned up. \n  - Ratifying use cases via GitHub PRs - voting done via GitHub (👍 / 👎 on an issue - see [UC 17](https://github.com/finos/FDC3/pull/153)) rather than Google Groups - AGREED \n- Use Cases \n  - 1. In Review [will be managed via submitted pull requests - see [this](https://github.com/finos/FDC3/pulls?q=is%3Aopen+is%3Apr+label%3Ause-cases)]\n  - 2. Accepted [DONE - listed [here](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases)]\n  - 3. Rejected \n  - 4. Deleted \n  - 5. Backlog \n  - Use Case XX: Template [we can create this as a github issue type] - JT to try and prove this works\n- Action Items \n  - to be reviewed and closed out. Relevant ones will be migrated. \n- Process: \n  - One of the participants edits meeting minutes live on a screenshare during the call. All participants on the call review and approve the minutes at the end of the call. Once approved verbally on the call, the meeting minutes PR can be merged. \n\n### 2. UC 17 Vote - Johan (5 min)\n- Voting directly on the PR: https://github.com/finos/FDC3/pull/153\n- APPROVED AND MERGED!\n\n### 3. UCWG Goals and Roadmap - JT (15 min)\n- see proposal [here](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/fdc3-okrs.md#use-case-working-group)\n- UCWG to review offline and comment\n\n### 4. AOB \n- lean UCWG + new recruits\n- clean up open action items in confluence\n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/docs/use-cases/meeting-minutes/2020-02-20 uc-wg meeting notes.md",
    "content": "---\n\n---\n\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n| Leslie Spiro | Tick42 |  |\n\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/docs/use-cases/meeting-minutes/2020-03-19 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Meeting not held due to low attendance**\n\n**Date**: 19 March 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n\n"
  },
  {
    "path": "website/docs/use-cases/overview.md",
    "content": "---\nid: overview\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/docs/use-cases/readme.md",
    "content": "---\n\n---\n# Overview \nHere are business use cases that have been documented and ratified by the Use Cases Working Group\n\n# Adoption of Use Cases into the FDC3 Standard\n\n**Use Cases Accepted onto Roadmap of Standards or Implemented**\n\n| Use Cases                                                           | Count         | %       |\n| -------------                                                       |:-------------:| :----:  |\n| 001-equity-sell-side-trader                                         | \t2 / 5       |   40%   | \n| 002-buy-side-portfolio-manager                                      | \t0 / 3\t      |   33%   | \n| 003-inhouse-cross-platform-launcher                                 | \t0 / 8       |    0%   | \n| 004-client-side-fx-trader                                           | \t0 / 1\t      |    0%   | \n| 005-buy-side-treasurer                                              | \t0 / 3\t      |    0%   | \n| 009-call-transcription-to-crm                                       | \t0 / 2\t      |    0%   | \n| 010-realtime-trade-ticket-population                                | \t0 / 1\t      |    0%   | \n| 013-user-launches-multiple-apps-from-a-single-container             | \t0 / 3\t      |    0%   | \n| 015-sales-floor-base-workflow                                       | \t0 / 2\t      |    0%   | \n| 016-quantifying-fdc3-interactions                                   | \t0 / 3\t      |    0%   | \n| total                                                               | \t2 / 31      |  6.5%   | \n\n\n\n**Summary**\n\n| Status                                | Count         | %       |\n| -------------                         |:-------------:| :----:  |\n| New                                   | \t24\t        |   77.5%   | \n| Proposed                              | \t5           | \t16%   | \n| **Accepted onto Roadmap of Standard** | \t0           | \t**0%**  | \n| **Implemented**                       | \t2         \t|  **6.5%** | \n| Rejected                              | \t0           | \t0%    | \n| N/R                                   | \t3           |         | \t\n| Total (excl. N/R)                     | \t31          | \t100%  | \n"
  },
  {
    "path": "website/docs/why-fdc3.md",
    "content": "---\nid: why-fdc3\nsidebar_label: Why FDC3?\ntitle: Why FDC3?\n---\n\n## Why look for FDC3-enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go.\n\nThe main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3-enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context).\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still, much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc..\n\nEvery application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3-enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3-enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration. With an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/docusaurus.config.js",
    "content": "module.exports = {\n  \"title\": \"FDC3\",\n  \"tagline\": \"Open standards for the financial desktop\",\n  \"url\": \"https://fdc3.finos.org\",\n  \"baseUrl\": \"/\",\n  \"staticDirectories\": [\"static\"],\n  \"organizationName\": \"finos\",\n  \"projectName\": \"FDC3\",\n  \"scripts\": [\n    \"https://buttons.github.io/buttons.js\"\n  ],\n  \"favicon\": \"img/favicon/favicon.ico\",\n  \"customFields\": {\n    \"separateCss\": [\n      \"static/toolbox/fdc3-workbench/static/css\",\n      \"static/toolbox/fdc3-explained/1.0\",\n      \"static/toolbox/fdc3-explained/1.1\",\n      \"static/toolbox/fdc3-explained/1.2\"\n    ],\n    \"wrapPagesHTML\": true,\n    \"repoUrl\": \"https://github.com/finos/FDC3\"\n  },\n  \"onBrokenLinks\": \"log\",\n  \"onBrokenMarkdownLinks\": \"log\",\n  \"presets\": [\n    [\n      \"@docusaurus/preset-classic\",\n      {\n        \"docs\": {\n          \"showLastUpdateAuthor\": true,\n          \"showLastUpdateTime\": true,\n          \"path\": \"./docs\",\n          \"sidebarPath\": \"./sidebars.json\",\n        },\n        \"theme\": {\n          \"customCss\": \"./src/css/customTheme.css\"\n        },\n        \"gtag\": {\n          \"trackingID\": \"G-EY9BQJ55YQ\",\n          \"anonymizeIP\": true,\n        }\n      }\n    ]\n  ],\n  markdown: {\n    mermaid: true,\n  },\n  themes: ['@docusaurus/theme-mermaid'],\n  \"plugins\": [],\n  \"themeConfig\": {\n    \"prism\": {\n      \"additionalLanguages\": [\"typescript\", \"javascript\", \"json\", \"csharp\", \"go\"],\n      \"theme\": require('prism-react-renderer').themes.vsDark\n    },\n    \"algolia\": {\n      \"appId\": \"YW91L9TW76\",\n      \"apiKey\": \"ab431bb4107069ef51780d8947cd8e0a\",\n      \"indexName\": \"fdc3-finos\",\n      \"contextualSearch\": true,\n      \"searchParameters\": {}\n    },\n    \"navbar\": {\n      \"title\": \"FDC3\",\n      \"logo\": {\n        \"src\": \"img/fdc3-icon-light-2019.svg\",\n        \"srcDark\": \"img/fdc3-icon-2019.svg\"\n      },\n      \"items\": [\n        {\n          \"to\": \"docs/fdc3-intro\",\n          \"label\": \"Getting Started\",\n          \"position\": \"left\"\n        },\n        {\n          \"to\": \"/community\",\n          \"label\": \"Community\",\n          \"position\": \"left\"\n        },\n        {\n          \"to\": \"docs/fdc3-standard\",\n          \"label\": \"The Standard\",\n          \"position\": \"left\"\n        },\n        {\n          \"to\": \"/get-involved\",\n          \"label\": \"Get Involved\",\n          \"position\": \"left\"\n        },\n        {\n          \"href\": \"https://directory.fdc3.finos.org\",\n          \"label\": \"FINOS AppD\",\n          \"position\": \"left\"\n        },\n        {\n          \"href\": \"/training\",\n          \"label\": \"Training\",\n          \"position\": \"left\"\n        },\n        {\n          type: 'docsVersionDropdown',\n          position: 'right',\n          dropdownItemsAfter: [{ to: '/versions', label: 'All versions' }],\n          dropdownActiveClassDisabled: true,\n        }\n      ]\n    },\n    \"image\": \"/assets/fdc3-logo.png\",\n    \"footer\": {\n      \"links\": [\n        {\n          \"title\": \"Learn\",\n          \"items\": [\n            {\n              \"label\": \"Getting Started\",\n              \"to\": \"/docs/fdc3-intro\"\n            },\n            {\n              \"label\": \"Supported Platforms\",\n              \"to\": \"/docs/next/api/supported-platforms\"\n            },\n            {\n              \"label\": \"API Reference\",\n              \"to\": \"/docs/api/ref/DesktopAgent\"\n            },\n            {\n              \"label\": \"Use Cases\",\n              \"to\": \"/docs/next/use-cases/overview\"\n            },\n            {\n              \"label\": \"Training\",\n              \"to\": \"https://fdc3.finos.org/training\"\n            }\n          ]\n        },\n        {\n          \"title\": \"Community\",\n          \"items\": [\n            {\n              \"label\": \"FINOS\",\n              \"to\": \"https://www.finos.org/\"\n            },\n            {\n              \"label\": \"Slack\",\n              \"to\": \"https://finos-lf.slack.com/messages/fdc3/\"\n            },\n            {\n              \"label\": \"Stack Overflow\",\n              \"to\": \"https://stackoverflow.com/questions/tagged/fdc3\"\n            },\n            {\n              \"label\": \"Google Groups\",\n              \"to\": \"https://groups.google.com/a/finos.org/forum/#!forum/fdc3\"\n            },\n            {\n              \"label\": \"Trademarks\",\n              \"to\": \"/docs/next/trademarks\"\n            }\n          ]\n        },\n        {\n          \"title\": \"More\",\n          \"items\": [\n            {\n              \"html\": \"<a href=\\\"https://github.com/finos/FDC3\\\"><img alt=\\\"Github\\\" src=\\\"https://img.shields.io/github/stars/finos/FDC3?label=FDC3&style=social\\\" /></a>\"\n            },\n            {\n              \"label\": \"Users\",\n              \"to\": \"/users\"\n            },\n            {\n              \"label\": \"Versions\",\n              \"to\": \"/versions\"\n            }\n          ]\n        }\n      ],\n      \"copyright\": \"<span class=\\\"footer-strap\\\">Proud member of the Fintech Open Source Foundation</span><br/><br/><span class=\\\"footer-copyright\\\">Copyright © 2019-2025 FDC3 - FINOS</span>\",\n      \"logo\": {\n        \"src\": \"img/finos_wordmark.svg\",\n        \"alt\": \"FINOS Logo\",\n        \"width\": 50,\n        \"href\": \"https://finos.org\"\n      }\n    },\n    \"mermaid\": {\n      \"options\": {\n        \"htmlLabels\": true,\n        \"markdownAutoWrap\": true,\n        \"wrap\": true,\n        \"wrappingWidth\": 50,\n        \"flowchart\": {\n          \"titleTopMargin\": 30,\n          \"subGraphTitleMargin\": {\n            \"top\": 30,\n            \"bottom\": 30\n          },\n          \"nodeSpacing\": 30,\n          \"rankSpacing\": 50,\n          \"diagramPadding\": 5,\n          \"useMaxWidth\": true,\n          \"htmlLabels\": true,\n          \"wrappingWidth\": 50\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "website/package.json",
    "content": "{\n  \"scripts\": {\n    \"clean\": \"npx rimraf build .docusaurus\",\n    \"examples\": \"docusaurus-examples\",\n    \"prestart\": \"npm run copy-schemas && npm run copy-appd && npm run copy-conformance && cross-env NODE_ENV=development npm run replace-conformance-urls && node schema2Markdown.js\",\n    \"start\": \"docusaurus start\",\n    \"prebuild\": \"npm run parent-build && npm run copy-schemas && npm run copy-appd && npm run copy-workbench && npm run copy-conformance && npm run replace-conformance-urls && npm run copy-reference-ui && node schema2Markdown.js && npm run copy-workbench && npm run copy-explained\",\n    \"build\": \"docusaurus build\",\n    \"build-temp\": \"npm run copy-schemas && npm run copy-appd && npm run copy-workbench && npm run copy-reference-ui && node schema2Markdown.js && npm run copy-workbench && npm run copy-explained && docusaurus build\",\n    \"parent-build\": \"cd .. && npm install && npm run build\",\n    \"copy-schemas\": \"del-cli static/schemas/next/*/ && cpy \\\"../packages/fdc3-schema/schemas/**\\\" static/schemas/next/ && cpy \\\"../packages/fdc3-context/schemas/context\\\" static/schemas/next/\",\n    \"copy-appd\": \"cpy \\\"../packages/fdc3-standard/src/app-directory/specification/*.schema.json\\\" \\\"static/schemas/next/\\\"\",\n    \"copy-workbench\": \"del-cli static/toolbox/fdc3-workbench && cpy \\\"../toolbox/fdc3-workbench/build/**\\\" static/toolbox/fdc3-workbench\",\n    \"copy-reference-ui\": \"del-cli static/toolbox/fdc3-reference-ui && cpy \\\"../toolbox/fdc3-for-web/reference-ui/dist/**\\\" static/toolbox/fdc3-reference-ui\",\n    \"copy-explained\": \"del-cli static/toolbox/fdc3-explained && cpy \\\"../toolbox/fdc3-explained\\\" ./static/toolbox/\",\n    \"copy-conformance\": \"del-cli static/toolbox/fdc3-conformance && cpy \\\"../toolbox/fdc3-conformance/dist/**\\\" static/toolbox/fdc3-conformance\",\n    \"replace-conformance-urls\": \"node replaceConformanceUrls.js\",\n    \"version\": \"cross-env-shell VERSION=2.2 npm run version-run\",\n    \"version-run\": \"cross-env-shell \\\"echo Creating version: \\\\$VERSION... && npm run prebuild && npm run docusaurus docs:version $VERSION && npm run version:docs-schema && npm run version:docs-replace && npm run version:schemas && npm run version:schemas-replace && npm run version:appd-replace\\\"\",\n    \"version:docs-schema\": \"cross-env-shell replace-in-files --string=/schemas/next --replacement=/schemas/$VERSION versioned_docs/version-$VERSION/*/*.md versioned_docs/version-$VERSION/*/*/*.md\",\n    \"version:docs-replace\": \"cross-env-shell replace-in-files --string='\\\\(next\\\\)' --replacement='\\\\($VERSION\\\\)' versioned_docs/version-$VERSION/*/*.md versioned_docs/version-$VERSION/*/*/*.md\",\n    \"version:schemas\": \"cross-env-shell cpy static/schemas/next/** static/schemas/$VERSION\",\n    \"version:schemas-replace\": \"cross-env-shell replace-in-files --string=/schemas/next --replacement=/schemas/$VERSION static/schemas/$VERSION/**/*.schema.json\",\n    \"version:appd-replace\": \"cross-env-shell replace-in-files --string=\\\"\\\"next\\\"\\\" --replacement=\\\"\\\"$VERSION\\\"\\\" static/schemas/$VERSION/appd.schema.json\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"docusaurus deploy\",\n    \"docusaurus\": \"docusaurus\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/core\": \"^3.7.0\",\n    \"@docusaurus/preset-classic\": \"^3.7.0\",\n    \"@docusaurus/theme-mermaid\": \"^3.7.0\",\n    \"@mermaid-js/layout-elk\": \"^0.1.9\",\n    \"clsx\": \"^1.2.1\",\n    \"cpy-cli\": \"4.2.0\",\n    \"cross-env\": \"^7.0.3\",\n    \"del-cli\": \"5.0.0\",\n    \"fs-extra\": \"^11.2.0\",\n    \"js-yaml\": \"^4.1.1\",\n    \"prism-react-renderer\": \"^2.4.1\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"replace-in-files-cli\": \"2.0.0\",\n    \"replace-json-property\": \"1.8.0\",\n    \"rimraf\": \"5.0.0\"\n  },\n  \"overrides\": {\n    \"serialize-javascript\": \"^7.0.5\",\n    \"webpack\": \"~5.105.0\"\n  }\n}"
  },
  {
    "path": "website/replaceConformanceUrls.js",
    "content": "#!/usr/bin/env node\n\n/**\n * Script to replace hard-coded fdc3.finos.org URLs in the conformance JSON file\n * with the appropriate base URL based on the environment.\n * \n * Priority:\n * 1. FDC3_BASE_URL environment variable (if set)\n * 2. Netlify DEPLOY_PRIME_URL (for preview/branch deploys)\n * 3. Default: https://fdc3.finos.org (for production)\n */\n\nconst fs = require('fs');\nconst path = require('path');\n\n// Determine the base URL to use\nfunction getBaseUrl() {\n    // Check for explicit FDC3_BASE_URL first\n    if (process.env.FDC3_BASE_URL) {\n        return process.env.FDC3_BASE_URL;\n    }\n\n    // Check for local development (docusaurus start)\n    if (process.env.NODE_ENV === 'development') {\n        console.log('Running in development mode');\n        return 'http://localhost:3000';\n    }\n\n    // For Netlify preview/branch deploys, use DEPLOY_PRIME_URL\n    if (process.env.DEPLOY_PRIME_URL && process.env.CONTEXT !== 'production') {\n        return process.env.DEPLOY_PRIME_URL;\n    }\n\n    // Default to production URL\n    return 'https://fdc3.finos.org';\n}\n\nconst baseUrl = getBaseUrl();\nconst filePath = path.join(__dirname, 'static/toolbox/fdc3-conformance/directories/website-conformance.v2.json');\n\n// Check if file exists\nif (!fs.existsSync(filePath)) {\n    console.warn(`Warning: Conformance file not found at ${filePath}. Skipping URL replacement.`);\n    console.warn(`  This is normal if conformance files haven't been built yet.`);\n    process.exit(0);\n}\n\n// Read the file\nlet content = fs.readFileSync(filePath, 'utf8');\n\n// Replace all instances of https://fdc3.finos.org with the base URL\nconst oldUrl = 'https://fdc3.finos.org';\nconst newContent = content.replace(new RegExp(oldUrl.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), baseUrl);\n\n// Only write if content changed\nif (content !== newContent) {\n    fs.writeFileSync(filePath, newContent, 'utf8');\n    console.log(`✓ Replaced ${oldUrl} with ${baseUrl} in conformance file`);\n    console.log(`  File: ${filePath}`);\n} else {\n    console.log(`✓ No URL replacements needed in conformance file`);\n}\n\n"
  },
  {
    "path": "website/schema2Markdown.js",
    "content": "const fse = require('fs-extra');\nconst yaml = require('js-yaml');\nconst path = require('path');\n\n\n\nfunction processProperty(propertyName, propertyDetails, required, currentSchemaFilePath, wrapInDetails = true) {\n    let markdownContent = '';\n\n    if (propertyName === 'type') {\n        //skip rendering the type property as it should be rendered at the top level\n        return markdownContent;\n    }   \n    \n    if (wrapInDetails) { markdownContent += \"<details>\\n\" };\n    markdownContent += `  <summary><code>${propertyName}</code>${required ? \" <strong>(required)</strong>\" : \"\"}</summary>\\n\\n`;\n    \n    //Note this block doesn't support inline property definitions... only base types and references, \n    //  it will not render an object or array defined inline beyond stating that it is one\n    if (propertyDetails.type) {\n        //if enum doesn't exist, its ignored\n        markdownContent += renderType(propertyDetails.type, propertyDetails.enum) + \"\\n\";\n\n        if (propertyDetails.type == \"object\") {\n            if (propertyDetails.properties && Object.entries(propertyDetails.properties).length > 0) {\n                markdownContent += '**Subproperties:**\\n\\n';\n                \n                for (const [subpropertyName, subpropertyDetails] of Object.entries(propertyDetails.properties)) {\n                    let subPropRequired = propertyDetails?.required?.includes(subpropertyName) ?? false;\n                    markdownContent += processProperty(subpropertyName, subpropertyDetails, subPropRequired, currentSchemaFilePath);\n                };\n            } else if (propertyDetails.additionalProperties && Object.entries(propertyDetails.additionalProperties).length > 0) {\n                markdownContent += processProperty(\"Additional Properties\", propertyDetails.additionalProperties, false, currentSchemaFilePath);\n            } else {\n                console.warn(`    No sub or additional properties defined for object property ${propertyName}`);\n            }\n        } else if (propertyDetails.type == \"array\") {\n            if (propertyDetails.items) {\n                markdownContent += processProperty(\"Items\", propertyDetails.items, false, currentSchemaFilePath);\n            } else {\n                console.warn(`    No type defined for array ${propertyName} items, property details:\\n${JSON.stringify(propertyDetails, null, 2)}`);\n            }\n        }\n    } else if (propertyDetails.$ref) {\n        markdownContent += renderRef(propertyDetails.$ref, currentSchemaFilePath) + \"\\n\";\n    } else if (propertyDetails.oneOf || propertyDetails.anyOf || propertyDetails.allOf) {\n        //this block assumes composite properties are composed base types or references, doesn't support inline object or array definitions\n        markdownContent += `${propertyDetails.oneOf ? \"**One of:**\" : propertyDetails.anyOf ? \"**Any of:**\" : propertyDetails.allOf ? \"**All of:**\" : \"\"}\\n\\n`;\n        const typeArr = propertyDetails.oneOf ?? propertyDetails.anyOf ?? propertyDetails.allOf;\n        markdownContent += `${typeArr.map((item) => {\n            if (item.type){\n                //if enum doesn't exist its ignored\n                return \"- \" + renderType(item.type, item.enum);\n            } else if (item.$ref) {\n                return \"- \" + renderRef(item.$ref, currentSchemaFilePath);\n            } else {\n                console.warn(`    Failed to determine property type for composite property ${propertyName}, property details:\\n${JSON.stringify(propertyDetails, null, 2)}`);\n            }\n        }).join('')}\\n`;\n    } else {\n        console.warn(`    Failed to determine property type for ${propertyName}, property details:\\n${JSON.stringify(propertyDetails, null, 2)}`);\n    }\n\n    if (propertyDetails.description != null) {\n        markdownContent += `${escapeExperimental(propertyDetails.description)}\\n\\n`;\n    }\n\n    if (propertyDetails.examples) {\n        propertyDetails.examples.forEach((example) => {\n            markdownContent += `\\n**Example**: \\n\\n`;\n            markdownContent += `\\`\\`\\`js\\n${JSON.stringify(example, null, 2)}\\n\\`\\`\\`\\n\\n`;\n        });\n    }\n\n    if (wrapInDetails) { markdownContent += \"</details>\" }\n    markdownContent += \"\\n\\n\";\n    \n    return markdownContent;\n}\n\nfunction renderType(type, optionalEnum) {\n    if (optionalEnum) {\n        return `**type**: \\`${type}\\` with values:\\n${optionalEnum.map((item) => `- \\`${item}\\``).join(',\\n')}\\n`;\n    } else {\n        return `**type**: \\`${type}\\`\\n`;\n    }\n}\n\nfunction renderEnum(ref) {\n    // for each item in ref, wrap it in backticks and join with a comma\n    return `**possible values**:\\n${ref.map((item) => `- \\`${item}\\``).join(',\\n')}\\n`;\n}\n\nfunction renderRef(contextRef, currentSchemaFilePath) {\n    //There are three main types of refs to handle:\n    // - refs to internal definitions\n    // - refs to other context schemas\n    // - refs to API types\n    //References should be treated like URLs, they are either resolved absolutely, relatively or relative to the current doc's root\n    //  most refs in current context docs are relative, but we can't assume they always will be\n    //  We may also being dealing with definitions with the current file or other files.\n\n    //Examples:\n    // - ../api/api.schema.json#/definitions/AppIdentifier\n    // - #/$defs/AgentResponseMeta\n    // - instrument.schema.json\n    // - context.schema.json#/definitions/BaseContext\n\n    const [filePath, objectPath] = contextRef.split('#'); // ../api/api.schema.json, /definitions/AppIdentifier\n    let schemaData = null;\n    let standardPart = null;\n    if (!filePath && objectPath) {\n        //its a path inside the current file\n        schemaData = retrieveSchemaFile(currentSchemaFilePath);\n\n        //render the content as it won't have its own page\n        const referencedSchemaData = retrievePathInSchema(schemaData, objectPath);\n        const referencedTitle = referencedSchemaData.title ?? \"\";\n        \n        return processProperty(referencedTitle, referencedSchemaData, false, currentSchemaFilePath, false);\n\n    } else {\n        //its a ref to a different file\n        schemaData = retrieveSchemaFile(filePath, currentSchemaFilePath);\n\n        //determine if the reference is to a different section, e.g. to the API schemas\n        standardPart = retrieveFolderName(filePath);\n\n        const title = retrieveTitleFromSchemaData(schemaData,objectPath);\n        const outputDocName = `${title.replace(/\\s+/g, '')}`;\n\n        if (!standardPart) {\n            //its either in an unknown part or the current part of the Standard\n\n            //handle the generic Context type as it doesn't have a reference page\n            if (title == \"Context\"){\n                return `**type**: [Context](/docs/next/context/spec#the-context-interface)\\n\\n`;\n            } else {\n                return `**type**: [${title}](${outputDocName})\\n`;\n            }\n        } else {\n            //custom handling for other standard parts...\n            return `**type**: ${standardPart}/${title}\\n`;\n\n            //TODO handle API schema refs \n            // - which are currently split across two different docs pages (Types and Metadata)\n            // - perhaps reunite these pages and just link to the resulting page.\n        }\n    }\n    \n    \n}\n\nfunction hasAllOf(allOfArray) {\n    return Array.isArray(allOfArray) && \n        allOfArray.length > 0 && \n        allOfArray[0] != null && \n        allOfArray[0].properties != null\n}\n\nfunction hasProperties(schema) {\n    return schema.properties != null;\n}\n\n// Function to generate Markdown content from JSON schema\nfunction generateObjectMD(schema, objectName, schemaFolderName, filePath) {\n    //If the schema doesn't contain a title, \n    // it may have been embedded in a definition who's name would have been passed in\n    title = schema.title ?? objectName;\n\n    let markdownContent = `# ${title}\\n\\n`;\n\n    if (schema.description != null) {\n        markdownContent += `${escapeExperimental(schema.description)}\\n\\n`; \n    }\n\n    //If the schema has a top level enum (e.g. API error schemas) then it needs rendering here.\n    if (schema.enum) {\n        markdownContent += renderEnum(schema.enum) + \"\\n\";\n    }\n\n    //if working on windows you may have the wrong slashes...\n    const workingPath = filePath.replaceAll(\"\\\\\",\"/\");\n    const url = schema.$id;\n    const docusaurusUrl = url.replace(\"https://fdc3.finos.org\", \"pathname://\");\n    const githubUrl = workingPath.includes('context') \n        ? workingPath.replace(\"static/schemas/next/\", `https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/`)\n        : workingPath.replace(\"static/schemas/next/\", `https://github.com/finos/FDC3/tree/main/packages/fdc3-schema/schemas/`);\n\n        markdownContent += `## Schema\\n\\n[${url}](${docusaurusUrl}) ([github](${githubUrl}))\\n\\n`;\n\n    if (hasAllOf(schema.allOf) || hasProperties(schema)) {\n        // Extract properties, required fields, and $ref from the first allOf object\n        let root = schema;\n        if (hasAllOf(schema.allOf)) {\n            root = schema.allOf[0];\n        }\n        \n        const properties = root.properties;\n        const requiredProperties = root.required;\n        const typeString = properties?.type?.const;\n        const ref = root.$ref;\n                \n        markdownContent += `## Type\\n\\n`;\n        markdownContent += `\\`${typeString}\\`\\n\\n`;\n        markdownContent += `## Properties\\n\\n`; \n\n        for (const [propertyName, propertyDetails] of Object.entries(properties)) {\n            if (propertyName != \"type\"){\n                const required = !!requiredProperties?.includes(propertyName);\n                markdownContent += processProperty(propertyName, propertyDetails, required, workingPath);\n            }\n        }\n\n        if (ref) {\n            markdownContent += `ref: ${ref}\\n\\n`;\n        }\n\n        if (schema.examples && schema.examples.length > 0) {\n            if (schema.examples.length > 1) {\n                markdownContent += `## Examples\\n\\n`;\n            } else {\n                markdownContent += `## Example\\n\\n`;\n            }\n            \n            schema.examples.forEach((example) => {\n                markdownContent += '```json\\n';\n                markdownContent += JSON.stringify(example, null, 2);\n                markdownContent += '\\n```\\n\\n';\n            });\n        }\n\n        const frontMatter = generateFrontMatter(title, schema.description);\n\n        // outputDocName must not contain any spaces\n        const outputDocName = `${title.replace(/\\s+/g, '')}`;\n        const outputDocsPath = `${schemaFolderName}/ref/${outputDocName}`;\n        const outputFilePath = `./docs/${schemaFolderName}/ref/${outputDocName}.md`;\n\n        fse.outputFileSync(outputFilePath, `---\\n${yaml.dump(frontMatter)}\\n---\\n\\n${markdownContent}`);\n\n        return outputDocsPath;\n    }\n}\n\nfunction escapeExperimental(text) {\n    return text.replace(/@experimental/g, '[@experimental](/docs/fdc3-compliance#experimental-features)');\n}\n\nfunction generateFrontMatter(title, description) {\n    return {\n        title: title,\n        sidebar_label: title,\n    };\n}\n\nfunction processSchemaFile(schemaFile, schemaFolderName) {\n    const schemaData = fse.readJSONSync(schemaFile);\n\n    // if there is allOf, then it is an object\n    const allOfArray = schemaData.allOf;\n    let sidebarItems = [];\n    if (Array.isArray(allOfArray) && allOfArray.length > 0) {\n        sidebarItems.push(generateObjectMD(schemaData, null, schemaFolderName, schemaFile));\n    }\n    if (schemaData.definitions) {\n        for (const [objectName, objectDetails] of Object.entries(schemaData.definitions)) {\n            sidebarItems.push(generateObjectMD(objectDetails, objectName, schemaFolderName, schemaFile));\n        }\n    }\n\n    return sidebarItems;\n}\n/**\n * Given a path to a schema file, retrieves the schema file contents.\n * If a currentFilePath is specified the path is resolved relative to it \n * (as it is assumed that the path to be resolved is relative to that file).\n * \n * Does not support retrieving schemas via a full URL.\n * \n * @param {string} schemaFilePath \n * @param {string} currentFilePath \n * @returns Contents of the referenced schema file\n */\nfunction retrieveSchemaFile (schemaFilePath, currentFilePath) {\n    let resolvedPath = schemaFilePath;\n\n    if (currentFilePath) {\n        //resolve the file path relative to the current file\n        const currentFilePathData = path.parse(currentFilePath);\n        const schemaFilePathData = path.parse(schemaFilePath);\n        const pathComponents = [];\n        if (currentFilePathData.dir) {pathComponents.push(currentFilePathData.dir);}\n        if (schemaFilePathData.dir) {pathComponents.push(schemaFilePathData.dir);}\n        pathComponents.push(schemaFilePathData.base);\n        resolvedPath = path.join(...pathComponents);\n    }\n    \n    //read the file\n    return fse.readJSONSync(resolvedPath);\n}\n\nfunction retrieveFolderName (schemaFilePath) {\n    const schemaFilePathData = path.parse(schemaFilePath);\n    //fix windows paths\n    const workingPath = schemaFilePathData.dir.replaceAll(\"\\\\\",\"/\");\n    const parts = workingPath.split(\"/\");\n    return parts[parts.length-1];\n}\n\n/**\n * Retrieve the content at a particular path in a schema object.\n * @param {*} schemaData \n * @param {*} pathInSchema \n * @returns \n */\nfunction retrievePathInSchema(schemaData, pathInSchema) {\n    let outputData = schemaData;\n    const pathComponents = pathInSchema.split(\"/\");\n    pathComponents.forEach((component) => {\n        if (component && outputData) { outputData = outputData[component]; }\n    });\n    if (!outputData){\n        console.error(`    Failed to retrieve path: ${pathInSchema} from schema data: ${JSON.stringify(schemaData, null, 2)}`);\n    }\n    return outputData;\n}\n\n/**\n * Retrieves the title element from a schema object, with an optional path \n * (e.g. to a definition) within that schema.\n * @param {*} schemaData \n * @param {*} pathInSchema \n * @returns \n */\nfunction retrieveTitleFromSchemaData(schemaData, pathInSchema) {\n    //if a path within the schema was specified, navigate to it\n    if (pathInSchema){\n        schemaData = retrievePathInSchema(schemaData, pathInSchema);\n    }\n    \n    if (schemaData?.title) {\n        return schemaData.title;\n    } else {\n        if (pathInSchema) {\n            console.warn(`    Reference: ${pathInSchema} didn't have a title in the provided schemaData, returning the name of the reference instead. schemaData: ${JSON.stringify(schemaData, null, 2)}`);\n            return pathInSchema.split('/').pop().split('.')[0];\n        } else {\n            console.error(`    Failed to retrieve title  from schemaData: ${JSON.stringify(schemaData, null, 2)}`);\n        }\n\n        return null;\n    }\n}\n\nfunction parseSchemaFolder(schemaFolderName) {\n    const schemaFolder = `./static/schemas/next/${schemaFolderName}`;\n    \n    console.debug(\"Parsing schema folder: \", schemaFolder);\n\n    // Read all files in the schema folder\n    const schemaFiles = fse.readdirSync(schemaFolder)\n        .filter(file => file.endsWith('.json'))\n        // nosemgrep\n        .map(file => path.join(schemaFolder, file));\n\n    // Process each schema file\n    let sidebarItems = [];\n    for (const schemaFile of schemaFiles) {\n        \n        if (path.basename(schemaFile) === \"context.schema.json\"){\n            console.log(`  Skipping ${schemaFile}`);\n        } else {\n            console.log(`  Processing schema File: ${schemaFile}`);\n            sidebarItems.push(processSchemaFile(schemaFile, schemaFolderName));\n        }\n    }\n\n    // filter out null values\n    return sidebarItems.flat().filter(item => item);\n}\n\nfunction main() {\n    console.log(\"Generating Context reference pages...\")\n    //generate markdown docs for the current schema versions in the current docs draft\n\n    let sidebarObject = fse.readJsonSync(`./sidebars.json`)    \n\n    let sidebarContextObject = {\n        \"type\": \"category\",\n        \"label\": \"Context Data Part\",\n        \"items\": [\"context/spec\"]\n    }\n\n    sidebarContextObject.items = sidebarContextObject.items.concat(parseSchemaFolder('context'));\n\n    if (sidebarObject.docs[\"FDC3 Standard\"] == null) {\n        sidebarObject.docs[\"FDC3 Standard\"] = [];\n    }\n\n    //replace existing element\n    let foundIt = false;\n    sidebarObject.docs[\"FDC3 Standard\"].map((elem) => {\n\n        if (elem.label == \"Context Data Part\"){\n            foundIt = true;\n            elem.items = sidebarContextObject.items;\n            console.log(\"Replaced content of 'Context Data Part' of website navigation.\");\n        }\n        \n    });\n\n    //or create it if not found\n    if (!foundIt){\n        console.warn(\"'Context Data Part' not found in website navigation, adding it as a new section...\");\n        sidebarObject.docs[\"FDC3 Standard\"].push(sidebarContextObject)\n    }\n    fse.outputJSONSync(\n        `./sidebars.json`,\n        sidebarObject, { spaces: 2 });\n\n}\n\nif (require.main === module) {\n    main();\n}\n"
  },
  {
    "path": "website/sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"why-fdc3\",\n      \"fdc3-charter\"\n    ],\n    \"FDC3 Standard\": [\n      \"fdc3-standard\",\n      \"fdc3-compliance\",\n      \"fdc3-glossary\",\n      \"references\",\n      {\n        \"type\": \"category\",\n        \"label\": \"API Part\",\n        \"items\": [\n          \"api/spec\",\n          \"api/supported-platforms\",\n          \"api/ref/GetAgent\",\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/PrivateChannel\",\n          \"api/ref/Types\",\n          \"api/ref/Metadata\",\n          \"api/ref/Errors\",\n          \"api/ref/Events\",\n          {\n            \"type\": \"category\",\n            \"label\": \"Desktop Agent Specs\",\n            \"items\": [\n              \"api/specs/preloadDesktopAgents\",\n              \"api/specs/browserResidentDesktopAgents\",\n              \"api/specs/webConnectionProtocol\",\n              \"api/specs/desktopAgentCommunicationProtocol\"\n            ]\n          },\n          {\n            \"type\": \"category\",\n            \"label\": \"Conformance Tests\",\n            \"items\": [\n              \"api/conformance/Conformance-Overview\",\n              \"api/conformance/Basic-Tests\",\n              \"api/conformance/App-Channel-Tests\",\n              \"api/conformance/User-Channel-Tests\",\n              \"api/conformance/Open-Tests\",\n              \"api/conformance/Intents-Tests\",\n              \"api/conformance/Metadata-Tests\"\n            ]\n          }\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"App Directory Part\",\n        \"items\": [\n          \"app-directory/overview\",\n          \"app-directory/spec\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Intents Part\",\n        \"items\": [\n          \"intents/spec\",\n          \"intents/ref/CreateInteraction\",\n          \"intents/ref/CreateOrUpdateProfile\",\n          \"intents/ref/SendChatMessage\",\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/StartEmail\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewChat\",\n          \"intents/ref/ViewContact\",\n          \"intents/ref/ViewHoldings\",\n          \"intents/ref/ViewInstrument\",\n          \"intents/ref/ViewInteractions\",\n          \"intents/ref/ViewMessages\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewOrders\",\n          \"intents/ref/ViewProfile\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewResearch\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Context Data Part\",\n        \"items\": [\n          \"context/spec\",\n          \"context/ref/Action\",\n          \"context/ref/Chart\",\n          \"context/ref/ChatInitSettings\",\n          \"context/ref/ChatMessage\",\n          \"context/ref/ChatRoom\",\n          \"context/ref/ChatSearchCriteria\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Country\",\n          \"context/ref/Currency\",\n          \"context/ref/Email\",\n          \"context/ref/FileAttachment\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Interaction\",\n          \"context/ref/Message\",\n          \"context/ref/Nothing\",\n          \"context/ref/Order\",\n          \"context/ref/OrderList\",\n          \"context/ref/Organization\",\n          \"context/ref/Portfolio\",\n          \"context/ref/Position\",\n          \"context/ref/Product\",\n          \"context/ref/TimeRange\",\n          \"context/ref/Trade\",\n          \"context/ref/TradeList\",\n          \"context/ref/TransactionResult\",\n          \"context/ref/Valuation\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Agent Bridging Part\",\n        \"items\": [\n          \"agent-bridging/spec\",\n          \"agent-bridging/ref/broadcast\",\n          \"agent-bridging/ref/findInstances\",\n          \"agent-bridging/ref/findIntent\",\n          \"agent-bridging/ref/findIntentsByContext\",\n          \"agent-bridging/ref/getAppMetadata\",\n          \"agent-bridging/ref/open\",\n          \"agent-bridging/ref/PrivateChannel.broadcast\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerAdded\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerRemoved\",\n          \"agent-bridging/ref/PrivateChannel.onAddContextListener\",\n          \"agent-bridging/ref/PrivateChannel.onDisconnect\",\n          \"agent-bridging/ref/PrivateChannel.onUnsubscribe\",\n          \"agent-bridging/ref/raiseIntent\"\n        ]\n      }\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-6\",\n      \"use-cases/uc-7\",\n      \"use-cases/uc-8\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-11\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/src/components/Benefits/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport Carousel1 from '../Carousel1';\nimport HomeSection from \"../HomeSection\";\nimport Callout from \"../Callout\";\n\nexport default function Benefits() {\n\treturn (\n\t\t<HomeSection reverse=\"true\">\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>What are the Benefits?</h2>\n\t\t\t</div>\n\t\t\t<Carousel1 minHeight=\"35rem\">\n\t\t\t\t<aside>\n\t\t\t\t\t<h2 className={styles.number}>1</h2>\n\t\t\t\t\t<h3 className={styles.title}>📇 Manage The Information Overload </h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tFinance is an information-dense environment.\n\t\t\t\t\t\tTypically, traders will use serveral different displays so that they can keep track of multiple information sources at once. FDC3 helps with this by sharing the \"context\" between multiple applications, so that they collectively track the topic the user is focused on.\n\t\t\t\t\t</p>\n\t\t\t\t</aside>\n\t\t\t\t<aside>\n\t\t\t\t\t<h2 className={styles.number}>2</h2>\n\t\t\t\t\t<h3 className={styles.title}>🏃‍♂️ Work Faster</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tFDC3 standardizes a way to call actions between applications (called \"intents\"). Applications can raise intents for other apps to resolve, extending each other's functionality. Instead of the user copy-and-pasting bits of data from one application to another, FDC3 makes sure the intents have the data they need to seamlessly transition activity between applications.\n\t\t\t\t\t</p>\n\t\t\t\t</aside>\n\t\t\t\t<aside>\n\t\t\t\t\t<h2 className={styles.number}>3</h2>\n\t\t\t\t\t<h3 className={styles.title}> 🖥️ Platform Agnostic</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tAs an open standard, FDC3 can be implemented on any platform and in any language. All that is required is a \"Desktop Agent\" that implements the FDC3 standard, which is responsible for co-ordinating application interactions. (For a list of open source and proprietary desktop agents, see \"Platform providers\" here.) FDC3 is successfully running on Web and Native platforms in financial institutions around the world.\n\t\t\t\t\t</p>\n\t\t\t\t</aside>\n\t\t\t\t<aside>\n\t\t\t\t\t<h2 className={styles.number}>4</h2>\n\t\t\t\t\t<h3 className={styles.title}>🔌 End the Integration Nightmare</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tBy providing support for FDC3, vendors and financial organizations alike can avoid the bilateral or trilateral integration projects that plague desktop app roll-out, cause vendor lock-in and result in a slow pace of change on the Financial Services desktop.\n\t\t\t\t\t</p>\n\t\t\t\t</aside>\n\t\t\t\t<aside>\n\t\t\t\t\t<h2 className={styles.number}>5</h2>\n\t\t\t\t\t<h3 className={styles.title}>👐 Open Standards Innovation</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tFDC3 is developed collaboratively by a consortium of industry participants including banks, agent vendors, app developers and FinTech firms. By design, FDC3 is open to extension. We have an active community working on growing and improving the standard with new data and intents.\n\t\t\t\t\t</p>\n\t\t\t\t</aside>\n\t\t\t</Carousel1>\n\t\t</HomeSection>\n\n\n\t)\n}\n\n"
  },
  {
    "path": "website/src/components/Benefits/styles.module.css",
    "content": ".title {\n\tfont-family: Rokkitt;\n\tfont-size: 3rem;\n\tfont-weight: 400;\n\ttext-align: center;\n}\n\n.innerAside {\n\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 310 310\" fill=\"%23ace\"><path d=\"M102.91 50.54 24.57 155v104.46h104.45V155H76.79l55.96-74.61zm182.52 29.85-29.84-29.85L177.25 155v104.46H281.7V155h-52.23z\"></path></svg>');\n\tbackground-position: 0 0;\n\tbackground-repeat: no-repeat;\n}\n\n.innerAside h2 {\n\tfont-weight: 800;\n\tcolor: black;\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n\tline-height: 1.1;\n\ttext-wrap: wrap;\n}\n\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\n\nhtml[data-theme=dark] .innerAside h2 {\n\tcolor: white;\n}\n\n.number {\n\tfont-family: 'rokkitt';\n\ttext-align: center;\n\tfont-size: 5rem;\n\tfont-weight: 800;\n}"
  },
  {
    "path": "website/src/components/Callout/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\n\n\nexport default function Callout({children}) {\n\treturn (<div>{children}</div> )\n}"
  },
  {
    "path": "website/src/components/Callout/styles.module.css",
    "content": ""
  },
  {
    "path": "website/src/components/Carousel1/index.js",
    "content": "import React, { useEffect, useState } from 'react'\nimport styles from './styles.module.css'\n\nconst Carousel1 = ({minHeight = \"50rem\", children}) => {\n\n\tconst [currentIndex, setCurrentIndex] = useState(0)\n\tconst [length, setLength] = useState(children.length)\n\n\n\tconst next = () => {\n\t\tif (currentIndex < (length - 1)) {\n\t\t\tsetCurrentIndex(prevState => prevState + 1)\n\t\t}\n\t}\n\n\tconst prev = () => {\n\t\tif (currentIndex > 0) {\n\t\t\tsetCurrentIndex(prevState => prevState - 1)\n\t\t}\n\t}\n\n\tconst hasNext = () => (currentIndex < (length - 1))\n\n\tconst hasPrev = () => (currentIndex > 0)\n\n\tconst prevClass = styles.leftArrow + \" \" + (hasPrev() ? styles.active : styles.inactive)\n\n\tconst nextClass = styles.rightArrow + \" \" + (hasNext() ? styles.active : styles.inactive)\n\n\t// Set the length to match current children from props\n\tuseEffect(() => {\n\t\tsetLength(children.length)\n\t}, [children])\n\n\treturn (\n\t\t<div className={styles.carouselContainer}>\n\t\t\t<div className={styles.carouselWrapper}>\n\t\t\t\t{\n\t\t\t\t\tchildren.map((v, i) => <div className={currentIndex == i ? styles.show : styles.hide } style={{minHeight: minHeight}}>{v}</div>)\n\t\t\t\t}\n\t\t\t</div>\n\t\t\t<div className={styles.controls}>\n\t\t\t\t<button className={prevClass} onClick={prev}>\n\t\t\t\t\t&lt; PREV\n\t\t\t\t</button>\n\t\t\t\t<button className={nextClass} onClick={next}>\n\t\t\t\t\tNEXT &gt;\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default Carousel1"
  },
  {
    "path": "website/src/components/Carousel1/styles.module.css",
    "content": ".carouselContainer {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.carouselWrapper {\n\theight: auto;\n}\n\n.controls {\n\tdisplay: flex;\n}\n\n.leftArrow, .rightArrow {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttext-align: center;\n\tflex-basis: 45%;\n}\n\n.leftArrow {\n\talign-self: flex-start;\n}\n\n.rightArrow {\n\talign-self: flex-end;\n}\n\n\n.show {\n\tmin-height: 50rem;\n}\n\n.hide {\n\tdisplay: none;\n}\n\n.inactive {\n\tcolor: #0086bf44;\n}"
  },
  {
    "path": "website/src/components/Conformance/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport HomeSection2 from \"../HomeSection2\";\nimport ConformanceShowcase from \"../ConformanceShowcase\";\n\nexport default function Conformance() {\n\treturn (\n\t\t<HomeSection2 alt=\"true\">\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<a id=\"conformance\"></a>\n\t\t\t\t<h2 >FDC3 Conformance</h2>\n\t\t\t\t<p className={styles.explanation}>FDC3 has a <a href=\"https://github.com/finos/FDC3-Conformance-Framework\">conformance framework</a> that works to ensure compatibility with the standard. </p>\n\t\t\t</div>\n\t\t\t<ConformanceShowcase />\n\t\t\t<div>\n\t\t\t\t<a className={styles.cta} href=\"https://github.com/finos/FDC3-Conformance-Framework\">CONFORMANCE FRAMEWORK</a>\n\t\t\t</div>\n\t\t</HomeSection2>\n\t)\n}\n"
  },
  {
    "path": "website/src/components/Conformance/styles.module.css",
    "content": ".cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: #0086bf;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n}\n\n.innerAside {\n\tmargin: auto;\n\tfont-size: 3rem;\n\tcolor: black;\n\ttext-align: center;\n}\n\n.innerAside h2 {\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n\tfont-weight: bold;\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\n\n.right {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n}\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n\ttext-align: center;\n}\n\n.logo {\n\twidth: 15rem;\n}\n\n.explanation {\n\tfont-size: 1.5rem;\n\ttext-align: center;\n}"
  },
  {
    "path": "website/src/components/ConformanceShowcase/index.js",
    "content": "import community from \"../../../data/community.json\";\nimport { image1 } from \"../UseCases/styles.module.css\";\nconst React = require('react');\nimport styles from './styles.module.css'\n\nexport default () => {\n\n\tlet relevant = community.filter(c => c.conformance)\n\n\tlet badges = [\"/img/community/certified-1.2.png\", \"/img/community/certified-2.0.png\"]\n\n\tlet publishers = relevant.map(r => r.publisher).filter((x, i, a) => a.indexOf(x) === i).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))\n\n\tfunction Publisher({name}) {\n\t\tconst p = relevant.find(q => q.publisher == name)\n\t\t\n\t\treturn (<a href={p.infoLink} title={p.publisher}><img className={styles.conformanceImage} src={p.image} /></a>)\n\t}\n\n\tfunction ConformanceItem({ publisher, badge }) {\n\t\tconst pubs = relevant.filter(q => (q.publisher == publisher))\n\t\tconst details = pubs.flatMap(p => p.conformance.filter(c => c.src == badge))\n\t\tconst items = details.flatMap(d => d.items ?? [])\n\n\t\treturn (items.map( i => <div className={styles.conformanceText}><p>{i.text}</p><p><a href={i.link}>Read More</a></p></div>))\t\t\n\t}\n\n\treturn <div className={styles.conformanceShowcase}>\n\t\t<table>\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th></th>\n\t\t\t\t\t{\n\t\t\t\t\t\tbadges.map(b => <th><img className={styles.badgeImage} src={b} /></th>)\n\t\t\t\t\t}\n\t\t\t\t</tr>\n\t\t\t\t{\n\t\t\t\t\tpublishers.map(p =>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td><Publisher name={p} /></td>\n\t\t\t\t\t\t\t<td><ConformanceItem publisher={p} badge={badges[0]} /></td>\n\t\t\t\t\t\t\t<td><ConformanceItem publisher={p} badge={badges[1]} /></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t</thead>\n\t\t</table>\n\t</div>\n}\n\n\n"
  },
  {
    "path": "website/src/components/ConformanceShowcase/styles.module.css",
    "content": ".conformanceShowcase {\n\toverflow: scroll;\n}\n\n.conformanceShowcase table {\n\tbackground-color: #ffffff99;\n\tmax-width: 1200px;\n\tmargin: auto;\n}\n\n.conformanceShowcase td {\n}\n\n.conformanceShowcaseItem {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    text-align: left;\n}\n\n.conformanceText {\n    margin: 2rem;\n}\n\n.badgeImage {\n\tmax-width: 6rem;\n}\n\n.conformanceImage {\n\tmax-width: 10rem;\n}"
  },
  {
    "path": "website/src/components/Container/index.js",
    "content": "const React = require('react');\n\nexport default (props) => {\n    return (\n        <main>\n            <div className=\"container padding-top--md padding-bottom--lg\">\n                <div className=\"docMainWrapper wrapper\">\n                    {props.children}\n                </div>\n            </div>\n        </main>)\n}"
  },
  {
    "path": "website/src/components/Feature/index.js",
    "content": "const React = require('react');\n\nexport default (props) => {\n    return (<div  className=\"featureShowcaseSection padding-top--lg padding-bottom--lg\" style={{textAlign: 'center'}}>\n        {props.children}\n    </div>)\n}"
  },
  {
    "path": "website/src/components/GetInvolved/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport HomeSection from \"../HomeSection\";\nimport One from '../../../data/get-involved/1.mdx'\nimport Two from '../../../data/get-involved/2.mdx'\nimport Three from '../../../data/get-involved/3.mdx'\nimport Four from '../../../data/get-involved/4.mdx'\nimport Five from '../../../data/get-involved/5.mdx'\nimport GridBlock from \"../GridBlock\";\nimport Carousel1 from '../Carousel1';\n\n\nexport default function Benefits() {\n\treturn (\n\t\t<HomeSection>\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>Get Involved</h2>\n\t\t\t\t<p>\n\t\t\t\t<a href=\"mailto:fdc3+subscribe@finos.org\">Join the General List</a> to stay up to date with the project.\n\t\t\t\t </p>\n\n\t\t\t</div>\n\t\t\t<Carousel1  minHeight=\"40rem\">\n\t\t\t\t<div className={styles.item}><h1>1</h1><One /></div> \n\t\t\t\t<div className={styles.item}><h1>2</h1><Two /></div> \n\t\t\t\t<div className={styles.item}><h1>3</h1><Three /></div> \n\t\t\t\t<div className={styles.item}><h1>4</h1><Four /></div> \n\t\t\t\t<div className={styles.item}><h1>5</h1><Five /></div> \n\t\t\t</Carousel1>\n\t\t</HomeSection>\n\t)\n}\n\n"
  },
  {
    "path": "website/src/components/GetInvolved/styles.module.css",
    "content": ".benefit {\n\t\n}\n\n.title {\n\tfont-family: 'Electrolize';\n\tfont-size: 3rem;\n}\n\n.innerAside {\n\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"%23ace\"><path d=\"m22.66 10.25-8-7A1 1 0 0 0 13 4v3.03C3.56 7.54 1 15.33 1 20c0 1.05 1.42 1.39 1.89.45.67-1.34 3.92-5.05 10.11-5.42V18a1 1 0 0 0 1.66.75l8-7c.45-.4.45-1.11 0-1.51ZM15 15.8V14a1 1 0 0 0-1-1c-4.7 0-8.28 1.74-10.53 3.68C4.34 13.42 6.85 9 14 9a1 1 0 0 0 1-1V6.2l5.48 4.8L15 15.8Z\"/></svg>');\n\tbackground-repeat: no-repeat;\n\tbackground-position: 0 40;\n}\n\n.innerAside h2 {\n\tfont-weight: bold;\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n\tline-height: 1.1;\t\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\nhtml[data-theme=dark] .innerAside {\n\tcolor: white;\n}\n\n.item {\n\tborder: 1px dashed black;\n\tpadding: 1rem;\n\tmin-height: 40rem;\n}\n\n\nhtml[data-theme=dark] .item {\n\tborder: 1px dashed white;\n}\n\n\n\n.item h1 {\n\theight: 5rem;\n\ttext-align: center;\n\tfont-weight: 800;\n\tfont-family: 'Rokkitt';\n\tfont-size: 5rem;\n}\n\n.item h2 {\n\ttext-align: center;\n\tfont-weight: 400;\n\tfont-family: 'Rokkitt';\n\tfont-size: 2rem;\n}\n"
  },
  {
    "path": "website/src/components/GridBlock/index.js",
    "content": "const React = require('react');\n\nexport default ({items}) => {\n\n    return (\n      <div className=\"gridBlock\">\n        {\n          items.map((sl, key) =>\n            <div className=\"blockElement fiveByGridBlock\" key={key}>\n              <div className=\"blockContent\">\n                {sl}\n              </div>\n            </div>\n          )\n        }\n      </div>\n    )\n  }"
  },
  {
    "path": "website/src/components/HomeSection/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport MonoIcon from '../MonoIcon'\n\n// left, right panels, a call to action adn a footer icon\nexport default ({children, alt, reverse}) => {\n\treturn (\n\t\t<section className={alt ? styles.homeSectionAlt : styles.homeSection}>\n\t\t\t<div className={reverse ? styles.innerFlexReverse : styles.innerFlex}>\n\t\t\t\t<div className={styles.item}>\n\t\t\t\t\t{ children[0] }\n\t\t\t\t</div>\n\t\t\t\t<div className={styles.item}>\n\t\t\t\t\t{ children[1] }\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div className={styles.callToAction}>\n\t\t\t\t{ children[2] }\n\t\t\t</div>\n\t\t\t\n\t\t\t<div className={styles.footerImage}>\n\t\t\t\t<MonoIcon />\n\t\t\t</div>\n\t\t</section> )\n}\n\n\n"
  },
  {
    "path": "website/src/components/HomeSection/styles.module.css",
    "content": "section.homeSection, section.homeSectionAlt {\n\tmargin-top: 5rem;\n\tpadding-top: 5rem;\n\tpadding-bottom: 5rem;\n\tclip-path: polygon(0 3rem, 100% 0, 100% 100%, 0 calc(100% - 3rem));\n\toverflow: hidden;\n}\n\nsection.homeSectionAlt {\n\tbackground-color: #ace;\n\tcolor: black;\n}\n\ndiv.innerFlex, div.innerFlexReverse {\n\tdisplay: flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\twidth: 100%;\n\tmax-width: 1200px;\n\tmargin: auto;\n\tfont-size: 1.5rem;\n}\n\ndiv.innerFlexReverse {\n\tflex-direction: row-reverse;\n}\n\ndiv.item {\n\tpadding: 20px;\n\tflex-basis: 20rem;\n\tflex-grow: 1;\n\tflex-shrink: 0;\n}\n\ndiv.footerImage {\n\twidth: 3rem;\n\tmargin: auto;\n\tmargin-top: 3rem;\n}\n\ndiv.callToAction {\n\tmargin: 2rem auto;\n\tfont-size: 2rem;\n\ttext-align: center;\n}"
  },
  {
    "path": "website/src/components/HomeSection2/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport MonoIcon from '../MonoIcon'\n\n// title, central panel, a call to action adn a footer icon\nexport default ({ children, alt }) => {\n\treturn (\n\t\t<section className={alt ? styles.homeSectionAlt : styles.homeSection}>\n\t\t\t<div className={styles.title}>\n\t\t\t\t{children[0]}\n\t\t\t</div>\n\n\t\t\t<div className={styles.main}>\n\t\t\t\t{children[1]}\n\t\t\t</div>\n\n\t\t\t<div className={styles.callToAction}>\n\t\t\t\t{children[2]}\n\t\t\t</div>\n\n\t\t\t<div className={styles.footerImage}>\n\t\t\t\t<MonoIcon />\n\t\t\t</div>\n\t\t</section>)\n}\n\n\n"
  },
  {
    "path": "website/src/components/HomeSection2/styles.module.css",
    "content": "section.homeSection, \nsection.homeSectionAlt {\n\tmargin-top: 5rem;\n\tpadding-top: 5rem;\n\tpadding-bottom: 5rem;\n\tclip-path: polygon(0 3rem, 100% 0, 100% 100%, 0 calc(100% - 3rem));\n\toverflow: hidden;\n}\n\nsection.homeSectionAlt {\n\tbackground-color: #ace;\n\tcolor: black;\n}\n\n\n.title {\n\tmargin: auto;\n\tmax-width: 1200px;\n}\n\ndiv.innerFlex {\n\tdisplay: flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\twidth: 100%;\n\tmax-width: 1200px;\n\tmargin: auto;\n\tfont-size: 1.5rem;\n}\n\n\ndiv.item {\n\tpadding: 20px;\n}\n\ndiv.footerImage {\n\twidth: 3rem;\n\tmargin: auto;\n}\n\ndiv.callToAction {\n\tmargin: 2rem auto;\n\tfont-size: 2rem;\n\ttext-align: center;\n}\n\ndiv.main {\n\tmargin: auto;\n}"
  },
  {
    "path": "website/src/components/HomeSplash/index.js",
    "content": "\nconst React = require('react');\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\n\nexport default (props) => {\n\n    const context = useDocusaurusContext();\n    const siteConfig = context.siteConfig;\n    const repoUrl = siteConfig.customFields.repoUrl;\n  \n    const SplashContainer = props => (\n      <div className=\"homeContainer\">\n        <div className=\"homeSplashFade\">\n          <div className=\"wrapper homeWrapper\">{props.children}</div>\n        </div>\n      </div>\n    );\n  \n    const Logo = props => (\n      <div className=\"projectLogo\">\n        <img src={props.img_src} alt=\"Project Logo\" />\n      </div>\n    );\n  \n    const ProjectTitle = () => (\n      <div className=\"projectTitle\">\n        {/*siteConfig.title*/}\n        <small>{siteConfig.tagline}</small>\n      </div>\n      \n    );\n  \n    const PromoSection = props => (\n      <div className=\"section promoSection\">\n        <div className=\"promoRow\">\n          <div className=\"pluginRowBlock\">{props.children}</div>\n        </div>\n      </div>\n    );\n  \n    const Button = props => (\n      <div className=\"pluginWrapper buttonWrapper\">\n        <a className=\"button\" href={props.href} target={props.target}>\n          {props.children}\n        </a>\n      </div>\n    );\n  \n    return (\n      <SplashContainer>\n          <div className=\"inner\">\n                <img src=\"/img/fdc3-logo-2019.png\" aria-label=\"FDC3\" role=\"heading\" aria-level=\"1\" />\n                <ProjectTitle siteConfig={siteConfig} />\n                <PromoSection>\n                  <Button href=\"/docs/fdc3-intro\">Get Started</Button>\n                  <Button href={repoUrl}>GitHub</Button>\n                </PromoSection>\n              </div>\n      </SplashContainer>\n    );\n  }\n  "
  },
  {
    "path": "website/src/components/ImageBullet/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\n\nexport default ({children, image, alt}) => {\n    return <div className={styles.columns}>\n    \t<div className={styles.left}>\n\t        <img src={image} alt={alt} />\n    \t</div>\n        <div className={styles.right}>\n            {children}\n        </div>\n    </div>\n}"
  },
  {
    "path": "website/src/components/ImageBullet/styles.module.css",
    "content": ".columns {\n\tdisplay: flex;\n\tpadding-bottom: 1rem;\n\talign-items: center;\n\tgap: 1rem;\n}\n\n.left {\n\tflex-basis: 5rem;\n\tflex-shrink: 0;\n\tborder-radius: 2.5rem;\n\theight: 5rem;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.left img {\n\tpadding: 0;\n\tmargin: 0;\n}\n\n\nhtml[data-theme=dark] .left {\n\tbackground: #fff;\n}\n\n\n\n.right {\n\tflex-grow: 1;\n}"
  },
  {
    "path": "website/src/components/MonoIcon/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\n\n\n\nexport default function Icon() {\n\n\treturn (\n\t\t<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" x=\"0px\" y=\"0px\"\n\t\t\tviewBox=\"0 0 428.27 483.04\">\n\t\t\t\n\t\t\t<g>\n\t\t\t\t<path className={styles.fill} d=\"M428.27,363.7v-234L239.55,238.65c0.11,0.99,0.58,1.85,0.58,2.87c0,11.73-7.91,21.26-18.57,24.5v217.03\n\t\tL428.27,363.7L428.27,363.7z\"/>\n\t\t\t\t<path className={styles.fill} d=\"M234.38,225.9l186.09-107.44v-0.58L214.13,0L7.8,117.89v0.58L193.89,225.9c4.75-6.15,11.86-10.38,20.24-10.38\n\t\tC222.52,215.52,229.63,219.75,234.38,225.9L234.38,225.9z\"/>\n\t\t\t\t<path className={styles.fill} d=\"M188.72,238.65L0,129.69v234l206.71,119.34V266.02c-10.67-3.24-18.57-12.77-18.57-24.5\n\t\tC188.14,240.5,188.6,239.64,188.72,238.65L188.72,238.65z\"/>\n\t\t\t</g>\n\t\t</svg>)\n}\n"
  },
  {
    "path": "website/src/components/MonoIcon/styles.module.css",
    "content": ".fill {\n\tfill: black;\n}\n\nhtml[data-theme=dark] .fill {\n\tfill: white;\n}\n"
  },
  {
    "path": "website/src/components/NewSplashTop/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport TypeText from \"../TypeText\";\n\nexport default function NewSplashTop() {\n\treturn (\n\n\t\t<section className={styles.nst}>\n\t\t\t<svg className={styles.logo} version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" x=\"0px\" y=\"0px\"\n\t\t\t\tviewBox=\"-10 -10 465 683.04\">\n\t\t\t\t<g>\n\t\t\t\t\t<path className={styles.st0} d=\"M428.27,363.7v-234L239.55,238.65c0.11,0.99,0.58,1.85,0.58,2.87c0,11.73-7.91,21.26-18.57,24.5v217.03\n\t\tL428.27,363.7L428.27,363.7z\"/>\n\n\t\t\t\t\t<path className={styles.st1} d=\"M234.38,225.9l186.09-107.44v-0.58L214.13,0L7.8,117.89v0.58L193.89,225.9c4.75-6.15,11.86-10.38,20.24-10.38\n\t\tC222.52,215.52,229.63,219.75,234.38,225.9L234.38,225.9z\"/>\n\n\t\t\t\t\t<path className={styles.st2} d=\"M188.72,238.65L0,129.69v234l206.71,119.34V266.02c-10.67-3.24-18.57-12.77-18.57-24.5\n\t\tC188.14,240.5,188.6,239.64,188.72,238.65L188.72,238.65z\"/>\n\t\t\t\t</g>\n\n\t\t\t\t<g style={{transform: \"translate(5px, 500px)\"}}>\n\t\t\t\t\t<path className={styles._3} d=\"M402.38,83.71c18.34,0,29.62-11.4,29.62-26.92v-0.24c0-15.29-10.93-21.17-22.09-23.05l20.8-19.88V0H375.1\n\t\tv15.51h32.34L387.8,35.27l2.82,11.53h7.53c10.11,0,16.11,3.76,16.11,10.47v0.24c0,6.12-4.82,10-11.64,10\n\t\tc-8.35,0-14.23-3.53-19.87-9.88l-12.46,11.88C377.33,77.84,387.57,83.71,402.38,83.71L402.38,83.71z\"/>\n\t\t\t\t\t<path className={styles._f} d=\"M0,125.12h21.44V75.04h62.03V55.53H21.44V21.61h69.94V2.11H0V125.12L0,125.12z\" />\n\t\t\t\t\t<path className={styles._d} d=\"M136.72,105.61v-84h24.25\n\t\tc6.44,0,12.3,1.06,17.57,3.18c5.27,2.12,9.75,5.03,13.44,8.74c3.69,3.71,6.56,8.15,8.61,13.32c2.05,5.18,3.08,10.76,3.08,16.76\n\t\tv0.35c0,6-1.03,11.56-3.08,16.68c-2.05,5.12-4.92,9.53-8.61,13.24c-3.69,3.71-8.17,6.59-13.44,8.65\n\t\tc-5.27,2.06-11.13,3.09-17.57,3.09H136.72L136.72,105.61z  M115.28,125.12h45.87c9.6,0,18.42-1.58,26.45-4.75\n\t\tc8.02-3.16,14.94-7.5,20.74-13c5.8-5.5,10.28-12.01,13.44-19.51c3.16-7.5,4.74-15.58,4.74-24.25v-0.35\n\t\tc0-8.67-1.58-16.72-4.74-24.16c-3.16-7.44-7.64-13.91-13.44-19.42c-5.8-5.51-12.71-9.81-20.74-12.92\n\t\tc-8.03-3.1-16.84-4.66-26.45-4.66h-45.87V125.12L115.28,125.12\"/>\n\t\t\t\t\t<path className={styles._c} d=\"\n\t\t M325.71,125.73c4.74-0.99,9.11-2.46,13.09-4.39\n\t\tc3.98-1.93,7.7-4.22,11.16-6.85c3.45-2.64,6.77-5.65,9.93-9.05l-13.88-14.06c-5.27,4.92-10.6,8.82-15.99,11.69\n\t\tc-5.39,2.87-11.83,4.3-19.33,4.3c-5.86,0-11.28-1.14-16.26-3.43c-4.98-2.29-9.29-5.42-12.92-9.4c-3.63-3.98-6.45-8.64-8.44-13.97\n\t\tc-1.99-5.33-2.99-10.98-2.99-16.96v-0.35c0-5.97,0.99-11.6,2.99-16.87c1.99-5.27,4.8-9.87,8.44-13.79\n\t\tc3.63-3.92,7.93-7.03,12.92-9.31c4.98-2.28,10.4-3.43,16.26-3.43c7.03,0,13.29,1.41,18.8,4.22c5.51,2.81,10.72,6.5,15.64,11.07\n\t\tl13.88-15.99c-2.93-2.81-6.04-5.39-9.31-7.73c-3.28-2.34-6.85-4.36-10.72-6.06c-3.87-1.7-8.11-3.01-12.74-3.95\n\t\tC321.61,0.47,316.49,0,310.86,0c-9.37,0-17.92,1.67-25.66,5.01c-7.73,3.34-14.43,7.91-20.09,13.71\n\t\tc-5.66,5.8-10.05,12.54-13.18,20.21c-3.13,7.67-4.69,15.9-4.69,24.69v0.35c0,8.79,1.59,17.05,4.78,24.78\n\t\tc3.19,7.73,7.58,14.44,13.18,20.12c5.6,5.68,12.2,10.17,19.82,13.44c7.61,3.28,15.93,4.92,24.95,4.92\n\t\tC315.72,127.23,320.97,126.73,325.71,125.73L325.71,125.73z\"/>\n\n\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t\t\n\t\t\t<TypeText>Financial Desktop Connectivity and Collaboration Consortium</TypeText>\n\t\t</section>\n\t)\n}"
  },
  {
    "path": "website/src/components/NewSplashTop/styles.module.css",
    "content": "section.nst {\n\tmargin: auto;\n\tmax-width: 1200px;\n\ttext-align: center;\n}\n\nsvg.text {\n\t\n}\n\nsvg.logo {\n\theight: calc(70vh);\n\twidth: 100%;\n}\n\n@keyframes change {\n\t100% {\n\t\tstroke-dashoffset: 1000;\n\t}\t\n\t0% {\n\t\tfill: white;\n\t\tstroke: black;\n\t\tstroke-dashoffset: 0;\n\t}\n}\n\n@keyframes change-dark {\n\t100% {\n\t\tstroke-dashoffset: 1000;\n\t}\t\n\t0% {\n\t\tfill: black;\n\t\tstroke: white;\n\t\tstroke-dashoffset: 0;\n\t}\n}\n\n.st0,\n.st1,\n.st2,\n._f,\n._d,\n._c,\n._3 {\n\tanimation-direction: normal;\n\tanimation-duration: 4s;\n\tanimation-name: change; \n\tanimation-timing-function: ease-in-out;\n\tanimation-fill-mode: both;\n\tfill: black;\n\topacity: 1;\n\tstroke: black;\n\tstroke-width: 5px;\n\tstroke-dasharray: 1000;\n}\n\n.st1,\n._f,\n._d {\n\tanimation-duration: 4.2s;\n\tanimation-delay: .3s\n}\n\n.st2,\n._3 {\n\tanimation-duration: 3.5s;\n}\n\n\n.st0 {\n\tfill: #0054A6;\n}\n\n.st1 {\n\tfill: #5D93CD;\n}\n\n.st2 {\n\tfill: black;\n}\n\nhtml[data-theme=dark] .st2,\nhtml[data-theme=dark] ._f,\nhtml[data-theme=dark] ._d,\nhtml[data-theme=dark] ._c,\nhtml[data-theme=dark] ._3 {\n  fill: white;\t\n}\n\nhtml[data-theme=dark] .st0,\nhtml[data-theme=dark] .st1,\nhtml[data-theme=dark] .st2,\nhtml[data-theme=dark] ._f,\nhtml[data-theme=dark] ._d,\nhtml[data-theme=dark] ._c,\nhtml[data-theme=dark] ._3 {\n  animation-name: change-dark; \n}\n\ndiv.footerImage {\n\twidth: 3rem;\n\tmargin: auto;\n}"
  },
  {
    "path": "website/src/components/Parts/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport Carousel1 from '../Carousel1';\nimport HomeSection from \"../HomeSection\";\nimport Callout from \"../Callout\";\n\nexport default function Parts() {\n\treturn (\n\t\t<HomeSection alt=\"true\" reverse=\"true\">\n\t\t\t<div className={styles.innerAside}> \n\t\t\t\t<h2>The Standard</h2>\n\t\t\t\t<p className={styles.strap}>The FDC3 standard consists of five main parts...</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<Carousel1  minHeight=\"30rem\">\n\t\t\t\t\t<aside className={styles.part}>\n\t\t\t\t\t\t<h1>1</h1>\n\t\t\t\t\t\t<h2 className={styles.title}>The API</h2>\n\t\t\t\t\t\t<div className={styles.image}><img alt=\"\" src=\"/img/feature-api.svg\" /></div>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tCreate a consistent developer experience by adhering to the <a href=\"/docs/api/spec\">API standard</a>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</aside>\n\t\t\t\t\t<aside className={styles.part}>\n\t\t\t\t\t\t<h1>2</h1>\n\t\t\t\t\t\t<h2 className={styles.title}>Intents</h2>\n\t\t\t\t\t\t<div className={styles.image}><img alt=\"\" src=\"/img/feature-intents.svg\" /></div>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tUse <a href=\"/docs/intents/spec\">standardized verbs</a> to instruct other apps to take an action\n\t\t\t\t\t\t</p>\t\n\t\t\t\t\t</aside>\n\t\t\t\t\t<aside className={styles.part}>\n\t\t\t\t\t\t<h1>3</h1>\n\t\t\t\t\t\t<h2 className={styles.title}>Context Data</h2>\n\t\t\t\t\t\t<div className={styles.image}><img alt=\"\" src=\"/img/feature-context.svg\" /></div>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tShare <a href=\"/docs/context/spec\">context</a> between apps to eliminate re-keying and streamline workflow\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</aside>\n\t\t\t\t\t<aside className={styles.part}>\n\t\t\t\t\t\t<h1>4</h1>\n\t\t\t\t\t\t<h2 className={styles.title}>App Directory</h2>\n\t\t\t\t\t\t<div className={styles.image}><img alt=\"\" src=\"/img/feature-appd.svg\" /></div>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tDiscover trusted apps that can take part in a FDC3 workflow using an <a href=\"/docs/app-directory/overview\">App directory</a>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</aside>\n\t\t\t\t\t<aside className={styles.part}>\n\t\t\t\t\t\t<h1>5</h1>\n\t\t\t\t\t\t<h2 className={styles.title}>Agent Bridging</h2>\n\t\t\t\t\t\t<div className={styles.image}><img alt=\"\" src=\"/img/feature-bridging.svg\" /></div>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tLink 2 or more Desktop Agent APIs together via a <a href=\"/docs/agent-bridging/spec\">bridge</a> to extend interop across them.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p>\n<a href=\"https://fdc3.finos.org/docs/fdc3-compliance#experimental-features\">@experimental</a>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</aside>\n\t\t\t\t</Carousel1>\n\t\t\t</div>\n\t\t\t<p>\n\t\t\t\t<a className={styles.cta} href=\"/docs/fdc3-intro\">READ THE STANDARD</a>\n\t\t\t</p>\n\t\t</HomeSection>\n\n\n\t)\n}\n\n"
  },
  {
    "path": "website/src/components/Parts/styles.module.css",
    "content": ".part {\n\ttext-align: center;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n}\n\n.title {\n\tfont-size: 3rem;\n\tfont-family: \"Rokkitt\";\n}\n\n.part h1 {\n\tfont-size: 5rem;\n\tfont-family: \"Rokkitt\";\t\n\tfont-weight: 800;\n}\n\n.part img {\n\twidth: 60%;\n}\n\n.strap {\n\tfont-size: 3rem;\n\tfont-family: \"Rokkitt\";\n}\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n}\n\n.innerAside {\n\tcolor: black;\n\tfont-family: 'Rokkitt';\n\ttext-align: right;\n\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 500 500\" fill=\"%23fff\"><ellipse rx=\"200px\" ry=\"200px\" cy=\"200\" cx=\"200\" /></svg>');\n\tbackground-repeat: no-repeat;\n\tbackground-position: 0 0;\n\tbackground-size: cover;\n}\n\n.innerAside h2 {\n\tfont-size: 8rem;\n\tfont-weight: 800;\n\tfont-family: \"Rokkitt\";\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\nhtml[data-theme=dark] .innerAside h2,\nhtml[data-theme=dark] .strap {\n\tcolor: black;\n}\n\n.innerAside p, .title {\n\tfont-size: 3rem;\n\tfont-weight: 400;\n\tfont-family: \"Rokkitt\";\n}\n\nhtml[data-theme=dark] .innerAside {\n\tcolor: white;\n}"
  },
  {
    "path": "website/src/components/Training/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport HomeSection2 from \"../HomeSection2\";\n\nexport default function Training() {\n\treturn (\n\t\t<HomeSection2>\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>FDC3 Training and Certification</h2>\n\t\t\t</div>\n\n\t\t\t<div className={styles.trainingList}>\n\t\t\t\t<div className={styles.trainingItem}>\n\t\t\t\t\t<h2>Introduction to FDC3 (LFEL1000)</h2>\n\t\t\t\t\t<img className={styles.trainingImage} src=\"/img/training/LFEL1000.png\" />\n\t\t\t\t\t<p>This <strong>FREE</strong> entry-level course is designed for business technologists who are looking to adopt application interoperability within their technology landscape and for developers who want to build interoperable applications using the FDC3 Standard.</p>\n\t\t\t\t\t<a className={styles.cta} href=\"https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/\">MORE</a>\n\t\t\t\t</div>\n\t\t\t\t<div className={styles.trainingItem}>\n\t\t\t\t\t<h2>Developing Solutions with FDC3 (LFD237)</h2>\n\t\t\t\t\t<img className={styles.trainingImage} src=\"/img/training/LFD237.png\" />\n\t\t\t\t\t<p>This course is designed for developers who are looking to build interoperable applications using the FDC3 standard, as well as community participants who provide FDC3 technology and services.</p><p> LFD237 is priced at $299 but free seats are available to FINOS members.</p>\n\t\t\t\t\t<a className={styles.cta} href=\"https://training.linuxfoundation.org/training/developing-solutions-with-fdc3-lfd237/\">MORE</a>\n\t\t\t\t</div>\n\t\t\t\t<div className={styles.trainingItem}>\n\t\t\t\t\t<h2>FDC3 Certified Practitioner (FCFP)</h2>\n\t\t\t\t\t<img className={styles.trainingImage} src=\"/img/training/FCFP.png\" />\n\t\t\t\t\t<p>The FCFP is a professional certification designed for technical business analysts, software developers and FDC3 implementers in the finance, insurance, banking, and investment industries.</p><p>FCFP is priced at $250 but free seats are available to FINOS members.</p>\n\t\t\t\t\t<a className={styles.cta} href=\"https://training.linuxfoundation.org/certification/finos-certified-fdc3-practitioner/\">MORE</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<p>\n\t\t\t\t<a className={styles.cta} href=\"/training\">TRAINING PAGE</a>\n\t\t\t</p>\n\t\t</HomeSection2>\n\t)\n}\n\n"
  },
  {
    "path": "website/src/components/Training/styles.module.css",
    "content": ".title {\n\tfont-family: 'Electrolize';\n\tfont-size: 3rem;\n}\n\n.innerAside {\n\tcolor: black;\n\tline-height: 1.1;\n\ttext-align: center;\n}\n\n.innerAside h2 {\t\n\tfont-weight: bold;\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\n.trainingList {\n\tdisplay: flex;\n\tmax-width: 1200px;\n\tmargin: auto;\n\tgap: 2rem;\n\tflex-wrap: wrap;\n}\n\n\nhtml[data-theme=dark] .innerAside {\n\tcolor: white;\n}\n\n.trainingItem {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex-basis: 15rem;\n\tflex-shrink: 0;\n\tflex-grow: 1;\n\talign-items: center;\n}\n\n.trainingItem h2 {\n\theight: 5rem;\n}\n\n.trainingImage  {\n\tmargin-bottom: 2rem;\n}\n\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n\ttext-align: center;\n}"
  },
  {
    "path": "website/src/components/TypeText/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\n\n\nexport default function TypeText({children}) {\n\treturn (<div className={styles.animTypewriter}>{children}</div> )\n}"
  },
  {
    "path": "website/src/components/TypeText/styles.module.css",
    "content": ".animTypewriter {\n\tfont-family: Rokkitt;\n    margin: 0 auto;\n    font-size: 2.5rem;\n    text-align: center;\n    color: #777;\n}\n"
  },
  {
    "path": "website/src/components/UseCases/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport Carousel1 from '../Carousel1';\nimport HomeSection from \"../HomeSection\";\nimport Callout from \"../Callout\";\n\nexport default function UseCases() {\n\treturn (\n\t\t<HomeSection style={{ \"backgroundColor\": \"white\" }}>\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>Use Cases</h2>\n\t\t\t\t<p>The design of FDC3 is based on a set of foundational interoperability use-cases, validated by firms across the industry.</p><p>\n\t\t\t\t\tThis ensures the standard meets the real-world needs of the financial industry, not just assumptions.</p>\n\n\t\t\t</div>\n\t\t\t<div className={styles.right}>\n\t\t\t\t<img className={styles.image1} src=\"/img/use-cases/illus.svg\" />\n\t\t\t\t<a className={styles.cta} href=\"/docs/next/use-cases/overview\">READ MORE</a>\n\t\t\t</div>\n\t\t</HomeSection>\n\t)\n}\n\n"
  },
  {
    "path": "website/src/components/UseCases/styles.module.css",
    "content": ".cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: #0086bf;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n}\n\n.innerAside {\n\tmargin: auto;\n\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 500 500\" fill=\"%23ace\"><ellipse rx=\"200px\" ry=\"200px\" cy=\"200\" cx=\"200\" /></svg>');\n\tbackground-repeat: no-repeat;\n\tbackground-position: 0 0;\n\tbackground-size: cover;\n\tmin-height: 450px;\n}\n\n.innerAside h2 {\n\tfont-size: 8rem;\n\tfont-weight: bold;\n\tfont-family: 'Rokkitt';\n\tfont-size: 7rem;\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\nhtml[data-theme=dark] .innerAside {\n\tcolor: white;\n}\n\n.right {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n}\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: #0086bf;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n\ttext-align: center;\n}"
  },
  {
    "path": "website/src/components/UserShowcase/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport HomeSection2 from \"../HomeSection2\";\nimport Showcase from \"../../../core/Showcase\";\n\nimport users from './../../../data/users.json';\n\nexport default function UserShowcase() {\n\n\tconst pinnedUsers = users.filter(user => user.pinned);\n\tpinnedUsers.sort((a, b) => a.caption.localeCompare(b.caption))\n\n\treturn (\n\t\t<HomeSection2>\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>Who is Using FDC3?</h2>\n\t\t\t\t<p className={styles.explanation}>The FDC3 standards are created and used by <a href=\"/users\">leading organizations across the financial industry</a>. For more detail on who's using FDC3, developer tools, training and examples see the <a href=\"/community\">community page</a>.</p>\n\t\t\t</div>\n\t\t\t<div className={styles.showcaseOuter}>\n\t\t\t\t{\n\n\t\t\t\t\tpinnedUsers.map(pu =>\n\n\t\t\t\t\t\t<a href={pu.infoLink}><img className={styles.showcaseImage} src={pu.image} alt={pu.caption} title={pu.caption} /></a>\n\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t</div>\n\t\t\t<p>\n\t\t\t\t<a className={styles.button} href=\"/community\">COMMUNITY PAGE</a>\n\t\t\t</p>\n\t\t</HomeSection2>\n\t);\n};"
  },
  {
    "path": "website/src/components/UserShowcase/styles.module.css",
    "content": ".innerAside h2 {\n\tfont-weight: bold;\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n\tline-height: 1.1;\n\ttext-align: center;\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\n\n.innerAside p {\n\tfont-size: 1.5rem;\n\ttext-align: center;\n}\n\n.showcaseOuter {\n\talign-items: center;\n\tbackground-color: #fff;\n\tdisplay: flex;\n\tflex-flow: row wrap;\n\tjustify-content: center;\n\tmargin: 4rem;\n\tpadding: 2rem;\n}\n\n.showcaseImage {\n\tmargin-bottom: 10px;\n\tmargin-top: 10px;\n\tmax-height: 120px;\n\tmax-width: 250px;\n\tpadding-left: 15px;\n\tpadding-right: 15px;\n\twidth: 100%;\n\theight: 100%;\n}\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n}\n\n"
  },
  {
    "path": "website/src/components/WhatIsIt/index.js",
    "content": "import React from 'react';\nimport styles from './styles.module.css'\nimport HomeSection from \"../HomeSection\";\nimport ImageBullet from \"../ImageBullet\";\n\nexport default function Benefits() {\n\treturn (\n\t\t<HomeSection alt=\"true\">\n\t\t\t<div className={styles.innerAside}>\n\t\t\t\t<h2>What Is It?</h2>\n\t\t\t</div>\n\t\t\t<>\n\t\t\t\t<ImageBullet image=\"/img/splash/noun-radar.svg\" alt=\"Connect Icon\">FDC3 is an open standard for applications on financial desktop to interoperate and exchange data with each other.</ImageBullet>\n\t\t\t\t<ImageBullet  image=\"/img/splash/noun-speed.svg\" alt=\"Connect Icon\">\n\t\t\t\t\tUsers benefit from a more joined-up experience, which reduces the \"friction\" in getting tasks done.\n\t\t\t\t</ImageBullet>\n\t\t\t\t<ImageBullet  image=\"/img/splash/noun-connect.svg\" alt=\"Connect Icon\"> \n\t\t\t\tApplications can launch each other, respond to activity in other apps and request functionality from each other.\n\t\t\t\t</ImageBullet>\n\t\t\t</>\n\t\t\t<p>\n\t\t\t\t<a className={styles.cta} target='_blank' href=\"/pdf/FDC3-primer-2024.pdf\">READ THE PRIMER</a>\n\t\t\t\t<a className={styles.cta} target='_blank' href=\"https://github.com/finos/FDC3\">GITHUB REPO</a>\n\t\t\t</p>\n\t\t</HomeSection>\n\n\n\t)\n}\n\n\n\n"
  },
  {
    "path": "website/src/components/WhatIsIt/styles.module.css",
    "content": ".cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n}\n\n.innerAside {\n\tbackground-image: url('data:image/svg+xml,<svg width=\"1200pt\" height=\"1200pt\" version=\"1.1\" viewBox=\"0 0 1200 1200\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m600 1200c-331.35 0-600-268.65-600-600s268.65-600 600-600 600 268.65 600 600-268.65 600-600 600zm0-1050c-248.48 0-450 201.52-450 450s201.52 450 450 450 450-201.52 450-450-201.52-450-450-450zm0 150c-124.27 0-225 100.73-225 225h150c0-41.398 33.523-75 75-75s75 33.602 75 75-33.523 75-75 75h-37.5c-20.699 0-37.5 16.801-37.5 37.5v112.5h150v-13.801c87.148-30.977 150-113.4 150-211.2 0-124.27-100.73-225-225-225zm0 525h-75v75h150v-75z\" fill=\"white\"/></svg>');\n\tbackground-position: 0 0px;\n\tbackground-size: 60%;\n\tbackground-repeat: no-repeat;\n\theight: 25rem;\n}\n\n.innerAside h2 {\n\tfont-weight: 800;\n\tcolor: black;\n\tfont-family: 'Rokkitt';\n\tfont-size: 8rem;\n\tline-height: 1.1;\n\toverflow: hidden;\n}\n\n@media (max-width: 60rem) {\n\t.innerAside h2 {\n\t\tfont-size: 4rem;\n\t}\n}\n\nhtml[data-theme=dark] .innerAside {\n\tcolor: white;\n}"
  },
  {
    "path": "website/src/components/implementationFilters.js",
    "content": "function setType(theType) { \n\tlet typeToSet = theType;\n\n\tconsole.log(\"Setting filter type: \" + typeToSet);\n\tdocument.querySelectorAll(\".cta.filter\").forEach((elem) => {elem.classList.remove(\"selected\")});\n\tconst selectedButton = document.getElementById(typeToSet);\n\tif (selectedButton){\n\t\tselectedButton.classList.add(\"selected\");\n\t}\n\n\tif (typeToSet === \"all\") {\n\t\tdocument.querySelectorAll(\".implementation\").forEach((impl) => {\n\t\t\timpl.classList.remove(\"hide\");\n\t\t});\n\t} else {\n\t\tdocument.querySelectorAll(\".implementation\").forEach((impl) => {\n\t\t\tif (impl.classList.contains(typeToSet)) {\n\t\t\t\timpl.classList.remove(\"hide\");\n\t\t\t} else {\n\t\t\t\timpl.classList.add(\"hide\");\n\t\t\t}\n\t\t});\n\t}\n\tconst state = { 'type': typeToSet }\n\thistory.pushState(state, '', \"#type-\" + typeToSet);\n}\n\nexport default setType;"
  },
  {
    "path": "website/src/css/customTheme.css",
    "content": "\nhtml[data-theme='light'] {\n    background-color: #FFFFFF;\n}\n\nhtml[data-theme='dark'] {\n    background-color: #1B1B1B;\n}\n\n@font-face {\n    src: url(\"/fonts/Electrolize-Regular.ttf\");\n    font-family: 'Electrolize'\n}\n\n\n@font-face {\n    src: url(\"/fonts/Rokkitt-ExtraBold.ttf\");\n    font-family: 'Rokkitt';\n    font-weight: 800;\n}\n\n@font-face {\n    src: url(\"/fonts/Rokkitt-Medium.ttf\");\n    font-family: 'Rokkitt';\n    font-weight: 400;\n}\n\n@font-face {\n    src: url(\"/fonts/SpaceMono-Regular.ttf\");\n\tfont-family: 'Space-Mono'\n}\n\n.footer {\n\tbackground-color: #252525;\n\tborder-top: 1px solid #aaa;\n}\n\n.footer__title,\n.footer__link-item {\n\tcolor: #eee;\n}"
  },
  {
    "path": "website/src/pages/community.js",
    "content": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport React, { useState } from 'react';\nimport Layout from \"@theme/Layout\";\nimport Container from \"../components/Container\"\nimport implData from \"../../data/community.json\";\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport setType from '../components/implementationFilters'\nimport styles from \"./community.styles.css\"\n\n\nconst badgeTitles = {\n\t\"Open Source\": \"Indicates that the project source code is available to download and modify, under an Apache 2.0 or similar license.\",\n\t\"FDC3 1.2 Supported\": \"Indicates that this product advertises compatibility with the FDC3 1.2 Standard. \",\n\t\"FDC3 2.0 Supported \": \"Indicates that this product advertises compatibility with the FDC3 2.0 Standard. \",\n\t\"FDC3 1.2 Compliant\": \"This badge is applied to desktop agents that have passed the FINOS FDC3 1.2 Conformance testing process.\",\n\t\"FDC3 2.0 Compliant\": \"This badge is applied to desktop agents that have passed the FINOS FDC3 2.0 Conformance testing process.\"\n}\n\n//remove content guidelines, which are the first entry in the data file\nif (implData[0][\"//content guidelines\"]){\n\timplData.splice(0,1);\n}\n\n//alpha sort implementations\nimplData.sort((a, b) => {\n\tconst titleA = a.title.toUpperCase(); // ignore upper and lowercase\n\tconst titleB = b.title.toUpperCase(); // ignore upper and lowercase\n\tif (titleA < titleB) {\n\t\treturn -1;\n\t} else if (titleA > titleB) {\n\t\treturn 1;\n\t} else {\n\t\treturn 0;\n\t}\n});\n\n\nfunction Implementation({ type, title, publisher, image, infoLink, docsLink, badges, conformance, description }) {\n\treturn <div key={title + type} className={\"implementation \" + type}>\n\t\t<div className=\"implementation-metadata\">\n\t\t\t<div className=\"title-and-publisher\">\n\t\t\t\t<div className=\"title\">{infoLink ? <a href={infoLink} key={infoLink}>{title}</a> : { title }}</div>\n\t\t\t\t{publisher ? <div className=\"publisher\">{publisher}</div> : null}\n\t\t\t</div>\n\t\t\t<div className=\"type\">{type}</div>\n\t\t</div>\n\t\t<div className=\"implementation-details padding-top--sm padding-bottom--md\">\n\t\t\t<div className=\"implementation-image\">\n\t\t\t\t<img src={image} alt={title} title={title} />\n\t\t\t</div>\n\t\t\t<div className=\"description\">\n\t\t\t\t<div className=\"infoLinks\">\n\t\t\t\t\t{infoLink ? <a href={infoLink} className=\"button\">More info</a> : null}\n\t\t\t\t\t{docsLink ? <a href={docsLink} className=\"button\">Documentation</a> : null}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"prose\" dangerouslySetInnerHTML={{ __html: description }}></div>\n\t\t\t\t<div className=\"conformance\">\n\t\t\t\t\t{\n\t\t\t\t\t\tconformance ? <h3><a title=\"The FDC3 Conformance Framework\" href=\"https://github.com/finos/FDC3-Conformance-Framework\">Conformance Details</a></h3> : null\n\t\t\t\t\t}\n\t\t\t\t\t{\n\t\t\t\t\t\t(conformance ? conformance : []).map(c =>\n\t\t\t\t\t\t\t<div key={c.src} className=\"conformance-element\">\n\t\t\t\t\t\t\t\t<div className=\"conformance-badge\"><img src={c.src} /></div>\n\t\t\t\t\t\t\t\t<div className=\"conformance-text\"><ul>\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tc.items.map(ti => <li key={ti.text}>{ti.text} { ti.link ? <a className=\"conformance-details\" href={ti.link}>details</a> : \"\" }</li>)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</ul></div>\n\t\t\t\t\t\t\t</div>)\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"badges\">\n\t\t\t\t\t{badges.map(b => <div key={b.text} title={badgeTitles[b.text]} className=\"button badge\">{b.text}</div>)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n}\n\nfunction ImplementationsShowcase() {\n\t//set up state for filtering\n\tconst [type, setType] = useState(\"adopter\");\n\n\tfunction getButton(label, implType) {\n\t\tlet classes = \"button filter\";\n\t\tif (type == implType) { classes += \" selected\"};\n\t\treturn <button className={classes} id={implType} onClick={() => setType(implType)}>\n\t\t\t{label}\n\t\t</button>\n\t}\n\n\treturn <div key=\"is\">\n\t\t<div className=\"filters\">\n\t\t\t{getButton(\"Adopters\", \"adopter\")}\n\t\t\t{getButton(\"Platform Providers\", \"platform-provider\")}\n\t\t\t{getButton(\"App Providers\", \"application-provider\")}\n\t\t\t{getButton(\"Solution Providers\", \"solution-provider\")}\n\t\t\t{getButton(\"Tools & Training\", \"tools-and-training\")}\n\t\t\t{getButton(\"Demos\", \"demos\")}\n\t\t\t{getButton(\"Other\", \"other\")}\n\t\t</div>\n\t\t<div className=\"implementations\">\n\t\t\t{ //only render implementations matching current filter\n\t\t\timplData.map(impl => (\n\t\t\t\timpl.type == type && \n\t\t\t\t<Implementation key={impl.title + impl.type} {...impl} />\n\t\t\t))}\n\t\t</div>\n\t</div>\n}\n\nexport default (props) => {\n\tconst context = useDocusaurusContext();\n\tconst siteConfig = context.siteConfig;\n\tconst editUrl = `${siteConfig.customFields.repoUrl}/edit/main/website/data/community.json`;\n\n\treturn <Layout>\n\t\t<Container>\n\t\t\t<h1>FDC3 Community</h1>\n\t\t\t<div className=\"prose\">\n\t\t\t\t<p>\n\t\t\t\t\tThe Financial Desktop Connectivity and Collaboration Consortium (FDC3) standard is maintained and used by leading organizations across the financial industry through a variety of different implementations.\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\tFor more detail on who's implementing the Desktop Agent (a \"Platform Provider\"), using FDC3 to enable interop with their apps (an \"App Provider\") or details on where to find demos, examples apps, training materials and other resources, see below.\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\t<small>\n\t\t\t\t\t\t<i>\n\t\t\t\t\t\t\tDisclaimer: Please note that the majority of platforms, applications and content listed below are not affiliated with, supported, or otherwise maintained by FINOS or the FDC3 project and its maintainers. Please contact the publisher of each entry for more information.\n\t\t\t\t\t\t</i>\n\t\t\t\t\t</small>\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\t<i>\n\t\t\t\t\t\t<strong>Are you using FDC3?</strong>\n\t\t\t\t\t\t<a href={editUrl} className=\"button\">\n\t\t\t\t\t\t\tAdd your details\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</i>\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t<ImplementationsShowcase />\n\t\t</Container>\n\t</Layout>\n}\n\n\n"
  },
  {
    "path": "website/src/pages/community.styles.css",
    "content": "/* Conformance Added Dec 2022 */\n.conformance {\n\tpadding-left: 10px;\n}\n\n.conformance-element {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\talign-items: center;\n}\n\n.conformance-badge {\n\tflex-basis: 100px;\n\tflex-grow: 0;\n\tflex-shrink: 1;\n}\n\n.conformance-text {\n\tflex-basis: 500px;\n\tflex-grow: 1;\n\tflex-shrink: 5;\n\tcolor: rgb(90, 90, 90);\n}\n\n.front-conformance-logo {\n\twidth: 240px;\n\tpadding: 40px;\n}\n\n/* Implementations CSS added Apr 2021 */\n.filters {\n\tpadding-bottom: 0px;\n\tmargin-bottom: 0px;\n}\n\n.implementations {\n\tpadding-top: 0px;\n\tmargin-top: 0px;\n\tmargin-bottom: 25px;\n}\n\n.implementation {\n\tmargin: 6px 0px;\n\tpadding: 0px 0px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tborder-color: #0086bf;\n\tborder-width: 3px;\n\tborder-style: solid;\n}\n\n.implementation.hide {\n\tdisplay: none;\n}\n\n.implementation-metadata {\n\tpadding: 6px 6px;\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: space-between;\n\tbackground-color: #0086bf;\n\tcolor: #ffffff\n}\n\n.title-and-publisher {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\tflex-grow: 1;\n}\n\n.title-and-publisher>.title, .title-and-publisher>.title>a {\n\tfont-size: 24px;\n\tfont-weight: 600;\n\tflex-basis: 100%;\n\tcolor: #ffffff;\n}\n\n.implementation-metadata>.type {\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tflex-basis: content;\n\tfont-variant-caps: small-caps;\n}\n\n.title-and-publisher>.publisher {\n\tfont-size: 14px;\n\tfont-weight: 400;\n\tfont-variant-caps: small-caps;\n\tflex-basis: 100%;\n}\n\n.implementation-details>.implementation-image {\n\tpadding-top: 6px;\n\tpadding-bottom: 10px;\n\tobject-fit: contain;\n\tflex-basis: 300px;\n\tmargin-right: 6px;\n\tbackground-color: #FFFFFF;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.implementation-details>.implementation-image img {\n\tmax-width: 285px;\n\tmax-height: 150px;\n}\n\n.implementation-details>.description {\n\tflex-shrink: 1;\n\tflex-grow: 1;\n}\n\n.prose {\n\tpadding-left: 10px;\n}\n\n.implementation-details>.description>.infoLinks, .implementation-details>.description>.infoLinks>a\n\t{\n\tfont-size: 16px;\n\tfont-weight: 600;\n}\n\n.implementation-details {\n\tpadding: 6px 6px;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tflex-basis: 100%;\n\talign-items: stretch;\n}\n\n.implementation-details>.description>.badges {\n\tpadding-top: 10px;\n}\n\n.implementation-details>.description>.badges>.badge {\n\tbackground-color: rgb(239, 239, 239);\n\tdisplay: inline-block;\n\tborder: 0px;\n\tmargin-top: 5px;\n\tmargin-right: 10px;\n}\n\n@media screen and (max-width: 736px) {\n\t.implementation-details {\n\t\tpadding: 6px 6px;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tflex-basis: 100%;\n\t}\n\t.implementation-details>img {\n\t\talign-self: center;\n\t}\n}\n\n@media screen and (min-width: 737px) {\n\t.implementation-details>.description {\n\t\tflex-basis: 300px;\n\t}\n}\n\n.button {\n\tborder-radius: 3px;\n\tcolor: #0086bf;\n\tdisplay: inline-block;\n\tfont-size: 14px;\n\tline-height: 1.2em;\n\tmargin: 10px;\n\tpadding: 10px;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n}\n\n.button {\n  background: #0086bf44;\n  border: 1px solid #ffffff;\n}\n\n.button.selected {\n  background: #0086bf;\n  color: #fff;\n}\n\n.button.selected:hover {\n  background: #0086bf44;\n  color: #0086bf;;\n}\n\n.filter {\n    margin:0 2px 5px 0\n}"
  },
  {
    "path": "website/src/pages/get-involved.js",
    "content": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst React = require('react');\n\nimport Layout from \"@theme/Layout\";\nimport Container from \"../components/Container\"\nimport One from '../../data/get-involved/1.mdx'\nimport Two from '../../data/get-involved/2.mdx'\nimport Three from '../../data/get-involved/3.mdx'\nimport Four from '../../data/get-involved/4.mdx'\nimport GridBlock from \"../components/GridBlock\";\n\nimport Five from '../../data/get-involved/5.mdx'\n\nexport default () => {\n\n  return (\n    <Layout>\n      <Container>\n        <header className=\"postHeader\">\n          <h1>Get Involved in FDC3</h1>\n        </header>\n        <GridBlock items={[<One/>,<Two/>,<Three/>,<Four/>, <Five />]}/>\n      </Container>\n    </Layout>)\n};\n"
  },
  {
    "path": "website/src/pages/index.js",
    "content": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst React = require('react');\nimport Layout from \"@theme/Layout\";\n\nimport NewSplashTop from \"../components/NewSplashTop\";\nimport UseCases from \"../components/UseCases\";\nimport Benefits from \"../components/Benefits\";\nimport Parts from \"../components/Parts\";\nimport WhatIsIt from \"../components/WhatIsIt\";\n\nimport UserShowcase from \"../components/UserShowcase\";\nimport Conformance from \"../components/Conformance\";\nimport Training from \"../components/Training\"\nimport GetInvolved from \"../components/GetInvolved\"\n\n\nexport default () => {\n\treturn (<Layout>\n\t\t<NewSplashTop />\n\t\t<WhatIsIt />\n\t\t<Benefits />\n\t\t<UseCases />\n\t\t<Parts />\n\t\t\n\t\t\n\t\t<UserShowcase />\n\t\t<Conformance />\n\t\t<Training />\n\t\t\n\t\t<GetInvolved />\n\n\t</Layout>)\n}\n"
  },
  {
    "path": "website/src/pages/schemas/1.1/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/1.1/app-directory.yaml'></redoc>\n<script src=\"https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js\"></script>\n"
  },
  {
    "path": "website/src/pages/schemas/1.2/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/1.2/app-directory.yaml'></redoc>\n<script src=\"https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js\"></script>\n"
  },
  {
    "path": "website/src/pages/schemas/2.0/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/next/app-directory.yaml'></redoc>\n<script src=\"https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js\"></script>"
  },
  {
    "path": "website/src/pages/schemas/next/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/next/app-directory.yaml'></redoc>\n<script src=\"https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js\"></script>"
  },
  {
    "path": "website/src/pages/showcase.styles.css",
    "content": "\n.showcaseSection {\n}\n\n.productShowcaseSection .logos img {\n  width: 200px;\n}\n\n.showcaseSection .logos img {\n  width: 250px;\n}\n\n\n.featureShowcaseSection .logos img {\n  width: 200px;\n}\n\n.featureShowcaseSection h2,\n.userShowcase h2{\n  font-size: var(--ifm-h1-font-size);\n}\n\n.featureShowcaseSection {\n  background-color: var(--showcase-background); /* CHANGE THIS TO PRIMARY PROJECT COLOR */\n  padding-top: 10px;\n  padding-bottom: 40px;\n}\n\n.showcase-title{\n  font-size: var(--ifm-h3-font-size);\n  font-family: var(--ifm-heading-font-family);\n  font-weight: var(--ifm-heading-font-weight);\n  line-height: var(--ifm-heading-line-height);\n  margin: var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0;\n}\n\nhtml[data-theme='light'] {\n  --showcase-background: #F7F7F7;\n}\n\nhtml[data-theme='dark'] {\n  --showcase-background: #232323;\n} \n\n\n.showcase {\n  align-items: center;\n  display: flex;\n  flex-flow: row wrap;\n  justify-content: center;\n  padding: 20px;\n  margin-top: 20px;\n  background-color: white;\n}\n\n.showcase img {\n  max-width: 250px;\n  max-height: 120px;\n  padding-left: 15px;\n  padding-right: 15px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  width: 100%;\n  height: 100%;\n}\n\n.finos {\n  padding-top: 30px; /* CHANGED 14 MAY 2019 */\n  padding-bottom: 30px;\n  text-align: center;\n}\n\n.userShowcase p {\n  max-width: 60%;\n}\n\n.cta {\n\tbackground: #0086bf44;\n\tborder: 1px solid #ace;\n\tborder-radius: .5rem;\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 1rem;\n\tline-height: 1.2em;\n\tmargin: 1rem;\n\tpadding: 1rem;\n\ttext-decoration: none !important;\n\ttransition: background .3s, color .3s;\n\twidth: 15rem;\n\ttext-align: center;\n}\n"
  },
  {
    "path": "website/src/pages/training.js",
    "content": "const React = require('react');\nimport Layout from \"@theme/Layout\";\nimport styles from \"./community.styles.css\"\nimport Container from \"../components/Container\"\nimport implData from \"../../data/training.json\";\n\n\nexport default ({items}) => {\n\nfunction Implementation({ type, title, publisher, image, infoLink, docsLink, badges, conformance, description }) {\n\treturn <div key={title + type} className={\"implementation \" + type}>\n\t\t<div className=\"implementation-metadata\">\n\t\t\t<div className=\"title-and-publisher\">\n\t\t\t\t<div className=\"title\">{infoLink ? <a href={infoLink} key={infoLink}>{title}</a> : { title }}</div>\n\t\t\t\t{publisher ? <div className=\"publisher\">{publisher}</div> : null}\n\t\t\t</div>\n\t\t</div>\n\t\t<div className=\"implementation-details padding-top--sm padding-bottom--md\">\n\t\t\t<div className=\"implementation-image\">\n\t\t\t\t<img src={image} alt={title} title={title} />\n\t\t\t</div>\n\t\t\t<div className=\"description\">\n\t\t\t\t<div className=\"infoLinks\">\n\t\t\t\t\t{infoLink ? <a href={infoLink} className=\"button\">More info</a> : null}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"prose\" dangerouslySetInnerHTML={{ __html: description }}></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n}\n\n\n    return <Layout>\n\t\t<Container>\n\t\t\t<h1>FDC3 Training</h1>\n\t\t\t<div className=\"prose\">\n\t\t\t\t<p>\n\t\t\t\t\tIn 2023 FINOS, the FDC3 Community and the Linux Foundation worked to update \n\t\t\t\t\tthe training and certification offerings.  The below list contains both free and paid\n\t\t\t\t\ttrainings and professional certification for FDC3 practition\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\tReach out to <a href=\"mailto:help@finos.org\">FINOS</a> for enquiries around bulk discounts and membership.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div className=\"implementations\">\n\t\t\t\t{implData.map(impl => (\n\t\t\t\t\t<Implementation key={impl.title} {...impl} />\n\t\t\t\t))}\n\t\t</div>\n\t\t</Container>\n\t</Layout>\n  }"
  },
  {
    "path": "website/src/pages/users.js",
    "content": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst React = require('react');\n\nimport users from './../../data/users.json';\nimport Layout from \"@theme/Layout\";\nimport Container from \"../components/Container\"\nimport Showcase from \"../../core/Showcase\"\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport styles from \"./showcase.styles.css\"\n\nexport default (props) => {\n  const context = useDocusaurusContext();\n  const siteConfig = context.siteConfig;\n\n  const editUrl = `${siteConfig.customFields.repoUrl}/edit/main/website/data/users.json`;\n\n  const membersToShowcase = users.filter(\n    user => user.isMember,\n  );\n\n  membersToShowcase.sort((a, b) => a.caption.localeCompare(b.caption))\n\n  const othersToShowcase = users.filter(user => !user.isMember);\n\n  return (\n    <Layout>\n      <Container>\n        <div className=\"showcaseSection\">\n          <div className=\"prose\">\n            <h1>Who is Using FDC3?</h1>\n            <p>FDC3 has several industry-leading <a href=\"https://www.finos.org/become-a-member\">member participants.</a></p>\n          </div>\n          <Showcase users={membersToShowcase} />\n          {/* <div className=\"logos\">{showcase}</div> */}\n          {othersToShowcase.length > 0 ?\n            <div>\n              <div className=\"prose\">\n                <p>FDC3 is also used by financial organizations of all sizes.</p>\n              </div>\n              <Showcase users={othersToShowcase} />\n            </div> : null}\n          <p>Are you using FDC3?</p>\n          <a href={editUrl} className=\"cta\">\n            Add your company\n          </a>\n        </div>\n      </Container>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "website/src/pages/versions.js",
    "content": "const React = require('react');\n\nimport versions from '../../versions.json'\nimport Layout from \"@theme/Layout\";\nimport Container from \"../components/Container\"\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\n\n\nexport default (props) => {\n  const context = useDocusaurusContext();\n  const siteConfig = context.siteConfig;\n  const latestVersion = versions[0];\n  const repoUrl = siteConfig.customFields.repoUrl\n\n  return (\n    <Layout title=\"Versions\">\n      <Container>\n        <div className=\"post\">\n          <header className=\"postHeader\">\n            <h1>{siteConfig.title} Versions</h1>\n          </header>\n          <h3 id=\"latest\">Current version (Stable)</h3>\n          <table className=\"versions\">\n            <tbody>\n              <tr key=\"headers\">\n                <th>{latestVersion}</th>\n                <td>\n                  <a href=\"/docs/fdc3-intro\">Documentation</a>\n                </td>\n                <td>\n                  <a href={`${repoUrl}/releases/tag/v${latestVersion}`}>Release Notes</a>\n                </td>\n              </tr>\n            </tbody>\n          </table>\n          <h3 id=\"rc\">Latest version (Unreleased)</h3>\n          <table className=\"versions\">\n            <tbody>\n              <tr key=\"latest\">\n                <th>master</th>\n                <td>\n                  <a href={\"/docs/next/fdc3-intro\"}>Documentation</a>\n                </td>\n                <td>\n                  <a href={repoUrl}>Source Code</a>\n                </td>\n              </tr>\n            </tbody>\n          </table>\n          <p>Here you can find the latest documentation and unreleased code.</p>\n          <h3 id=\"archive\">Past Versions</h3>\n          <table className=\"versions\">\n            <tbody>\n              {versions\n                .filter(version => version !== latestVersion)\n                .map(version => (\n                    <tr key=\"{version}\">\n                      <th>{version}</th>\n                      <td>\n                        <a href={\"/docs/\"+version+\"/fdc3-intro\"}>Documentation</a>\n                      </td>\n                      <td>\n                        <a href={`${repoUrl}/releases/tag/v${version}`}>Release Notes</a>\n                      </td>\n                    </tr>\n                  ))\n              }\n            </tbody>\n          </table>\n          <p>\n            You can find past versions of this project on{' '}\n            <a href={repoUrl}>GitHub</a>.\n          </p>\n        </div>\n    </Container>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "website/static/schemas/1.0/app-directory.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"utf8\" />\n  <title>ReDoc documentation</title>\n  <!-- needed for adaptive design -->\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <style>\n    body {\n      padding: 0;\n      margin: 0;\n    }\n  </style>\n  <script>/*!\n * ReDoc - OpenAPI/Swagger-generated API Reference Documentation\n * -------------------------------------------------------------\n *   Version: \"2.0.0-rc.1\"\n *   Repo: https://github.com/Rebilly/ReDoc\n */\n!function(e,t){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=t(require(\"null\"),function(){try{return require(\"esprima\")}catch(e){}}()):\"function\"==typeof define&&define.amd?define([\"null\",\"esprima\"],t):\"object\"==typeof exports?exports.Redoc=t(require(\"null\"),function(){try{return require(\"esprima\")}catch(e){}}()):e.Redoc=t(e.null,e.esprima)}(this,function(e,t){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\"object\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\"default\",{enumerable:!0,value:e}),2&t&&\"string\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\"a\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\"\",n(n.s=134)}([function(e,t,n){\"use strict\";e.exports=n(178)},function(e,t,n){\"use strict\";(function(e,r){n.d(t,\"a\",function(){return Jt}),n.d(t,\"b\",function(){return Wt}),n.d(t,\"o\",function(){return Ft}),n.d(t,\"g\",function(){return De}),n.d(t,\"n\",function(){return v}),n.d(t,\"k\",function(){return ne}),n.d(t,\"i\",function(){return Je}),n.d(t,\"j\",function(){return Pe}),n.d(t,\"l\",function(){return be}),n.d(t,\"e\",function(){return le}),n.d(t,\"m\",function(){return Xt}),n.d(t,\"d\",function(){return O}),n.d(t,\"f\",function(){return Kt}),n.d(t,\"h\",function(){return Le}),n.d(t,\"c\",function(){return x});\n/*! *****************************************************************************\nCopyright (c) Microsoft Corporation. All rights reserved.\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at http://www.apache.org/licenses/LICENSE-2.0\n\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\nMERCHANTABLITY OR NON-INFRINGEMENT.\n\nSee the Apache Version 2.0 License for specific language governing permissions\nand limitations under the License.\n***************************************************************************** */\nvar o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};function i(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e};function s(e,t){var n=\"function\"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}function l(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(s(arguments[t]));return e}var c={},u={};function p(e){if(!0!==e.__mobxDidRunLazyInitializers){var t=e.__mobxDecorators;if(t)for(var n in pt(e,\"__mobxDidRunLazyInitializers\",!0),t){var r=t[n];r.propertyCreator(e,r.prop,r.descriptor,r.decoratorTarget,r.decoratorArguments)}}}function f(e,t){return function(){var n,r,o=function(r,o,i,s){if(!0===s)return t(r,o,i,r,n),null;if(!Object.prototype.hasOwnProperty.call(r,\"__mobxDecorators\")){var l=r.__mobxDecorators;pt(r,\"__mobxDecorators\",a({},l))}return r.__mobxDecorators[o]={prop:o,propertyCreator:t,descriptor:i,decoratorTarget:r,decoratorArguments:n},function(e,t){var n=t?c:u;return n[e]||(n[e]={configurable:!0,enumerable:t,get:function(){return p(this),this[e]},set:function(t){p(this),this[e]=t}})}(o,e)};return(2===(r=arguments).length||3===r.length)&&\"string\"==typeof r[1]||4===r.length&&!0===r[3]?(n=et,o.apply(null,arguments)):(n=Array.prototype.slice.call(arguments),o)}}function d(){return!!Et.spyListeners.length}function h(e){if(Et.spyListeners.length)for(var t=Et.spyListeners,n=0,r=t.length;n<r;n++)t[n](e)}function m(e){h(a({},e,{spyReportStart:!0}))}var g={spyReportEnd:!0};function y(e){h(e?a({},e,{spyReportEnd:!0}):g)}function v(e){return Et.spyListeners.push(e),st(function(){Et.spyListeners=Et.spyListeners.filter(function(t){return t!==e})})}function b(e,t){var n=function(){return w(e,t,this,arguments)};return n.isMobxAction=!0,n}function w(e,t,n,r){var o=function(e,t,n,r){var o=d()&&!!e,i=0;if(o){i=Date.now();var a=r&&r.length||0,s=new Array(a);if(a>0)for(var l=0;l<a;l++)s[l]=r[l];m({type:\"action\",name:e,object:n,arguments:s})}var c=Ut();Tt();var u=k(!0);return{prevDerivation:c,prevAllowStateChanges:u,notifySpy:o,startTime:i}}(e,0,n,r);try{return t.apply(n,r)}finally{!function(e){E(e.prevAllowStateChanges),jt(),Bt(e.prevDerivation),e.notifySpy&&y({time:Date.now()-e.startTime})}(o)}}function x(e,t){var n,r=k(e);try{n=t()}finally{E(r)}return n}function k(e){var t=Et.allowStateChanges;return Et.allowStateChanges=e,t}function E(e){Et.allowStateChanges=e}function S(){ot(!1)}function _(e){return function(t,n,r){if(r){if(r.value)return{value:b(e,r.value),enumerable:!1,configurable:!0,writable:!0};var o=r.initializer;return{enumerable:!1,configurable:!0,writable:!0,initializer:function(){return b(e,o.call(this))}}}return function(e){return function(t,n,r){Object.defineProperty(t,n,{configurable:!0,enumerable:!1,get:function(){},set:function(t){pt(this,n,O(e,t))}})}}(e).apply(this,arguments)}}var O=function(e,t,n,r){return 1===arguments.length&&\"function\"==typeof e?b(e.name||\"<unnamed action>\",e):2===arguments.length&&\"function\"==typeof t?b(e,t):1===arguments.length&&\"string\"==typeof e?_(e):!0!==r?_(t).apply(null,arguments):void(e[t]=b(e.name||t,n.value))};function C(e,t,n){pt(e,t,b(t,n.bind(e)))}O.bound=function(e,t,n,r){return!0===r?(C(e,t,n.value),null):n?{configurable:!0,enumerable:!1,get:function(){return C(this,t,n.value||n.initializer.call(this)),this[t]},set:S}:{enumerable:!1,configurable:!0,set:function(e){C(this,t,e)},get:function(){}}};var T=Object.prototype.toString;function j(e,t){return A(e,t)}function A(e,t,n,r){if(e===t)return 0!==e||1/e==1/t;if(null==e||null==t)return!1;if(e!=e)return t!=t;var o=typeof e;return(\"function\"===o||\"object\"===o||\"object\"==typeof t)&&function(e,t,n,r){e=I(e),t=I(t);var o=T.call(e);if(o!==T.call(t))return!1;switch(o){case\"[object RegExp]\":case\"[object String]\":return\"\"+e==\"\"+t;case\"[object Number]\":return+e!=+e?+t!=+t:0==+e?1/+e==1/t:+e==+t;case\"[object Date]\":case\"[object Boolean]\":return+e==+t;case\"[object Symbol]\":return\"undefined\"!=typeof Symbol&&Symbol.valueOf.call(e)===Symbol.valueOf.call(t)}var i=\"[object Array]\"===o;if(!i){if(\"object\"!=typeof e||\"object\"!=typeof t)return!1;var a=e.constructor,s=t.constructor;if(a!==s&&!(\"function\"==typeof a&&a instanceof a&&\"function\"==typeof s&&s instanceof s)&&\"constructor\"in e&&\"constructor\"in t)return!1}r=r||[];var l=(n=n||[]).length;for(;l--;)if(n[l]===e)return r[l]===t;if(n.push(e),r.push(t),i){if((l=e.length)!==t.length)return!1;for(;l--;)if(!A(e[l],t[l],n,r))return!1}else{var c,u=Object.keys(e);if(l=u.length,Object.keys(t).length!==l)return!1;for(;l--;)if(c=u[l],!P(t,c)||!A(e[c],t[c],n,r))return!1}return n.pop(),r.pop(),!0}(e,t,n,r)}function I(e){return Je(e)?e.peek():ht(e)||Pe(e)?mt(e.entries()):e}function P(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function R(e,t){return e===t}var N={identity:R,structural:function(e,t){return j(e,t)},default:function(e,t){return function(e,t){return\"number\"==typeof e&&\"number\"==typeof t&&isNaN(e)&&isNaN(t)}(e,t)||R(e,t)}};function L(e,t){void 0===t&&(t=tt);var n,r=t&&t.name||e.name||\"Autorun@\"+rt();if(!t.scheduler&&!t.delay)n=new Wt(r,function(){this.track(a)},t.onError);else{var o=D(t),i=!1;n=new Wt(r,function(){i||(i=!0,o(function(){i=!1,n.isDisposed||n.track(a)}))},t.onError)}function a(){e(n)}return n.schedule(),n.getDisposer()}var M=function(e){return e()};function D(e){return e.scheduler?e.scheduler:e.delay?function(t){return setTimeout(t,e.delay)}:M}var F=function(){function e(e){this.dependenciesState=vt.NOT_TRACKING,this.observing=[],this.newObserving=null,this.isBeingObserved=!1,this.isPendingUnobservation=!1,this.observers=[],this.observersIndexes={},this.diffValue=0,this.runId=0,this.lastAccessedBy=0,this.lowestObserverState=vt.UP_TO_DATE,this.unboundDepsCount=0,this.__mapid=\"#\"+rt(),this.value=new Pt(null),this.isComputing=!1,this.isRunningSetter=!1,this.isTracing=bt.NONE,this.derivation=e.get,this.name=e.name||\"ComputedValue@\"+rt(),e.set&&(this.setter=b(this.name+\"-setter\",e.set)),this.equals=e.equals||(e.compareStructural||e.struct?N.structural:N.default),this.scope=e.context,this.requiresReaction=!!e.requiresReaction,this.keepAlive=!!e.keepAlive}return e.prototype.onBecomeStale=function(){!function(e){if(e.lowestObserverState!==vt.UP_TO_DATE)return;e.lowestObserverState=vt.POSSIBLY_STALE;var t=e.observers,n=t.length;for(;n--;){var r=t[n];r.dependenciesState===vt.UP_TO_DATE&&(r.dependenciesState=vt.POSSIBLY_STALE,r.isTracing!==bt.NONE&&It(r,e),r.onBecomeStale())}}(this)},e.prototype.onBecomeUnobserved=function(){},e.prototype.onBecomeObserved=function(){},e.prototype.get=function(){this.isComputing&&ot(\"Cycle detected in computation \"+this.name+\": \"+this.derivation),0!==Et.inBatch||0!==this.observers.length||this.keepAlive?(At(this),Nt(this)&&this.trackAndCompute()&&function(e){if(e.lowestObserverState===vt.STALE)return;e.lowestObserverState=vt.STALE;var t=e.observers,n=t.length;for(;n--;){var r=t[n];r.dependenciesState===vt.POSSIBLY_STALE?r.dependenciesState=vt.STALE:r.dependenciesState===vt.UP_TO_DATE&&(e.lowestObserverState=vt.UP_TO_DATE)}}(this)):Nt(this)&&(this.warnAboutUntrackedRead(),Tt(),this.value=this.computeValue(!1),jt());var e=this.value;if(Rt(e))throw e.cause;return e},e.prototype.peek=function(){var e=this.computeValue(!1);if(Rt(e))throw e.cause;return e},e.prototype.set=function(e){if(this.setter){it(!this.isRunningSetter,\"The setter of computed value '\"+this.name+\"' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?\"),this.isRunningSetter=!0;try{this.setter.call(this.scope,e)}finally{this.isRunningSetter=!1}}else it(!1,!1)},e.prototype.trackAndCompute=function(){d()&&h({object:this.scope,type:\"compute\",name:this.name});var e=this.value,t=this.dependenciesState===vt.NOT_TRACKING,n=this.computeValue(!0),r=t||Rt(e)||Rt(n)||!this.equals(e,n);return r&&(this.value=n),r},e.prototype.computeValue=function(e){var t;if(this.isComputing=!0,Et.computationDepth++,e)t=Mt(this,this.derivation,this.scope);else if(!0===Et.disableErrorBoundaries)t=this.derivation.call(this.scope);else try{t=this.derivation.call(this.scope)}catch(e){t=new Pt(e)}return Et.computationDepth--,this.isComputing=!1,t},e.prototype.suspend=function(){this.keepAlive||(Dt(this),this.value=void 0)},e.prototype.observe=function(e,t){var n=this,r=!0,o=void 0;return L(function(){var i=n.get();if(!r||t){var a=Ut();e({type:\"update\",object:n,newValue:i,oldValue:o}),Bt(a)}r=!1,o=i})},e.prototype.warnAboutUntrackedRead=function(){},e.prototype.toJSON=function(){return this.get()},e.prototype.toString=function(){return this.name+\"[\"+this.derivation.toString()+\"]\"},e.prototype.valueOf=function(){return yt(this.get())},e}();F.prototype[gt()]=F.prototype.valueOf;var U=dt(\"ComputedValue\",F);function B(e){return void 0!==e.interceptors&&e.interceptors.length>0}function z(e,t){var n=e.interceptors||(e.interceptors=[]);return n.push(t),st(function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)})}function $(e,t){var n=Ut();try{var r=e.interceptors;if(r)for(var o=0,i=r.length;o<i&&(it(!(t=r[o](t))||t.type,\"Intercept handlers should return nothing or a change object\"),t);o++);return t}finally{Bt(n)}}function W(e){return void 0!==e.changeListeners&&e.changeListeners.length>0}function q(e,t){var n=e.changeListeners||(e.changeListeners=[]);return n.push(t),st(function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)})}function H(e,t){var n=Ut(),r=e.changeListeners;if(r){for(var o=0,i=(r=r.slice()).length;o<i;o++)r[o](t);Bt(n)}}var Y={};!function(){if(Ae)return;Ae=function(){function e(e){void 0===e&&(e=\"Atom@\"+rt()),this.name=e,this.isPendingUnobservation=!1,this.isBeingObserved=!1,this.observers=[],this.observersIndexes={},this.diffValue=0,this.lastAccessedBy=0,this.lowestObserverState=vt.NOT_TRACKING}return e.prototype.onBecomeUnobserved=function(){},e.prototype.onBecomeObserved=function(){},e.prototype.reportObserved=function(){return At(this)},e.prototype.reportChanged=function(){Tt(),function(e){if(e.lowestObserverState===vt.STALE)return;e.lowestObserverState=vt.STALE;var t=e.observers,n=t.length;for(;n--;){var r=t[n];r.dependenciesState===vt.UP_TO_DATE&&(r.isTracing!==bt.NONE&&It(r,e),r.onBecomeStale()),r.dependenciesState=vt.STALE}}(this),jt()},e.prototype.toString=function(){return this.name},e}(),Ie=dt(\"Atom\",Ae)}();var V=function(e){function t(t,n,r,o){void 0===r&&(r=\"ObservableValue@\"+rt()),void 0===o&&(o=!0);var i=e.call(this,r)||this;return i.enhancer=n,i.hasUnreportedChange=!1,i.value=n(t,void 0,r),o&&d()&&h({type:\"create\",name:i.name,newValue:\"\"+i.value}),i}return i(t,e),t.prototype.dehanceValue=function(e){return void 0!==this.dehancer?this.dehancer(e):e},t.prototype.set=function(e){var t=this.value;if((e=this.prepareNewValue(e))!==Y){var n=d();n&&m({type:\"update\",name:this.name,newValue:e,oldValue:t}),this.setNewValue(e),n&&y()}},t.prototype.prepareNewValue=function(e){if(Lt(this),B(this)){var t=$(this,{object:this,type:\"update\",newValue:e});if(!t)return Y;e=t.newValue}return e=this.enhancer(e,this.value,this.name),this.value!==e?e:Y},t.prototype.setNewValue=function(e){var t=this.value;this.value=e,this.reportChanged(),W(this)&&H(this,{type:\"update\",object:this,newValue:e,oldValue:t})},t.prototype.get=function(){return this.reportObserved(),this.dehanceValue(this.value)},t.prototype.intercept=function(e){return z(this,e)},t.prototype.observe=function(e,t){return t&&e({object:this,type:\"update\",newValue:this.value,oldValue:void 0}),q(this,e)},t.prototype.toJSON=function(){return this.get()},t.prototype.toString=function(){return this.name+\"[\"+this.value+\"]\"},t.prototype.valueOf=function(){return yt(this.get())},t}(Ae);V.prototype[gt()]=V.prototype.valueOf;dt(\"ObservableValue\",V);var Q=function(){function e(e,t,n){this.target=e,this.name=t,this.defaultEnhancer=n,this.values={}}return e.prototype.read=function(e,t){if(this.target===e||(this.illegalAccess(e,t),this.values[t]))return this.values[t].get()},e.prototype.write=function(e,t,n){var r=this.target;r!==e&&this.illegalAccess(e,t);var o=this.values[t];if(o instanceof F)o.set(n);else{if(B(this)){if(!(l=$(this,{type:\"update\",object:r,name:t,newValue:n})))return;n=l.newValue}if((n=o.prepareNewValue(n))!==Y){var i=W(this),s=d(),l=i||s?{type:\"update\",object:r,oldValue:o.value,name:t,newValue:n}:null;s&&m(a({},l,{name:this.name,key:t})),o.setNewValue(n),i&&H(this,l),s&&y()}}},e.prototype.remove=function(e){if(this.values[e]){var t=this.target;if(B(this))if(!(i=$(this,{object:t,name:e,type:\"remove\"})))return;try{Tt();var n=W(this),r=d(),o=this.values[e].get();this.keys&&this.keys.remove(e),delete this.values[e],delete this.target[e];var i=n||r?{type:\"remove\",object:t,oldValue:o,name:e}:null;r&&m(a({},i,{name:this.name,key:e})),n&&H(this,i),r&&y()}finally{jt()}}},e.prototype.illegalAccess=function(e,t){console.warn(\"Property '\"+t+\"' of '\"+e+\"' was accessed through the prototype chain. Use 'decorate' instead to declare the prop or access it statically through it's owner\")},e.prototype.observe=function(e,t){return q(this,e)},e.prototype.intercept=function(e){return z(this,e)},e.prototype.getKeys=function(){var e=this;return void 0===this.keys&&(this.keys=new Ye(Object.keys(this.values).filter(function(t){return e.values[t]instanceof V}),ke,\"keys(\"+this.name+\")\",!0)),this.keys.slice()},e}();function G(e,t,n){void 0===t&&(t=\"\"),void 0===n&&(n=xe);var r=e.$mobx;return r||(ut(e)||(t=(e.constructor.name||\"ObservableObject\")+\"@\"+rt()),t||(t=\"ObservableObject@\"+rt()),ft(e,\"$mobx\",r=new Q(e,t,n)),r)}function X(e,t,n,r){var o=G(e);if(B(o)){var i=$(o,{object:e,name:t,type:\"add\",newValue:n});if(!i)return;n=i.newValue}n=(o.values[t]=new V(n,r,o.name+\".\"+t,!1)).value,Object.defineProperty(e,t,function(e){return J[e]||(J[e]={configurable:!0,enumerable:!0,get:function(){return this.$mobx.read(this,e)},set:function(t){this.$mobx.write(this,e,t)}})}(t)),o.keys&&o.keys.push(t),function(e,t,n,r){var o=W(e),i=d(),s=o||i?{type:\"add\",object:t,name:n,newValue:r}:null;i&&m(a({},s,{name:e.name,key:n}));o&&H(e,s);i&&y()}(o,e,t,n)}function K(e,t,n){var r=G(e);n.name=r.name+\".\"+t,n.context=e,r.values[t]=new F(n),Object.defineProperty(e,t,function(e){return Z[e]||(Z[e]={configurable:!0,enumerable:!1,get:function(){return ee(this).read(this,e)},set:function(t){ee(this).write(this,e,t)}})}(t))}var J=Object.create(null),Z=Object.create(null);function ee(e){var t=e.$mobx;return t||(p(e),e.$mobx)}var te=dt(\"ObservableObjectAdministration\",Q);function ne(e){return!!ct(e)&&(p(e),te(e.$mobx))}function re(t){var n=f(!0,function(e,n,r,o,i){X(e,n,r?r.initializer?r.initializer.call(e):r.value:void 0,t)}),r=(void 0!==e&&e.env,n);return r.enhancer=t,r}function oe(e,t){if(null==e)return!1;if(void 0!==t){if(ne(e)){var n=e.$mobx;return n.values&&!!n.values[t]}return!1}return ne(e)||!!e.$mobx||Ie(e)||Qt(e)||U(e)}function ie(e){return 1!==arguments.length&&ot(!1),oe(e)}var ae=f(!1,function(e,t,n,r,o){var i=n.get,s=n.set,l=o[0]||{};K(e,t,a({get:i,set:s},l))}),se=ae({equals:N.structural}),le=function(e,t,n){if(\"string\"==typeof t)return ae.apply(null,arguments);if(null!==e&&\"object\"==typeof e&&1===arguments.length)return ae.apply(null,arguments);var r=\"object\"==typeof t?t:{};return r.get=e,r.set=\"function\"==typeof t?t:r.set,r.name=r.name||e.name||\"\",new F(r)};function ce(e,t,n,r){var o=(r=fe(r)).defaultDecorator||(!1===r.deep?ge:he);p(e),G(e,r.name,o.enhancer),Tt();try{for(var i in t){var a=Object.getOwnPropertyDescriptor(t,i);0;var s=(n&&i in n?n[i]:a.get?ae:o)(e,i,a,!0);s&&Object.defineProperty(e,i,s)}}finally{jt()}return e}le.struct=se;var ue={deep:!0,name:void 0,defaultDecorator:void 0},pe={deep:!1,name:void 0,defaultDecorator:void 0};function fe(e){return null==e?ue:\"string\"==typeof e?{name:e,deep:!0}:e}function de(e){return e.defaultDecorator?e.defaultDecorator.enhancer:!1===e.deep?ke:xe}Object.freeze(ue),Object.freeze(pe);var he=re(xe),me=re(function(e,t,n){return null==e?e:ne(e)||Je(e)||Pe(e)?e:Array.isArray(e)?be.array(e,{name:n,deep:!1}):ut(e)?be.object(e,void 0,{name:n,deep:!1}):ht(e)?be.map(e,{name:n,deep:!1}):ot(!1)}),ge=re(ke),ye=re(function(e,t,n){0;return j(e,t)?t:e});var ve={box:function(e,t){arguments.length>2&&we(\"box\");var n=fe(t);return new V(e,de(n),n.name)},shallowBox:function(e,t){return arguments.length>2&&we(\"shallowBox\"),at(\"observable.shallowBox\",\"observable.box(value, { deep: false })\"),be.box(e,{name:t,deep:!1})},array:function(e,t){arguments.length>2&&we(\"array\");var n=fe(t);return new Ye(e,de(n),n.name)},shallowArray:function(e,t){return arguments.length>2&&we(\"shallowArray\"),at(\"observable.shallowArray\",\"observable.array(values, { deep: false })\"),be.array(e,{name:t,deep:!1})},map:function(e,t){arguments.length>2&&we(\"map\");var n=fe(t);return new je(e,de(n),n.name)},shallowMap:function(e,t){return arguments.length>2&&we(\"shallowMap\"),at(\"observable.shallowMap\",\"observable.map(values, { deep: false })\"),be.map(e,{name:t,deep:!1})},object:function(e,t,n){return\"string\"==typeof arguments[1]&&we(\"object\"),ce({},e,t,fe(n))},shallowObject:function(e,t){return\"string\"==typeof arguments[1]&&we(\"shallowObject\"),at(\"observable.shallowObject\",\"observable.object(values, {}, { deep: false })\"),be.object(e,{},{name:t,deep:!1})},ref:ge,shallow:me,deep:he,struct:ye},be=function(e,t,n){if(\"string\"==typeof arguments[1])return he.apply(null,arguments);if(ie(e))return e;var r=ut(e)?be.object(e,t,n):Array.isArray(e)?be.array(e,t):ht(e)?be.map(e,t):e;if(r!==e)return r;ot(!1)};function we(e){ot(\"Expected one or two arguments to observable.\"+e+\". Did you accidentally try to use observable.\"+e+\" as decorator?\")}function xe(e,t,n){return ie(e)?e:Array.isArray(e)?be.array(e,{name:n}):ut(e)?be.object(e,void 0,{name:n}):ht(e)?be.map(e,{name:n}):e}function ke(e){return e}function Ee(){return\"function\"==typeof Symbol&&Symbol.iterator||\"@@iterator\"}function Se(e,t){ft(e,Ee(),t)}function _e(e){return e[Ee()]=Oe,e}function Oe(){return this}function Ce(e,t){void 0===t&&(t=void 0),Tt();try{return e.apply(t)}finally{jt()}}Object.keys(ve).forEach(function(e){return be[e]=ve[e]});var Te={},je=function(){function e(e,t,n){if(void 0===t&&(t=xe),void 0===n&&(n=\"ObservableMap@\"+rt()),this.enhancer=t,this.name=n,this.$mobx=Te,this._keys=new Ye(void 0,ke,this.name+\".keys()\",!0),\"function\"!=typeof Map)throw new Error(\"mobx.map requires Map polyfill for the current browser. Check babel-polyfill or core-js/es6/map.js\");this._data=new Map,this._hasMap=new Map,this.merge(e)}return e.prototype._has=function(e){return this._data.has(e)},e.prototype.has=function(e){return this._hasMap.has(e)?this._hasMap.get(e).get():this._updateHasMapEntry(e,!1).get()},e.prototype.set=function(e,t){var n=this._has(e);if(B(this)){var r=$(this,{type:n?\"update\":\"add\",object:this,newValue:t,name:e});if(!r)return this;t=r.newValue}return n?this._updateValue(e,t):this._addValue(e,t),this},e.prototype.delete=function(e){var t=this;if(B(this)&&!(o=$(this,{type:\"delete\",object:this,name:e})))return!1;if(this._has(e)){var n=d(),r=W(this),o=r||n?{type:\"delete\",object:this,oldValue:this._data.get(e).value,name:e}:null;return n&&m(a({},o,{name:this.name,key:e})),Ce(function(){t._keys.remove(e),t._updateHasMapEntry(e,!1),t._data.get(e).setNewValue(void 0),t._data.delete(e)}),r&&H(this,o),n&&y(),!0}return!1},e.prototype._updateHasMapEntry=function(e,t){var n=this._hasMap.get(e);return n?n.setNewValue(t):(n=new V(t,ke,this.name+\".\"+e+\"?\",!1),this._hasMap.set(e,n)),n},e.prototype._updateValue=function(e,t){var n=this._data.get(e);if((t=n.prepareNewValue(t))!==Y){var r=d(),o=W(this),i=o||r?{type:\"update\",object:this,oldValue:n.value,name:e,newValue:t}:null;r&&m(a({},i,{name:this.name,key:e})),n.setNewValue(t),o&&H(this,i),r&&y()}},e.prototype._addValue=function(e,t){var n=this;Ce(function(){var r=new V(t,n.enhancer,n.name+\".\"+e,!1);n._data.set(e,r),t=r.value,n._updateHasMapEntry(e,!0),n._keys.push(e)});var r=d(),o=W(this),i=o||r?{type:\"add\",object:this,name:e,newValue:t}:null;r&&m(a({},i,{name:this.name,key:e})),o&&H(this,i),r&&y()},e.prototype.get=function(e){return this.has(e)?this.dehanceValue(this._data.get(e).get()):this.dehanceValue(void 0)},e.prototype.dehanceValue=function(e){return void 0!==this.dehancer?this.dehancer(e):e},e.prototype.keys=function(){return this._keys[Ee()]()},e.prototype.values=function(){var e=this,t=0;return _e({next:function(){return t<e._keys.length?{value:e.get(e._keys[t++]),done:!1}:{value:void 0,done:!0}}})},e.prototype.entries=function(){var e=this,t=0;return _e({next:function(){if(t<e._keys.length){var n=e._keys[t++];return{value:[n,e.get(n)],done:!1}}return{done:!0}}})},e.prototype.forEach=function(e,t){var n=this;this._keys.forEach(function(r){return e.call(t,n.get(r),r,n)})},e.prototype.merge=function(e){var t=this;return Pe(e)&&(e=e.toJS()),Ce(function(){ut(e)?Object.keys(e).forEach(function(n){return t.set(n,e[n])}):Array.isArray(e)?e.forEach(function(e){var n=s(e,2),r=n[0],o=n[1];return t.set(r,o)}):ht(e)?e.forEach(function(e,n){return t.set(n,e)}):null!=e&&ot(\"Cannot initialize map from \"+e)}),this},e.prototype.clear=function(){var e=this;Ce(function(){Ft(function(){e._keys.slice().forEach(function(t){return e.delete(t)})})})},e.prototype.replace=function(e){var t=this;return Ce(function(){var n,r=ut(n=e)?Object.keys(n):Array.isArray(n)?n.map(function(e){return s(e,1)[0]}):ht(n)||Pe(n)?mt(n.keys()):ot(\"Cannot get keys from '\"+n+\"'\");t._keys.filter(function(e){return-1===r.indexOf(e)}).forEach(function(e){return t.delete(e)}),t.merge(e)}),this},Object.defineProperty(e.prototype,\"size\",{get:function(){return this._keys.length},enumerable:!0,configurable:!0}),e.prototype.toPOJO=function(){var e=this,t={};return this._keys.forEach(function(n){return t[\"\"+n]=e.get(n)}),t},e.prototype.toJS=function(){var e=this,t=new Map;return this._keys.forEach(function(n){return t.set(n,e.get(n))}),t},e.prototype.toJSON=function(){return this.toPOJO()},e.prototype.toString=function(){var e=this;return this.name+\"[{ \"+this._keys.map(function(t){return t+\": \"+e.get(t)}).join(\", \")+\" }]\"},e.prototype.observe=function(e,t){return q(this,e)},e.prototype.intercept=function(e){return z(this,e)},e}();Se(je.prototype,function(){return this.entries()}),ft(je.prototype,\"undefined\"!=typeof Symbol?Symbol.toStringTag:\"@@toStringTag\",\"Map\");var Ae,Ie,Pe=dt(\"ObservableMap\",je);function Re(e,t){if(\"object\"==typeof e&&null!==e){if(Je(e))return void 0!==t&&ot(!1),e.$mobx.atom;if(Pe(e)){var n=e;return void 0===t?Re(n._keys):((r=n._data.get(t)||n._hasMap.get(t))||ot(!1),r)}var r;if(p(e),t&&!e.$mobx&&e[t],ne(e))return t?((r=e.$mobx.values[t])||ot(!1),r):ot(!1);if(Ie(e)||U(e)||Qt(e))return e}else if(\"function\"==typeof e&&Qt(e.$mobx))return e.$mobx;return ot(!1)}function Ne(e,t){return e||ot(\"Expecting some object\"),void 0!==t?Ne(Re(e,t)):Ie(e)||U(e)||Qt(e)?e:Pe(e)?e:(p(e),e.$mobx?e.$mobx:void ot(!1))}function Le(e,t){return(void 0!==t?Re(e,t):ne(e)||Pe(e)?Ne(e):Re(e)).name}function Me(e,t,n,r){var o=\"string\"==typeof n?Re(t,n):Re(t),i=\"string\"==typeof n?r:n,a=o[e];return\"function\"!=typeof a?ot(!1):(o[e]=function(){a.call(this),i.call(this)},function(){o[e]=a})}function De(e,t,n){void 0===t&&(t=lt),void 0===n&&(n=lt);var r,o=new Ae(e);return Me(\"onBecomeObserved\",o,t,r),function(e,t,n){Me(\"onBecomeUnobserved\",e,t,n)}(o,n),o}var Fe,Ue,Be,ze,$e=(Fe=!1,Ue={},Object.defineProperty(Ue,\"0\",{set:function(){Fe=!0}}),Object.create(Ue)[0]=1,!1===Fe),We=0,qe=function(){return function(){}}();Be=qe,ze=Array.prototype,void 0!==Object.setPrototypeOf?Object.setPrototypeOf(Be.prototype,ze):void 0!==Be.prototype.__proto__?Be.prototype.__proto__=ze:Be.prototype=ze,Object.isFrozen(Array)&&[\"constructor\",\"push\",\"shift\",\"concat\",\"pop\",\"unshift\",\"replace\",\"find\",\"findIndex\",\"splice\",\"reverse\",\"sort\"].forEach(function(e){Object.defineProperty(qe.prototype,e,{configurable:!0,writable:!0,value:Array.prototype[e]})});var He=function(){function e(e,t,n,r){this.array=n,this.owned=r,this.values=[],this.lastKnownLength=0,this.atom=new Ae(e||\"ObservableArray@\"+rt()),this.enhancer=function(n,r){return t(n,r,e+\"[..]\")}}return e.prototype.dehanceValue=function(e){return void 0!==this.dehancer?this.dehancer(e):e},e.prototype.dehanceValues=function(e){return void 0!==this.dehancer&&this.values.length>0?e.map(this.dehancer):e},e.prototype.intercept=function(e){return z(this,e)},e.prototype.observe=function(e,t){return void 0===t&&(t=!1),t&&e({object:this.array,type:\"splice\",index:0,added:this.values.slice(),addedCount:this.values.length,removed:[],removedCount:0}),q(this,e)},e.prototype.getArrayLength=function(){return this.atom.reportObserved(),this.values.length},e.prototype.setArrayLength=function(e){if(\"number\"!=typeof e||e<0)throw new Error(\"[mobx.array] Out of range: \"+e);var t=this.values.length;if(e!==t)if(e>t){for(var n=new Array(e-t),r=0;r<e-t;r++)n[r]=void 0;this.spliceWithArray(t,0,n)}else this.spliceWithArray(e,t-e)},e.prototype.updateArrayLength=function(e,t){if(e!==this.lastKnownLength)throw new Error(\"[mobx] Modification exception: the internal structure of an observable array was changed. Did you use peek() to change it?\");this.lastKnownLength+=t,t>0&&e+t+1>We&&Xe(e+t+1)},e.prototype.spliceWithArray=function(e,t,n){var r=this;Lt(this.atom);var o=this.values.length;if(void 0===e?e=0:e>o?e=o:e<0&&(e=Math.max(0,o+e)),t=1===arguments.length?o-e:null==t?0:Math.max(0,Math.min(t,o-e)),void 0===n&&(n=et),B(this)){var i=$(this,{object:this.array,type:\"splice\",index:e,removedCount:t,added:n});if(!i)return et;t=i.removedCount,n=i.added}var a=(n=0===n.length?n:n.map(function(e){return r.enhancer(e,void 0)})).length-t;this.updateArrayLength(o,a);var s=this.spliceItemsIntoValues(e,t,n);return 0===t&&0===n.length||this.notifyArraySplice(e,n,s),this.dehanceValues(s)},e.prototype.spliceItemsIntoValues=function(e,t,n){if(n.length<1e4)return(r=this.values).splice.apply(r,l([e,t],n));var r,o=this.values.slice(e,e+t);return this.values=this.values.slice(0,e).concat(n,this.values.slice(e+t)),o},e.prototype.notifyArrayChildUpdate=function(e,t,n){var r=!this.owned&&d(),o=W(this),i=o||r?{object:this.array,type:\"update\",index:e,newValue:t,oldValue:n}:null;r&&m(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&H(this,i),r&&y()},e.prototype.notifyArraySplice=function(e,t,n){var r=!this.owned&&d(),o=W(this),i=o||r?{object:this.array,type:\"splice\",index:e,removed:n,added:t,removedCount:n.length,addedCount:t.length}:null;r&&m(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&H(this,i),r&&y()},e}(),Ye=function(e){function t(t,n,r,o){void 0===r&&(r=\"ObservableArray@\"+rt()),void 0===o&&(o=!1);var i=e.call(this)||this,a=new He(r,n,i,o);if(ft(i,\"$mobx\",a),t&&t.length){var s=k(!0);i.spliceWithArray(0,0,t),E(s)}return $e&&Object.defineProperty(a.array,\"0\",Ve),i}return i(t,e),t.prototype.intercept=function(e){return this.$mobx.intercept(e)},t.prototype.observe=function(e,t){return void 0===t&&(t=!1),this.$mobx.observe(e,t)},t.prototype.clear=function(){return this.splice(0)},t.prototype.concat=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this.$mobx.atom.reportObserved(),Array.prototype.concat.apply(this.peek(),e.map(function(e){return Je(e)?e.peek():e}))},t.prototype.replace=function(e){return this.$mobx.spliceWithArray(0,this.$mobx.values.length,e)},t.prototype.toJS=function(){return this.slice()},t.prototype.toJSON=function(){return this.toJS()},t.prototype.peek=function(){return this.$mobx.atom.reportObserved(),this.$mobx.dehanceValues(this.$mobx.values)},t.prototype.find=function(e,t,n){void 0===n&&(n=0),3===arguments.length&&at(\"The array.find fromIndex argument to find will not be supported anymore in the next major\");var r=this.findIndex.apply(this,arguments);return-1===r?void 0:this.get(r)},t.prototype.findIndex=function(e,t,n){void 0===n&&(n=0),3===arguments.length&&at(\"The array.findIndex fromIndex argument to find will not be supported anymore in the next major\");for(var r=this.peek(),o=r.length,i=n;i<o;i++)if(e.call(t,r[i],i,this))return i;return-1},t.prototype.splice=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];switch(arguments.length){case 0:return[];case 1:return this.$mobx.spliceWithArray(e);case 2:return this.$mobx.spliceWithArray(e,t)}return this.$mobx.spliceWithArray(e,t,n)},t.prototype.spliceWithArray=function(e,t,n){return this.$mobx.spliceWithArray(e,t,n)},t.prototype.push=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=this.$mobx;return n.spliceWithArray(n.values.length,0,e),n.values.length},t.prototype.pop=function(){return this.splice(Math.max(this.$mobx.values.length-1,0),1)[0]},t.prototype.shift=function(){return this.splice(0,1)[0]},t.prototype.unshift=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=this.$mobx;return n.spliceWithArray(0,0,e),n.values.length},t.prototype.reverse=function(){var e=this.slice();return e.reverse.apply(e,arguments)},t.prototype.sort=function(e){var t=this.slice();return t.sort.apply(t,arguments)},t.prototype.remove=function(e){var t=this.$mobx.dehanceValues(this.$mobx.values).indexOf(e);return t>-1&&(this.splice(t,1),!0)},t.prototype.move=function(e,t){function n(e){if(e<0)throw new Error(\"[mobx.array] Index out of bounds: \"+e+\" is negative\");var t=this.$mobx.values.length;if(e>=t)throw new Error(\"[mobx.array] Index out of bounds: \"+e+\" is not smaller than \"+t)}if(at(\"observableArray.move is deprecated, use .slice() & .replace() instead\"),n.call(this,e),n.call(this,t),e!==t){var r,o=this.$mobx.values;r=e<t?l(o.slice(0,e),o.slice(e+1,t+1),[o[e]],o.slice(t+1)):l(o.slice(0,t),[o[e]],o.slice(t,e),o.slice(e+1)),this.replace(r)}},t.prototype.get=function(e){var t=this.$mobx;if(t){if(e<t.values.length)return t.atom.reportObserved(),t.dehanceValue(t.values[e]);console.warn(\"[mobx.array] Attempt to read an array index (\"+e+\") that is out of bounds (\"+t.values.length+\"). Please check length first. Out of bound indices will not be tracked by MobX\")}},t.prototype.set=function(e,t){var n=this.$mobx,r=n.values;if(e<r.length){Lt(n.atom);var o=r[e];if(B(n)){var i=$(n,{type:\"update\",object:this,index:e,newValue:t});if(!i)return;t=i.newValue}(t=n.enhancer(t,o))!==o&&(r[e]=t,n.notifyArrayChildUpdate(e,t,o))}else{if(e!==r.length)throw new Error(\"[mobx.array] Index out of bounds, \"+e+\" is larger than \"+r.length);n.spliceWithArray(e,0,[t])}},t}(qe);Se(Ye.prototype,function(){this.$mobx.atom.reportObserved();var e=this,t=0;return _e({next:function(){return t<e.length?{value:e[t++],done:!1}:{done:!0,value:void 0}}})}),Object.defineProperty(Ye.prototype,\"length\",{enumerable:!1,configurable:!0,get:function(){return this.$mobx.getArrayLength()},set:function(e){this.$mobx.setArrayLength(e)}}),\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&pt(Ye.prototype,\"undefined\"!=typeof Symbol?Symbol.toStringTag:\"@@toStringTag\",\"Array\"),[\"every\",\"filter\",\"forEach\",\"indexOf\",\"join\",\"lastIndexOf\",\"map\",\"reduce\",\"reduceRight\",\"slice\",\"some\",\"toString\",\"toLocaleString\"].forEach(function(e){var t=Array.prototype[e];it(\"function\"==typeof t,\"Base function not defined on Array prototype: '\"+e+\"'\"),pt(Ye.prototype,e,function(){return t.apply(this.peek(),arguments)})}),function(e,t){for(var n=0;n<t.length;n++)pt(e,t[n],e[t[n]])}(Ye.prototype,[\"constructor\",\"intercept\",\"observe\",\"clear\",\"concat\",\"get\",\"replace\",\"toJS\",\"toJSON\",\"peek\",\"find\",\"findIndex\",\"splice\",\"spliceWithArray\",\"push\",\"pop\",\"set\",\"shift\",\"unshift\",\"reverse\",\"sort\",\"remove\",\"move\",\"toString\",\"toLocaleString\"]);var Ve=Qe(0);function Qe(e){return{enumerable:!1,configurable:!1,get:function(){return this.get(e)},set:function(t){this.set(e,t)}}}function Ge(e){Object.defineProperty(Ye.prototype,\"\"+e,Qe(e))}function Xe(e){for(var t=We;t<e;t++)Ge(t);We=e}Xe(1e3);var Ke=dt(\"ObservableArrayAdministration\",He);function Je(e){return ct(e)&&Ke(e.$mobx)}var Ze=\"An invariant failed, however the error is obfuscated because this is an production build.\",et=[];Object.freeze(et);var tt={};function nt(){return\"undefined\"!=typeof window?window:r}function rt(){return++Et.mobxGuid}function ot(e){throw it(!1,e),\"X\"}function it(e,t){if(!e)throw new Error(\"[mobx] \"+(t||Ze))}Object.freeze(tt);function at(e,t){return!1}function st(e){var t=!1;return function(){if(!t)return t=!0,e.apply(this,arguments)}}var lt=function(){};function ct(e){return null!==e&&\"object\"==typeof e}function ut(e){if(null===e||\"object\"!=typeof e)return!1;var t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function pt(e,t,n){Object.defineProperty(e,t,{enumerable:!1,writable:!0,configurable:!0,value:n})}function ft(e,t,n){Object.defineProperty(e,t,{enumerable:!1,writable:!1,configurable:!0,value:n})}function dt(e,t){var n=\"isMobX\"+e;return t.prototype[n]=!0,function(e){return ct(e)&&!0===e[n]}}function ht(e){return void 0!==nt().Map&&e instanceof nt().Map}function mt(e){for(var t=[];;){var n=e.next();if(n.done)break;t.push(n.value)}return t}function gt(){return\"function\"==typeof Symbol&&Symbol.toPrimitive||\"@@toPrimitive\"}function yt(e){return null===e?null:\"object\"==typeof e?\"\"+e:e}var vt,bt,wt=function(){return function(){this.version=5,this.trackingDerivation=null,this.computationDepth=0,this.runId=0,this.mobxGuid=0,this.inBatch=0,this.pendingUnobservations=[],this.pendingReactions=[],this.isRunningReactions=!1,this.allowStateChanges=!0,this.enforceActions=!1,this.spyListeners=[],this.globalReactionErrorHandlers=[],this.computedRequiresReaction=!1,this.disableErrorBoundaries=!1}}(),xt=!0,kt=!1,Et=function(){var e=nt();return e.__mobxInstanceCount>0&&!e.__mobxGlobals&&(xt=!1),e.__mobxGlobals&&e.__mobxGlobals.version!==(new wt).version&&(xt=!1),xt?e.__mobxGlobals?(e.__mobxInstanceCount+=1,e.__mobxGlobals):(e.__mobxInstanceCount=1,e.__mobxGlobals=new wt):(setTimeout(function(){kt||ot(\"There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`\")},1),new wt)}();function St(e){var t,n,r={name:e.name};return e.observing&&e.observing.length>0&&(r.dependencies=(t=e.observing,n=[],t.forEach(function(e){-1===n.indexOf(e)&&n.push(e)}),n).map(St)),r}function _t(e,t){var n=e.observers.length;n&&(e.observersIndexes[t.__mapid]=n),e.observers[n]=t,e.lowestObserverState>t.dependenciesState&&(e.lowestObserverState=t.dependenciesState)}function Ot(e,t){if(1===e.observers.length)e.observers.length=0,Ct(e);else{var n=e.observers,r=e.observersIndexes,o=n.pop();if(o!==t){var i=r[t.__mapid]||0;i?r[o.__mapid]=i:delete r[o.__mapid],n[i]=o}delete r[t.__mapid]}}function Ct(e){!1===e.isPendingUnobservation&&(e.isPendingUnobservation=!0,Et.pendingUnobservations.push(e))}function Tt(){Et.inBatch++}function jt(){if(0==--Et.inBatch){Yt();for(var e=Et.pendingUnobservations,t=0;t<e.length;t++){var n=e[t];n.isPendingUnobservation=!1,0===n.observers.length&&(n.isBeingObserved&&(n.isBeingObserved=!1,n.onBecomeUnobserved()),n instanceof F&&n.suspend())}Et.pendingUnobservations=[]}}function At(e){var t=Et.trackingDerivation;return null!==t?(t.runId!==e.lastAccessedBy&&(e.lastAccessedBy=t.runId,t.newObserving[t.unboundDepsCount++]=e,e.isBeingObserved||(e.isBeingObserved=!0,e.onBecomeObserved())),!0):(0===e.observers.length&&Et.inBatch>0&&Ct(e),!1)}function It(e,t){if(console.log(\"[mobx.trace] '\"+e.name+\"' is invalidated due to a change in: '\"+t.name+\"'\"),e.isTracing===bt.BREAK){var n=[];!function e(t,n,r){if(n.length>=1e3)return void n.push(\"(and many more)\");n.push(\"\"+new Array(r).join(\"\\t\")+t.name);t.dependencies&&t.dependencies.forEach(function(t){return e(t,n,r+1)})}((r=e,St(Re(r,o))),n,1),new Function(\"debugger;\\n/*\\nTracing '\"+e.name+\"'\\n\\nYou are entering this break point because derivation '\"+e.name+\"' is being traced and '\"+t.name+\"' is now forcing it to update.\\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\\n\\n\"+(e instanceof F?e.derivation.toString():\"\")+\"\\n\\nThe dependencies for this derivation are:\\n\\n\"+n.join(\"\\n\")+\"\\n*/\\n    \")()}var r,o}!function(e){e[e.NOT_TRACKING=-1]=\"NOT_TRACKING\",e[e.UP_TO_DATE=0]=\"UP_TO_DATE\",e[e.POSSIBLY_STALE=1]=\"POSSIBLY_STALE\",e[e.STALE=2]=\"STALE\"}(vt||(vt={})),function(e){e[e.NONE=0]=\"NONE\",e[e.LOG=1]=\"LOG\",e[e.BREAK=2]=\"BREAK\"}(bt||(bt={}));var Pt=function(){return function(e){this.cause=e}}();function Rt(e){return e instanceof Pt}function Nt(e){switch(e.dependenciesState){case vt.UP_TO_DATE:return!1;case vt.NOT_TRACKING:case vt.STALE:return!0;case vt.POSSIBLY_STALE:for(var t=Ut(),n=e.observing,r=n.length,o=0;o<r;o++){var i=n[o];if(U(i)){if(Et.disableErrorBoundaries)i.get();else try{i.get()}catch(e){return Bt(t),!0}if(e.dependenciesState===vt.STALE)return Bt(t),!0}}return zt(e),Bt(t),!1}}function Lt(e){var t=e.observers.length>0;Et.computationDepth>0&&t&&ot(!1),Et.allowStateChanges||!t&&\"strict\"!==Et.enforceActions||ot(!1)}function Mt(e,t,n){zt(e),e.newObserving=new Array(e.observing.length+100),e.unboundDepsCount=0,e.runId=++Et.runId;var r,o=Et.trackingDerivation;if(Et.trackingDerivation=e,!0===Et.disableErrorBoundaries)r=t.call(n);else try{r=t.call(n)}catch(e){r=new Pt(e)}return Et.trackingDerivation=o,function(e){for(var t=e.observing,n=e.observing=e.newObserving,r=vt.UP_TO_DATE,o=0,i=e.unboundDepsCount,a=0;a<i;a++){var s=n[a];0===s.diffValue&&(s.diffValue=1,o!==a&&(n[o]=s),o++),s.dependenciesState>r&&(r=s.dependenciesState)}n.length=o,e.newObserving=null,i=t.length;for(;i--;){var s=t[i];0===s.diffValue&&Ot(s,e),s.diffValue=0}for(;o--;){var s=n[o];1===s.diffValue&&(s.diffValue=0,_t(s,e))}r!==vt.UP_TO_DATE&&(e.dependenciesState=r,e.onBecomeStale())}(e),r}function Dt(e){var t=e.observing;e.observing=[];for(var n=t.length;n--;)Ot(t[n],e);e.dependenciesState=vt.NOT_TRACKING}function Ft(e){var t=Ut(),n=e();return Bt(t),n}function Ut(){var e=Et.trackingDerivation;return Et.trackingDerivation=null,e}function Bt(e){Et.trackingDerivation=e}function zt(e){if(e.dependenciesState!==vt.UP_TO_DATE){e.dependenciesState=vt.UP_TO_DATE;for(var t=e.observing,n=t.length;n--;)t[n].lowestObserverState=vt.UP_TO_DATE}}function $t(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=!1;\"boolean\"==typeof e[e.length-1]&&(n=e.pop());var r=function(e){switch(e.length){case 0:return Et.trackingDerivation;case 1:return Re(e[0]);case 2:return Re(e[0],e[1])}}(e);if(!r)return ot(!1);r.isTracing===bt.NONE&&console.log(\"[mobx.trace] '\"+r.name+\"' tracing enabled\"),r.isTracing=n?bt.BREAK:bt.LOG}var Wt=function(){function e(e,t,n){void 0===e&&(e=\"Reaction@\"+rt()),this.name=e,this.onInvalidate=t,this.errorHandler=n,this.observing=[],this.newObserving=[],this.dependenciesState=vt.NOT_TRACKING,this.diffValue=0,this.runId=0,this.unboundDepsCount=0,this.__mapid=\"#\"+rt(),this.isDisposed=!1,this._isScheduled=!1,this._isTrackPending=!1,this._isRunning=!1,this.isTracing=bt.NONE}return e.prototype.onBecomeStale=function(){this.schedule()},e.prototype.schedule=function(){this._isScheduled||(this._isScheduled=!0,Et.pendingReactions.push(this),Yt())},e.prototype.isScheduled=function(){return this._isScheduled},e.prototype.runReaction=function(){if(!this.isDisposed){if(Tt(),this._isScheduled=!1,Nt(this)){this._isTrackPending=!0;try{this.onInvalidate(),this._isTrackPending&&d()&&h({name:this.name,type:\"scheduled-reaction\"})}catch(e){this.reportExceptionInDerivation(e)}}jt()}},e.prototype.track=function(e){Tt();var t,n=d();n&&(t=Date.now(),m({name:this.name,type:\"reaction\"})),this._isRunning=!0;var r=Mt(this,e,void 0);this._isRunning=!1,this._isTrackPending=!1,this.isDisposed&&Dt(this),Rt(r)&&this.reportExceptionInDerivation(r.cause),n&&y({time:Date.now()-t}),jt()},e.prototype.reportExceptionInDerivation=function(e){var t=this;if(this.errorHandler)this.errorHandler(e,this);else{if(Et.disableErrorBoundaries)throw e;var n=\"[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '\"+this;console.error(n,e),d()&&h({type:\"error\",name:this.name,message:n,error:\"\"+e}),Et.globalReactionErrorHandlers.forEach(function(n){return n(e,t)})}},e.prototype.dispose=function(){this.isDisposed||(this.isDisposed=!0,this._isRunning||(Tt(),Dt(this),jt()))},e.prototype.getDisposer=function(){var e=this.dispose.bind(this);return e.$mobx=this,e},e.prototype.toString=function(){return\"Reaction[\"+this.name+\"]\"},e.prototype.trace=function(e){void 0===e&&(e=!1),$t(this,e)},e}();var qt=100,Ht=function(e){return e()};function Yt(){Et.inBatch>0||Et.isRunningReactions||Ht(Vt)}function Vt(){Et.isRunningReactions=!0;for(var e=Et.pendingReactions,t=0;e.length>0;){++t===qt&&(console.error(\"Reaction doesn't converge to a stable state after \"+qt+\" iterations. Probably there is a cycle in the reactive function: \"+e[0]),e.splice(0));for(var n=e.splice(0),r=0,o=n.length;r<o;r++)n[r].runReaction()}Et.isRunningReactions=!1}var Qt=dt(\"Reaction\",Wt);function Gt(e){var t=Ht;Ht=function(n){return e(function(){return t(n)})}}function Xt(e,t,n,r){return\"function\"==typeof n?function(e,t,n,r){return Ne(e,t).observe(n,r)}(e,t,n,r):function(e,t,n){return Ne(e).observe(t,n)}(e,t,n)}function Kt(e){var t=e.enforceActions,n=e.computedRequiresReaction,r=e.disableErrorBoundaries,o=e.arrayBuffer,i=e.reactionScheduler;if(void 0!==t){var a=void 0;switch(t){case!0:case\"observed\":a=!0;break;case!1:case\"never\":a=!1;break;case\"strict\":case\"always\":a=\"strict\";break;default:fail(\"Invalid value for 'enforceActions': '\"+t+\"', expected 'never', 'always' or 'observed'\")}Et.enforceActions=a,Et.allowStateChanges=!0!==a&&\"strict\"!==a}void 0!==n&&(Et.computedRequiresReaction=!!n),!0===e.isolateGlobalState&&((Et.pendingReactions.length||Et.inBatch||Et.isRunningReactions)&&ot(\"isolateGlobalState should be called before MobX is running any reactions\"),kt=!0,xt&&(0==--nt().__mobxInstanceCount&&(nt().__mobxGlobals=void 0),Et=new wt)),void 0!==r&&(!0===r&&console.warn(\"WARNING: Debug feature only. MobX will NOT recover from errors if this is on.\"),Et.disableErrorBoundaries=!!r),\"number\"==typeof o&&Xe(o),i&&Gt(i)}\"object\"==typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__&&__MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx({spy:v,extras:{getDebugName:Le}});var Jt=\"$mobx\"}).call(this,n(6),n(4))},function(e,t,n){var r=n(58)(\"wks\"),o=n(32),i=n(5).Symbol,a=\"function\"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)(\"Symbol.\"+e))}).store=r},function(e,t,n){\"use strict\";var r=n(47),o=[\"kind\",\"resolve\",\"construct\",\"instanceOf\",\"predicate\",\"represent\",\"defaultStyle\",\"styleAliases\"],i=[\"scalar\",\"sequence\",\"mapping\"];e.exports=function(e,t){var n,a;if(t=t||{},Object.keys(t).forEach(function(t){if(-1===o.indexOf(t))throw new r('Unknown option \"'+t+'\" is met in definition of \"'+e+'\" YAML type.')}),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=(n=t.styleAliases||null,a={},null!==n&&Object.keys(n).forEach(function(e){n[e].forEach(function(t){a[String(t)]=e})}),a),-1===i.indexOf(this.kind))throw new r('Unknown kind \"'+this.kind+'\" is specified for \"'+e+'\" YAML type.')}},function(e,t){var n;n=function(){return this}();try{n=n||new Function(\"return this\")()}catch(e){\"object\"==typeof window&&(n=window)}e.exports=n},function(e,t){var n=e.exports=\"undefined\"!=typeof window&&window.Math==Math?window:\"undefined\"!=typeof self&&self.Math==Math?self:Function(\"return this\")();\"number\"==typeof __g&&(__g=n)},function(e,t){var n,r,o=e.exports={};function i(){throw new Error(\"setTimeout has not been defined\")}function a(){throw new Error(\"clearTimeout has not been defined\")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n=\"function\"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r=\"function\"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var l,c=[],u=!1,p=-1;function f(){u&&l&&(u=!1,l.length?c=l.concat(c):p=-1,c.length&&d())}function d(){if(!u){var e=s(f);u=!0;for(var t=c.length;t;){for(l=c,c=[];++p<t;)l&&l[p].run();p=-1,t=c.length}l=null,u=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===a||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function h(e,t){this.fun=e,this.array=t}function m(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new h(e,t)),1!==c.length||u||s(d)},h.prototype.run=function(){this.fun.apply(null,this.array)},o.title=\"browser\",o.browser=!0,o.env={},o.argv=[],o.version=\"\",o.versions={},o.on=m,o.addListener=m,o.once=m,o.off=m,o.removeListener=m,o.removeAllListeners=m,o.emit=m,o.prependListener=m,o.prependOnceListener=m,o.listeners=function(e){return[]},o.binding=function(e){throw new Error(\"process.binding is not supported\")},o.cwd=function(){return\"/\"},o.chdir=function(e){throw new Error(\"process.chdir is not supported\")},o.umask=function(){return 0}},function(e,t){var n=e.exports={version:\"2.5.7\"};\"number\"==typeof __e&&(__e=n)},function(e,t){e.exports=function(e){return\"object\"==typeof e?null!==e:\"function\"==typeof e}},function(e,t,n){\"use strict\";(function(e){\n/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>\n * @license  MIT\n */\nvar r=n(191),o=n(192),i=n(101);function a(){return l.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()<t)throw new RangeError(\"Invalid typed array length\");return l.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=l.prototype:(null===e&&(e=new l(t)),e.length=t),e}function l(e,t,n){if(!(l.TYPED_ARRAY_SUPPORT||this instanceof l))return new l(e,t,n);if(\"number\"==typeof e){if(\"string\"==typeof t)throw new Error(\"If encoding is specified then the first argument must be a string\");return p(this,e)}return c(this,e,t,n)}function c(e,t,n,r){if(\"number\"==typeof t)throw new TypeError('\"value\" argument must not be a number');return\"undefined\"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError(\"'offset' is out of bounds\");if(t.byteLength<n+(r||0))throw new RangeError(\"'length' is out of bounds\");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);l.TYPED_ARRAY_SUPPORT?(e=t).__proto__=l.prototype:e=f(e,t);return e}(e,t,n,r):\"string\"==typeof t?function(e,t,n){\"string\"==typeof n&&\"\"!==n||(n=\"utf8\");if(!l.isEncoding(n))throw new TypeError('\"encoding\" must be a valid string encoding');var r=0|h(t,n),o=(e=s(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(l.isBuffer(t)){var n=0|d(t.length);return 0===(e=s(e,n)).length?e:(t.copy(e,0,0,n),e)}if(t){if(\"undefined\"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||\"length\"in t)return\"number\"!=typeof t.length||(r=t.length)!=r?s(e,0):f(e,t);if(\"Buffer\"===t.type&&i(t.data))return f(e,t.data)}var r;throw new TypeError(\"First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.\")}(e,t)}function u(e){if(\"number\"!=typeof e)throw new TypeError('\"size\" argument must be a number');if(e<0)throw new RangeError('\"size\" argument must not be negative')}function p(e,t){if(u(t),e=s(e,t<0?0:0|d(t)),!l.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function f(e,t){var n=t.length<0?0:0|d(t.length);e=s(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function d(e){if(e>=a())throw new RangeError(\"Attempt to allocate Buffer larger than maximum size: 0x\"+a().toString(16)+\" bytes\");return 0|e}function h(e,t){if(l.isBuffer(e))return e.length;if(\"undefined\"!=typeof ArrayBuffer&&\"function\"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;\"string\"!=typeof e&&(e=\"\"+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case\"ascii\":case\"latin1\":case\"binary\":return n;case\"utf8\":case\"utf-8\":case void 0:return B(e).length;case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return 2*n;case\"hex\":return n>>>1;case\"base64\":return z(e).length;default:if(r)return B(e).length;t=(\"\"+t).toLowerCase(),r=!0}}function m(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function g(e,t,n,r,o){if(0===e.length)return-1;if(\"string\"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if(\"string\"==typeof t&&(t=l.from(t,r)),l.isBuffer(t))return 0===t.length?-1:y(e,t,n,r,o);if(\"number\"==typeof t)return t&=255,l.TYPED_ARRAY_SUPPORT&&\"function\"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):y(e,[t],n,r,o);throw new TypeError(\"val must be string, number or Buffer\")}function y(e,t,n,r,o){var i,a=1,s=e.length,l=t.length;if(void 0!==r&&(\"ucs2\"===(r=String(r).toLowerCase())||\"ucs-2\"===r||\"utf16le\"===r||\"utf-16le\"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,l/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var u=-1;for(i=n;i<s;i++)if(c(e,i)===c(t,-1===u?0:i-u)){if(-1===u&&(u=i),i-u+1===l)return u*a}else-1!==u&&(i-=i-u),u=-1}else for(n+l>s&&(n=s-l),i=n;i>=0;i--){for(var p=!0,f=0;f<l;f++)if(c(e,i+f)!==c(t,f)){p=!1;break}if(p)return i}return-1}function v(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError(\"Invalid hex string\");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[n+a]=s}return a}function b(e,t,n,r){return $(B(t,e.length-n),e,n,r)}function w(e,t,n,r){return $(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function x(e,t,n,r){return w(e,t,n,r)}function k(e,t,n,r){return $(z(t),e,n,r)}function E(e,t,n,r){return $(function(e,t){for(var n,r,o,i=[],a=0;a<e.length&&!((t-=2)<0);++a)n=e.charCodeAt(a),r=n>>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function _(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o<n;){var i,a,s,l,c=e[o],u=null,p=c>239?4:c>223?3:c>191?2:1;if(o+p<=n)switch(p){case 1:c<128&&(u=c);break;case 2:128==(192&(i=e[o+1]))&&(l=(31&c)<<6|63&i)>127&&(u=l);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(l=(15&c)<<12|(63&i)<<6|63&a)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(l=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&l<1114112&&(u=l)}null===u?(u=65533,p=1):u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u),o+=p}return function(e){var t=e.length;if(t<=O)return String.fromCharCode.apply(String,e);var n=\"\",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=O));return n}(r)}t.Buffer=l,t.SlowBuffer=function(e){+e!=e&&(e=0);return l.alloc(+e)},t.INSPECT_MAX_BYTES=50,l.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&\"function\"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=a(),l.poolSize=8192,l._augment=function(e){return e.__proto__=l.prototype,e},l.from=function(e,t,n){return c(null,e,t,n)},l.TYPED_ARRAY_SUPPORT&&(l.prototype.__proto__=Uint8Array.prototype,l.__proto__=Uint8Array,\"undefined\"!=typeof Symbol&&Symbol.species&&l[Symbol.species]===l&&Object.defineProperty(l,Symbol.species,{value:null,configurable:!0})),l.alloc=function(e,t,n){return function(e,t,n,r){return u(t),t<=0?s(e,t):void 0!==n?\"string\"==typeof r?s(e,t).fill(n,r):s(e,t).fill(n):s(e,t)}(null,e,t,n)},l.allocUnsafe=function(e){return p(null,e)},l.allocUnsafeSlow=function(e){return p(null,e)},l.isBuffer=function(e){return!(null==e||!e._isBuffer)},l.compare=function(e,t){if(!l.isBuffer(e)||!l.isBuffer(t))throw new TypeError(\"Arguments must be Buffers\");if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0},l.isEncoding=function(e){switch(String(e).toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"latin1\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return!0;default:return!1}},l.concat=function(e,t){if(!i(e))throw new TypeError('\"list\" argument must be an Array of Buffers');if(0===e.length)return l.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=l.allocUnsafe(t),o=0;for(n=0;n<e.length;++n){var a=e[n];if(!l.isBuffer(a))throw new TypeError('\"list\" argument must be an Array of Buffers');a.copy(r,o),o+=a.length}return r},l.byteLength=h,l.prototype._isBuffer=!0,l.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError(\"Buffer size must be a multiple of 16-bits\");for(var t=0;t<e;t+=2)m(this,t,t+1);return this},l.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError(\"Buffer size must be a multiple of 32-bits\");for(var t=0;t<e;t+=4)m(this,t,t+3),m(this,t+1,t+2);return this},l.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError(\"Buffer size must be a multiple of 64-bits\");for(var t=0;t<e;t+=8)m(this,t,t+7),m(this,t+1,t+6),m(this,t+2,t+5),m(this,t+3,t+4);return this},l.prototype.toString=function(){var e=0|this.length;return 0===e?\"\":0===arguments.length?_(this,0,e):function(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return\"\";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return\"\";if((n>>>=0)<=(t>>>=0))return\"\";for(e||(e=\"utf8\");;)switch(e){case\"hex\":return j(this,t,n);case\"utf8\":case\"utf-8\":return _(this,t,n);case\"ascii\":return C(this,t,n);case\"latin1\":case\"binary\":return T(this,t,n);case\"base64\":return S(this,t,n);case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return A(this,t,n);default:if(r)throw new TypeError(\"Unknown encoding: \"+e);e=(e+\"\").toLowerCase(),r=!0}}.apply(this,arguments)},l.prototype.equals=function(e){if(!l.isBuffer(e))throw new TypeError(\"Argument must be a Buffer\");return this===e||0===l.compare(this,e)},l.prototype.inspect=function(){var e=\"\",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString(\"hex\",0,n).match(/.{2}/g).join(\" \"),this.length>n&&(e+=\" ... \")),\"<Buffer \"+e+\">\"},l.prototype.compare=function(e,t,n,r,o){if(!l.isBuffer(e))throw new TypeError(\"Argument must be a Buffer\");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError(\"out of range index\");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),u=e.slice(t,n),p=0;p<s;++p)if(c[p]!==u[p]){i=c[p],a=u[p];break}return i<a?-1:a<i?1:0},l.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},l.prototype.indexOf=function(e,t,n){return g(this,e,t,n,!0)},l.prototype.lastIndexOf=function(e,t,n){return g(this,e,t,n,!1)},l.prototype.write=function(e,t,n,r){if(void 0===t)r=\"utf8\",n=this.length,t=0;else if(void 0===n&&\"string\"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error(\"Buffer.write(string, encoding, offset[, length]) is no longer supported\");t|=0,isFinite(n)?(n|=0,void 0===r&&(r=\"utf8\")):(r=n,n=void 0)}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError(\"Attempt to write outside buffer bounds\");r||(r=\"utf8\");for(var i=!1;;)switch(r){case\"hex\":return v(this,e,t,n);case\"utf8\":case\"utf-8\":return b(this,e,t,n);case\"ascii\":return w(this,e,t,n);case\"latin1\":case\"binary\":return x(this,e,t,n);case\"base64\":return k(this,e,t,n);case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return E(this,e,t,n);default:if(i)throw new TypeError(\"Unknown encoding: \"+r);r=(\"\"+r).toLowerCase(),i=!0}},l.prototype.toJSON=function(){return{type:\"Buffer\",data:Array.prototype.slice.call(this._arr||this,0)}};var O=4096;function C(e,t,n){var r=\"\";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(127&e[o]);return r}function T(e,t,n){var r=\"\";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(e[o]);return r}function j(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var o=\"\",i=t;i<n;++i)o+=U(e[i]);return o}function A(e,t,n){for(var r=e.slice(t,n),o=\"\",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function I(e,t,n){if(e%1!=0||e<0)throw new RangeError(\"offset is not uint\");if(e+t>n)throw new RangeError(\"Trying to access beyond buffer length\")}function P(e,t,n,r,o,i){if(!l.isBuffer(e))throw new TypeError('\"buffer\" argument must be a Buffer instance');if(t>o||t<i)throw new RangeError('\"value\" argument is out of bounds');if(n+r>e.length)throw new RangeError(\"Index out of range\")}function R(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o<i;++o)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function N(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o<i;++o)e[n+o]=t>>>8*(r?o:3-o)&255}function L(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError(\"Index out of range\");if(n<0)throw new RangeError(\"Index out of range\")}function M(e,t,n,r,i){return i||L(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function D(e,t,n,r,i){return i||L(e,0,n,8),o.write(e,t,n,r,52,8),n+8}l.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),l.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=l.prototype;else{var o=t-e;n=new l(o,void 0);for(var i=0;i<o;++i)n[i]=this[i+e]}return n},l.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r},l.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e+--t],o=1;t>0&&(o*=256);)r+=this[e+--t]*o;return r},l.prototype.readUInt8=function(e,t){return t||I(e,1,this.length),this[e]},l.prototype.readUInt16LE=function(e,t){return t||I(e,2,this.length),this[e]|this[e+1]<<8},l.prototype.readUInt16BE=function(e,t){return t||I(e,2,this.length),this[e]<<8|this[e+1]},l.prototype.readUInt32LE=function(e,t){return t||I(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},l.prototype.readUInt32BE=function(e,t){return t||I(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},l.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r>=(o*=128)&&(r-=Math.pow(2,8*t)),r},l.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},l.prototype.readInt8=function(e,t){return t||I(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},l.prototype.readInt16LE=function(e,t){t||I(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt16BE=function(e,t){t||I(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt32LE=function(e,t){return t||I(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},l.prototype.readInt32BE=function(e,t){return t||I(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},l.prototype.readFloatLE=function(e,t){return t||I(e,4,this.length),o.read(this,e,!0,23,4)},l.prototype.readFloatBE=function(e,t){return t||I(e,4,this.length),o.read(this,e,!1,23,4)},l.prototype.readDoubleLE=function(e,t){return t||I(e,8,this.length),o.read(this,e,!0,52,8)},l.prototype.readDoubleBE=function(e,t){return t||I(e,8,this.length),o.read(this,e,!1,52,8)},l.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||P(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i<n&&(o*=256);)this[t+i]=e/o&255;return t+n},l.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||P(this,e,t,n,Math.pow(2,8*n)-1,0);var o=n-1,i=1;for(this[t+o]=255&e;--o>=0&&(i*=256);)this[t+o]=e/i&255;return t+n},l.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,1,255,0),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},l.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):R(this,e,t,!0),t+2},l.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):R(this,e,t,!1),t+2},l.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):N(this,e,t,!0),t+4},l.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},l.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);P(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i<n&&(a*=256);)e<0&&0===s&&0!==this[t+i-1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},l.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);P(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},l.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,1,127,-128),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):R(this,e,t,!0),t+2},l.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):R(this,e,t,!1),t+2},l.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,2147483647,-2147483648),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):N(this,e,t,!0),t+4},l.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},l.prototype.writeFloatLE=function(e,t,n){return M(this,e,t,!0,n)},l.prototype.writeFloatBE=function(e,t,n){return M(this,e,t,!1,n)},l.prototype.writeDoubleLE=function(e,t,n){return D(this,e,t,!0,n)},l.prototype.writeDoubleBE=function(e,t,n){return D(this,e,t,!1,n)},l.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError(\"targetStart out of bounds\");if(n<0||n>=this.length)throw new RangeError(\"sourceStart out of bounds\");if(r<0)throw new RangeError(\"sourceEnd out of bounds\");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var o,i=r-n;if(this===e&&n<t&&t<r)for(o=i-1;o>=0;--o)e[o+t]=this[o+n];else if(i<1e3||!l.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)e[o+t]=this[o+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+i),t);return i},l.prototype.fill=function(e,t,n,r){if(\"string\"==typeof e){if(\"string\"==typeof t?(r=t,t=0,n=this.length):\"string\"==typeof n&&(r=n,n=this.length),1===e.length){var o=e.charCodeAt(0);o<256&&(e=o)}if(void 0!==r&&\"string\"!=typeof r)throw new TypeError(\"encoding must be a string\");if(\"string\"==typeof r&&!l.isEncoding(r))throw new TypeError(\"Unknown encoding: \"+r)}else\"number\"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError(\"Out of range index\");if(n<=t)return this;var i;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),\"number\"==typeof e)for(i=t;i<n;++i)this[i]=e;else{var a=l.isBuffer(e)?e:B(new l(e,r).toString()),s=a.length;for(i=0;i<n-t;++i)this[i+t]=a[i%s]}return this};var F=/[^+\\/0-9A-Za-z-_]/g;function U(e){return e<16?\"0\"+e.toString(16):e.toString(16)}function B(e,t){var n;t=t||1/0;for(var r=e.length,o=null,i=[],a=0;a<r;++a){if((n=e.charCodeAt(a))>55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error(\"Invalid code point\");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function z(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\\s+|\\s+$/g,\"\")}(e).replace(F,\"\")).length<2)return\"\";for(;e.length%4!=0;)e+=\"=\";return e}(e))}function $(e,t,n,r){for(var o=0;o<r&&!(o+n>=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(4))},function(e,t,n){\"use strict\";var r=n(184),o=n(186);function i(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}t.parse=b,t.resolve=function(e,t){return b(e,!1,!0).resolve(t)},t.resolveObject=function(e,t){return e?b(e,!1,!0).resolveObject(t):t},t.format=function(e){o.isString(e)&&(e=b(e));return e instanceof i?e.format():i.prototype.format.call(e)},t.Url=i;var a=/^([a-z0-9.+-]+:)/i,s=/:[0-9]*$/,l=/^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,c=[\"{\",\"}\",\"|\",\"\\\\\",\"^\",\"`\"].concat([\"<\",\">\",'\"',\"`\",\" \",\"\\r\",\"\\n\",\"\\t\"]),u=[\"'\"].concat(c),p=[\"%\",\"/\",\"?\",\";\",\"#\"].concat(u),f=[\"/\",\"?\",\"#\"],d=/^[+a-z0-9A-Z_-]{0,63}$/,h=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,m={javascript:!0,\"javascript:\":!0},g={javascript:!0,\"javascript:\":!0},y={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,\"http:\":!0,\"https:\":!0,\"ftp:\":!0,\"gopher:\":!0,\"file:\":!0},v=n(187);function b(e,t,n){if(e&&o.isObject(e)&&e instanceof i)return e;var r=new i;return r.parse(e,t,n),r}i.prototype.parse=function(e,t,n){if(!o.isString(e))throw new TypeError(\"Parameter 'url' must be a string, not \"+typeof e);var i=e.indexOf(\"?\"),s=-1!==i&&i<e.indexOf(\"#\")?\"?\":\"#\",c=e.split(s);c[0]=c[0].replace(/\\\\/g,\"/\");var b=e=c.join(s);if(b=b.trim(),!n&&1===e.split(\"#\").length){var w=l.exec(b);if(w)return this.path=b,this.href=b,this.pathname=w[1],w[2]?(this.search=w[2],this.query=t?v.parse(this.search.substr(1)):this.search.substr(1)):t&&(this.search=\"\",this.query={}),this}var x=a.exec(b);if(x){var k=(x=x[0]).toLowerCase();this.protocol=k,b=b.substr(x.length)}if(n||x||b.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)){var E=\"//\"===b.substr(0,2);!E||x&&g[x]||(b=b.substr(2),this.slashes=!0)}if(!g[x]&&(E||x&&!y[x])){for(var S,_,O=-1,C=0;C<f.length;C++){-1!==(T=b.indexOf(f[C]))&&(-1===O||T<O)&&(O=T)}-1!==(_=-1===O?b.lastIndexOf(\"@\"):b.lastIndexOf(\"@\",O))&&(S=b.slice(0,_),b=b.slice(_+1),this.auth=decodeURIComponent(S)),O=-1;for(C=0;C<p.length;C++){var T;-1!==(T=b.indexOf(p[C]))&&(-1===O||T<O)&&(O=T)}-1===O&&(O=b.length),this.host=b.slice(0,O),b=b.slice(O),this.parseHost(),this.hostname=this.hostname||\"\";var j=\"[\"===this.hostname[0]&&\"]\"===this.hostname[this.hostname.length-1];if(!j)for(var A=this.hostname.split(/\\./),I=(C=0,A.length);C<I;C++){var P=A[C];if(P&&!P.match(d)){for(var R=\"\",N=0,L=P.length;N<L;N++)P.charCodeAt(N)>127?R+=\"x\":R+=P[N];if(!R.match(d)){var M=A.slice(0,C),D=A.slice(C+1),F=P.match(h);F&&(M.push(F[1]),D.unshift(F[2])),D.length&&(b=\"/\"+D.join(\".\")+b),this.hostname=M.join(\".\");break}}}this.hostname.length>255?this.hostname=\"\":this.hostname=this.hostname.toLowerCase(),j||(this.hostname=r.toASCII(this.hostname));var U=this.port?\":\"+this.port:\"\",B=this.hostname||\"\";this.host=B+U,this.href+=this.host,j&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),\"/\"!==b[0]&&(b=\"/\"+b))}if(!m[k])for(C=0,I=u.length;C<I;C++){var z=u[C];if(-1!==b.indexOf(z)){var $=encodeURIComponent(z);$===z&&($=escape(z)),b=b.split(z).join($)}}var W=b.indexOf(\"#\");-1!==W&&(this.hash=b.substr(W),b=b.slice(0,W));var q=b.indexOf(\"?\");if(-1!==q?(this.search=b.substr(q),this.query=b.substr(q+1),t&&(this.query=v.parse(this.query)),b=b.slice(0,q)):t&&(this.search=\"\",this.query={}),b&&(this.pathname=b),y[k]&&this.hostname&&!this.pathname&&(this.pathname=\"/\"),this.pathname||this.search){U=this.pathname||\"\";var H=this.search||\"\";this.path=U+H}return this.href=this.format(),this},i.prototype.format=function(){var e=this.auth||\"\";e&&(e=(e=encodeURIComponent(e)).replace(/%3A/i,\":\"),e+=\"@\");var t=this.protocol||\"\",n=this.pathname||\"\",r=this.hash||\"\",i=!1,a=\"\";this.host?i=e+this.host:this.hostname&&(i=e+(-1===this.hostname.indexOf(\":\")?this.hostname:\"[\"+this.hostname+\"]\"),this.port&&(i+=\":\"+this.port)),this.query&&o.isObject(this.query)&&Object.keys(this.query).length&&(a=v.stringify(this.query));var s=this.search||a&&\"?\"+a||\"\";return t&&\":\"!==t.substr(-1)&&(t+=\":\"),this.slashes||(!t||y[t])&&!1!==i?(i=\"//\"+(i||\"\"),n&&\"/\"!==n.charAt(0)&&(n=\"/\"+n)):i||(i=\"\"),r&&\"#\"!==r.charAt(0)&&(r=\"#\"+r),s&&\"?\"!==s.charAt(0)&&(s=\"?\"+s),t+i+(n=n.replace(/[?#]/g,function(e){return encodeURIComponent(e)}))+(s=s.replace(\"#\",\"%23\"))+r},i.prototype.resolve=function(e){return this.resolveObject(b(e,!1,!0)).format()},i.prototype.resolveObject=function(e){if(o.isString(e)){var t=new i;t.parse(e,!1,!0),e=t}for(var n=new i,r=Object.keys(this),a=0;a<r.length;a++){var s=r[a];n[s]=this[s]}if(n.hash=e.hash,\"\"===e.href)return n.href=n.format(),n;if(e.slashes&&!e.protocol){for(var l=Object.keys(e),c=0;c<l.length;c++){var u=l[c];\"protocol\"!==u&&(n[u]=e[u])}return y[n.protocol]&&n.hostname&&!n.pathname&&(n.path=n.pathname=\"/\"),n.href=n.format(),n}if(e.protocol&&e.protocol!==n.protocol){if(!y[e.protocol]){for(var p=Object.keys(e),f=0;f<p.length;f++){var d=p[f];n[d]=e[d]}return n.href=n.format(),n}if(n.protocol=e.protocol,e.host||g[e.protocol])n.pathname=e.pathname;else{for(var h=(e.pathname||\"\").split(\"/\");h.length&&!(e.host=h.shift()););e.host||(e.host=\"\"),e.hostname||(e.hostname=\"\"),\"\"!==h[0]&&h.unshift(\"\"),h.length<2&&h.unshift(\"\"),n.pathname=h.join(\"/\")}if(n.search=e.search,n.query=e.query,n.host=e.host||\"\",n.auth=e.auth,n.hostname=e.hostname||e.host,n.port=e.port,n.pathname||n.search){var m=n.pathname||\"\",v=n.search||\"\";n.path=m+v}return n.slashes=n.slashes||e.slashes,n.href=n.format(),n}var b=n.pathname&&\"/\"===n.pathname.charAt(0),w=e.host||e.pathname&&\"/\"===e.pathname.charAt(0),x=w||b||n.host&&e.pathname,k=x,E=n.pathname&&n.pathname.split(\"/\")||[],S=(h=e.pathname&&e.pathname.split(\"/\")||[],n.protocol&&!y[n.protocol]);if(S&&(n.hostname=\"\",n.port=null,n.host&&(\"\"===E[0]?E[0]=n.host:E.unshift(n.host)),n.host=\"\",e.protocol&&(e.hostname=null,e.port=null,e.host&&(\"\"===h[0]?h[0]=e.host:h.unshift(e.host)),e.host=null),x=x&&(\"\"===h[0]||\"\"===E[0])),w)n.host=e.host||\"\"===e.host?e.host:n.host,n.hostname=e.hostname||\"\"===e.hostname?e.hostname:n.hostname,n.search=e.search,n.query=e.query,E=h;else if(h.length)E||(E=[]),E.pop(),E=E.concat(h),n.search=e.search,n.query=e.query;else if(!o.isNullOrUndefined(e.search)){if(S)n.hostname=n.host=E.shift(),(j=!!(n.host&&n.host.indexOf(\"@\")>0)&&n.host.split(\"@\"))&&(n.auth=j.shift(),n.host=n.hostname=j.shift());return n.search=e.search,n.query=e.query,o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:\"\")+(n.search?n.search:\"\")),n.href=n.format(),n}if(!E.length)return n.pathname=null,n.search?n.path=\"/\"+n.search:n.path=null,n.href=n.format(),n;for(var _=E.slice(-1)[0],O=(n.host||e.host||E.length>1)&&(\".\"===_||\"..\"===_)||\"\"===_,C=0,T=E.length;T>=0;T--)\".\"===(_=E[T])?E.splice(T,1):\"..\"===_?(E.splice(T,1),C++):C&&(E.splice(T,1),C--);if(!x&&!k)for(;C--;C)E.unshift(\"..\");!x||\"\"===E[0]||E[0]&&\"/\"===E[0].charAt(0)||E.unshift(\"\"),O&&\"/\"!==E.join(\"/\").substr(-1)&&E.push(\"\");var j,A=\"\"===E[0]||E[0]&&\"/\"===E[0].charAt(0);S&&(n.hostname=n.host=A?\"\":E.length?E.shift():\"\",(j=!!(n.host&&n.host.indexOf(\"@\")>0)&&n.host.split(\"@\"))&&(n.auth=j.shift(),n.host=n.hostname=j.shift()));return(x=x||n.host&&E.length)&&!A&&E.unshift(\"\"),E.length?n.pathname=E.join(\"/\"):(n.pathname=null,n.path=null),o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:\"\")+(n.search?n.search:\"\")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},i.prototype.parseHost=function(){var e=this.host,t=s.exec(e);t&&(\":\"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){e.exports=n(182)()},function(e,t,n){var r;\n/*!\n  Copyright (c) 2017 Jed Watson.\n  Licensed under the MIT License (MIT), see\n  http://jedwatson.github.io/classnames\n*/\n/*!\n  Copyright (c) 2017 Jed Watson.\n  Licensed under the MIT License (MIT), see\n  http://jedwatson.github.io/classnames\n*/\n!function(){\"use strict\";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if(\"string\"===i||\"number\"===i)e.push(r);else if(Array.isArray(r)&&r.length){var a=o.apply(null,r);a&&e.push(a)}else if(\"object\"===i)for(var s in r)n.call(r,s)&&r[s]&&e.push(s)}}return e.join(\" \")}e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,t,n){\"use strict\";!function e(){if(\"undefined\"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&\"function\"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),e.exports=n(179)},function(e,t,n){var r=n(8);e.exports=function(e){if(!r(e))throw TypeError(e+\" is not an object!\");return e}},function(e,t,n){\"use strict\";var r=n(246);function o(e,t,n){if(3===arguments.length)return o.set(e,t,n);if(2===arguments.length)return o.get(e,t);var r=o.bind(o,e);for(var i in o)o.hasOwnProperty(i)&&(r[i]=o[i].bind(r,e));return r}e.exports=o,o.get=function(e,t){for(var n=Array.isArray(t)?t:o.parse(t),r=0;r<n.length;++r){var i=n[r];if(!(\"object\"==typeof e&&i in e))throw new Error(\"Invalid reference token: \"+i);e=e[i]}return e},o.set=function(e,t,n){for(var r=Array.isArray(t)?t:o.parse(t),i=r[0],a=0;a<r.length-1;++a){var s=r[a];\"-\"===s&&Array.isArray(e)&&(s=e.length),i=r[a+1],s in e||(i.match(/^(\\d+|-)$/)?e[s]=[]:e[s]={}),e=e[s]}return\"-\"===i&&Array.isArray(e)&&(i=e.length),e[i]=n,this},o.remove=function(e,t){var n=Array.isArray(t)?t:o.parse(t),r=n[n.length-1];if(void 0===r)throw new Error('Invalid JSON pointer for remove: \"'+t+'\"');var i=o.get(e,n.slice(0,-1));if(Array.isArray(i)){var a=+r;if(\"\"===r&&isNaN(a))throw new Error('Invalid array index: \"'+r+'\"');Array.prototype.splice.call(i,a,1)}else delete i[r]},o.dict=function(e,t){var n={};return o.walk(e,function(e,t){n[t]=e},t),n},o.walk=function(e,t,n){var i=[];n=n||function(e){var t=Object.prototype.toString.call(e);return\"[object Object]\"===t||\"[object Array]\"===t},function e(a){r(a,function(r,a){i.push(String(a)),n(r)?e(r):t(r,o.compile(i)),i.pop()})}(e)},o.has=function(e,t){try{o.get(e,t)}catch(e){return!1}return!0},o.escape=function(e){return e.toString().replace(/~/g,\"~0\").replace(/\\//g,\"~1\")},o.unescape=function(e){return e.replace(/~1/g,\"/\").replace(/~0/g,\"~\")},o.parse=function(e){if(\"\"===e)return[];if(\"/\"!==e.charAt(0))throw new Error(\"Invalid JSON pointer: \"+e);return e.substring(1).split(/\\//).map(o.unescape)},o.compile=function(e){return 0===e.length?\"\":\"/\"+e.map(o.escape).join(\"/\")}},function(e,t,n){var r=n(14),o=n(82),i=n(60),a=Object.defineProperty;t.f=n(17)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if(\"get\"in n||\"set\"in n)throw TypeError(\"Accessors not supported!\");return\"value\"in n&&(e[t]=n.value),e}},function(e,t,n){e.exports=!n(27)(function(){return 7!=Object.defineProperty({},\"a\",{get:function(){return 7}}).a})},function(e,t,n){var r=n(5),o=n(7),i=n(22),a=n(21),s=n(24),l=function(e,t,n){var c,u,p,f,d=e&l.F,h=e&l.G,m=e&l.S,g=e&l.P,y=e&l.B,v=h?r:m?r[t]||(r[t]={}):(r[t]||{}).prototype,b=h?o:o[t]||(o[t]={}),w=b.prototype||(b.prototype={});for(c in h&&(n=t),n)p=((u=!d&&v&&void 0!==v[c])?v:n)[c],f=y&&u?s(p,r):g&&\"function\"==typeof p?s(Function.call,p):p,v&&a(v,c,p,e&l.U),b[c]!=p&&i(b,c,f),g&&w[c]!=p&&(w[c]=p)};r.core=o,l.F=1,l.G=2,l.S=4,l.P=8,l.B=16,l.W=32,l.U=64,l.R=128,e.exports=l},function(e,t,n){\"use strict\";(function(r){var o=/^win/.test(r.platform),i=/\\//g,a=/^(\\w{2,}):\\/\\//i,s=e.exports,l=[/\\?/g,\"%3F\",/\\#/g,\"%23\"],c=[/\\%23/g,\"#\",/\\%24/g,\"$\",/\\%26/g,\"&\",/\\%2C/g,\",\",/\\%40/g,\"@\"];t.parse=n(10).parse,t.resolve=n(10).resolve,t.cwd=function(){return r.browser?location.href:r.cwd()+\"/\"},t.getProtocol=function(e){var t=a.exec(e);if(t)return t[1].toLowerCase()},t.getExtension=function(e){var t=e.lastIndexOf(\".\");return t>=0?e.substr(t).toLowerCase():\"\"},t.getHash=function(e){var t=e.indexOf(\"#\");return t>=0?e.substr(t):\"#\"},t.stripHash=function(e){var t=e.indexOf(\"#\");return t>=0&&(e=e.substr(0,t)),e},t.isHttp=function(e){var t=s.getProtocol(e);return\"http\"===t||\"https\"===t||void 0===t&&r.browser},t.isFileSystemPath=function(e){if(r.browser)return!1;var t=s.getProtocol(e);return void 0===t||\"file\"===t},t.fromFileSystemPath=function(e){o&&(e=e.replace(/\\\\/g,\"/\")),e=encodeURI(e);for(var t=0;t<l.length;t+=2)e=e.replace(l[t],l[t+1]);return e},t.toFileSystemPath=function(e,t){e=decodeURI(e);for(var n=0;n<c.length;n+=2)e=e.replace(c[n],c[n+1]);var r=\"file://\"===e.substr(0,7).toLowerCase();return r&&(e=\"/\"===e[7]?e.substr(8):e.substr(7),o&&\"/\"===e[1]&&(e=e[0]+\":\"+e.substr(1)),t?e=\"file:///\"+e:(r=!1,e=o?e:\"/\"+e)),o&&!r&&\":\\\\\"===(e=e.replace(i,\"\\\\\")).substr(1,2)&&(e=e[0].toUpperCase()+e.substr(1)),e}}).call(this,n(6))},function(e,t){\"function\"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){var r=n(5),o=n(22),i=n(23),a=n(32)(\"src\"),s=Function.toString,l=(\"\"+s).split(\"toString\");n(7).inspectSource=function(e){return s.call(e)},(e.exports=function(e,t,n,s){var c=\"function\"==typeof n;c&&(i(n,\"name\")||o(n,\"name\",t)),e[t]!==n&&(c&&(i(n,a)||o(n,a,e[t]?\"\"+e[t]:l.join(String(t)))),e===r?e[t]=n:s?e[t]?e[t]=n:o(e,t,n):(delete e[t],o(e,t,n)))})(Function.prototype,\"toString\",function(){return\"function\"==typeof this&&this[a]||s.call(this)})},function(e,t,n){var r=n(16),o=n(42);e.exports=n(17)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(44);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){\"use strict\";var r=n(216),o=Array.prototype.slice,i=[\"name\",\"message\",\"stack\"],a=[\"name\",\"message\",\"description\",\"number\",\"code\",\"fileName\",\"lineNumber\",\"columnNumber\",\"sourceURL\",\"line\",\"column\",\"stack\"];function s(t){return function(n,r,i,a){var s=[],h=\"\";\"string\"==typeof n?(s=o.call(arguments),n=r=void 0):\"string\"==typeof r?(s=o.call(arguments,1),r=void 0):\"string\"==typeof i&&(s=o.call(arguments,2)),s.length>0&&(h=e.exports.formatter.apply(null,s)),n&&n.message&&(h+=(h?\" \\n\":\"\")+n.message);var m,g,y,v=new t(h);return function(e,t){var n,r;!function(e){if(!d)return!1;var t=Object.getOwnPropertyDescriptor(e,\"stack\");return!!t&&\"function\"==typeof t.get}(e)?e.stack=t?p(e.stack,t.stack):f(e.stack):t?function(e,t){var n=Object.getOwnPropertyDescriptor(e,\"stack\");Object.defineProperty(e,\"stack\",{get:function(){return p(n.get.apply(e),t.stack)},enumerable:!1,configurable:!0})}(e,t):(n=e,r=Object.getOwnPropertyDescriptor(n,\"stack\"),Object.defineProperty(n,\"stack\",{get:function(){return f(r.get.apply(n))},enumerable:!1,configurable:!0}))}(m=v,g=n),l(m,g),(y=v).toJSON=c,y.inspect=u,l(v,r),v}}function l(e,t){if(t&&\"object\"==typeof t)for(var n=Object.keys(t),r=0;r<n.length;r++){var o=n[r];if(!(i.indexOf(o)>=0))try{e[o]=t[o]}catch(e){}}}function c(){var e={},t=Object.keys(this);t=t.concat(a);for(var n=0;n<t.length;n++){var r=t[n],o=this[r],i=typeof o;\"undefined\"!==i&&\"function\"!==i&&(e[r]=o)}return e}function u(){return JSON.stringify(this,null,2).replace(/\\\\n/g,\"\\n\")}function p(e,t){return(e=f(e))&&t?e+\"\\n\\n\"+t:e||t}function f(e){if(e){var t=e.split(\"\\n\");if(t.length<2)return e;for(var n=0;n<t.length;n++){if(t[n].indexOf(\"onoFactory\")>=0)return t.splice(n,1),t.join(\"\\n\")}return e}}e.exports=s(Error),e.exports.error=s(Error),e.exports.eval=s(EvalError),e.exports.range=s(RangeError),e.exports.reference=s(ReferenceError),e.exports.syntax=s(SyntaxError),e.exports.type=s(TypeError),e.exports.uri=s(URIError),e.exports.formatter=r;var d=!(!Object.getOwnPropertyDescriptor||!Object.defineProperty||\"undefined\"!=typeof navigator&&/Android/.test(navigator.userAgent))},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var r=n(64),o=n(43);e.exports=function(e){return r(o(e))}},function(e,t,n){\"use strict\";var r=n(37),o=n(47),i=n(3);function a(e,t,n){var r=[];return e.include.forEach(function(e){n=a(e,t,n)}),e[t].forEach(function(e){n.forEach(function(t,n){t.tag===e.tag&&t.kind===e.kind&&r.push(n)}),n.push(e)}),n.filter(function(e,t){return-1===r.indexOf(t)})}function s(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&\"scalar\"!==e.loadKind)throw new o(\"There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.\")}),this.compiledImplicit=a(this,\"implicit\",[]),this.compiledExplicit=a(this,\"explicit\",[]),this.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{}};function r(e){n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e<t;e+=1)arguments[e].forEach(r);return n}(this.compiledImplicit,this.compiledExplicit)}s.DEFAULT=null,s.create=function(){var e,t;switch(arguments.length){case 1:e=s.DEFAULT,t=arguments[0];break;case 2:e=arguments[0],t=arguments[1];break;default:throw new o(\"Wrong number of arguments for Schema.create function\")}if(e=r.toArray(e),t=r.toArray(t),!e.every(function(e){return e instanceof s}))throw new o(\"Specified list of super schemas (or a single Schema object) contains a non-Schema object.\");if(!t.every(function(e){return e instanceof i}))throw new o(\"Specified list of YAML types (or a single Type object) contains a non-Type object.\");return new s({include:e,explicit:t})},e.exports=s},function(e,t,n){\"use strict\";var r=n(49),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=p;var i=n(38);i.inherits=n(20);var a=n(110),s=n(114);i.inherits(p,a);for(var l=o(s.prototype),c=0;c<l.length;c++){var u=l[c];p.prototype[u]||(p.prototype[u]=s.prototype[u])}function p(e){if(!(this instanceof p))return new p(e);a.call(this,e),s.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once(\"end\",f)}function f(){this.allowHalfOpen||this._writableState.ended||r.nextTick(d,this)}function d(e){e.end()}Object.defineProperty(p.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(p.prototype,\"destroyed\",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),p.prototype._destroy=function(e,t){this.push(null),this.end(),r.nextTick(t,e)}},function(e,t){e.exports=!1},function(e,t){var n=0,r=Math.random();e.exports=function(e){return\"Symbol(\".concat(void 0===e?\"\":e,\")_\",(++n+r).toString(36))}},function(e,t){e.exports={}},function(e,t,n){var r=n(84),o=n(66);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t,n){var r=n(61),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(16).f,o=n(23),i=n(2)(\"toStringTag\");e.exports=function(e,t,n){e&&!o(e=n?e:e.prototype,i)&&r(e,i,{configurable:!0,value:t})}},function(e,t,n){\"use strict\";function r(e){return null==e}e.exports.isNothing=r,e.exports.isObject=function(e){return\"object\"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:r(e)?[]:[e]},e.exports.repeat=function(e,t){var n,r=\"\";for(n=0;n<t;n+=1)r+=e;return r},e.exports.isNegativeZero=function(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e},e.exports.extend=function(e,t){var n,r,o,i;if(t)for(n=0,r=(i=Object.keys(t)).length;n<r;n+=1)e[o=i[n]]=t[o];return e}},function(e,t,n){(function(e){function n(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):\"[object Array]\"===n(e)},t.isBoolean=function(e){return\"boolean\"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return\"number\"==typeof e},t.isString=function(e){return\"string\"==typeof e},t.isSymbol=function(e){return\"symbol\"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return\"[object RegExp]\"===n(e)},t.isObject=function(e){return\"object\"==typeof e&&null!==e},t.isDate=function(e){return\"[object Date]\"===n(e)},t.isError=function(e){return\"[object Error]\"===n(e)||e instanceof Error},t.isFunction=function(e){return\"function\"==typeof e},t.isPrimitive=function(e){return null===e||\"boolean\"==typeof e||\"number\"==typeof e||\"string\"==typeof e||\"symbol\"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";var r=function(e,t){return e===t};t.a=function(e,t){var n;void 0===t&&(t=r);var o,i=[],a=!1,s=function(e,n){return t(e,i[n])};return function(){for(var t=arguments.length,r=new Array(t),l=0;l<t;l++)r[l]=arguments[l];return a&&n===this&&r.length===i.length&&r.every(s)?o:(o=e.apply(this,r),a=!0,n=this,i=r,o)}}},function(e,t,n){var r,o,i;o=[t],void 0===(i=\"function\"==typeof(r=function(e){\"use strict\";e.__esModule=!0;var t={},n=Object.prototype.hasOwnProperty,r={memoize:function(e){var r=arguments.length<=1||void 0===arguments[1]?t:arguments[1],o=r.cache||{};return function(){for(var t=arguments.length,i=Array(t),a=0;a<t;a++)i[a]=arguments[a];var s=String(i[0]);return!1===r.caseSensitive&&(s=s.toLowerCase()),n.call(o,s)?o[s]:o[s]=e.apply(this,i)}},debounce:function(e,t){if(\"function\"==typeof t){var n=e;e=t,t=n}var r=t&&t.delay||t||0,o=void 0,i=void 0,a=void 0;return function(){for(var t=arguments.length,n=Array(t),s=0;s<t;s++)n[s]=arguments[s];o=n,i=this,a||(a=setTimeout(function(){e.apply(i,o),o=i=a=null},r))}},bind:function(e,t,n){var r=n.value;return{configurable:!0,get:function(){var e=r.bind(this);return Object.defineProperty(this,t,{value:e,configurable:!0,writable:!0}),e}}}},o=s(r.memoize),i=s(r.debounce),a=s(function(e,t){return e.bind(t)},function(){return r.bind});function s(e,t){var n,r=(t=t||e.decorate||(n=e,function(e){return\"function\"==typeof e?n(e):function(t,r,o){o.value=n(o.value,e,t,r,o)}}))();return function(){for(var n=arguments.length,o=Array(n),i=0;i<n;i++)o[i]=arguments[i];var a=o.length;return(a<2?t:a>2?r:e).apply(void 0,o)}}e.memoize=o,e.debounce=i,e.bind=a,e.default={memoize:o,debounce:i,bind:a}})?r.apply(t,o):r)||(e.exports=i)},function(e,t,n){(function(t){!function(t){\"use strict\";var n={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:g,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *(?:#+ *)?(?:\\n+|$)/,nptable:g,blockquote:/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/,list:/^( {0,3})(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:\"^ {0,3}(?:<(script|pre|style)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n+|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?\\\\?>\\\\n*|<![A-Z][\\\\s\\\\S]*?>\\\\n*|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>\\\\n*|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:\\\\n{2,}|$)|<(?!script|pre|style)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=\\\\h*\\\\n)[\\\\s\\\\S]*?(?:\\\\n{2,}|$)|</(?!script|pre|style)[a-z][\\\\w-]*\\\\s*>(?=\\\\h*\\\\n)[\\\\s\\\\S]*?(?:\\\\n{2,}|$))\",def:/^ {0,3}\\[(label)\\]: *\\n? *<?([^\\s>]+)>?(?:(?: +\\n? *| *\\n *)(title))? *(?:\\n+|$)/,table:g,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,paragraph:/^([^\\n]+(?:\\n(?!hr|heading|lheading| {0,3}>|<\\/?(?:tag)(?: +|\\n|\\/?>)|<(?:script|pre|style|!--))[^\\n]+)*)/,text:/^[^\\n]+/};function r(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||w.defaults,this.rules=n.normal,this.options.pedantic?this.rules=n.pedantic:this.options.gfm&&(this.options.tables?this.rules=n.tables:this.rules=n.gfm)}n._label=/(?!\\s*\\])(?:\\\\[\\[\\]]|[^\\[\\]])+/,n._title=/(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/,n.def=f(n.def).replace(\"label\",n._label).replace(\"title\",n._title).getRegex(),n.bullet=/(?:[*+-]|\\d{1,9}\\.)/,n.item=/^( *)(bull) ?[^\\n]*(?:\\n(?!\\1bull ?)[^\\n]*)*/,n.item=f(n.item,\"gm\").replace(/bull/g,n.bullet).getRegex(),n.list=f(n.list).replace(/bull/g,n.bullet).replace(\"hr\",\"\\\\n+(?=\\\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$))\").replace(\"def\",\"\\\\n+(?=\"+n.def.source+\")\").getRegex(),n._tag=\"address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul\",n._comment=/<!--(?!-?>)[\\s\\S]*?-->/,n.html=f(n.html,\"i\").replace(\"comment\",n._comment).replace(\"tag\",n._tag).replace(\"attribute\",/ +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/).getRegex(),n.paragraph=f(n.paragraph).replace(\"hr\",n.hr).replace(\"heading\",n.heading).replace(\"lheading\",n.lheading).replace(\"tag\",n._tag).getRegex(),n.blockquote=f(n.blockquote).replace(\"paragraph\",n.paragraph).getRegex(),n.normal=y({},n),n.gfm=y({},n.normal,{fences:/^ {0,3}(`{3,}|~{3,})([^`\\n]*)\\n(?:|([\\s\\S]*?)\\n)(?: {0,3}\\1[~`]* *(?:\\n+|$)|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)/}),n.gfm.paragraph=f(n.paragraph).replace(\"(?!\",\"(?!\"+n.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+n.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\").getRegex(),n.tables=y({},n.gfm,{nptable:/^ *([^|\\n ].*\\|.*)\\n *([-:]+ *\\|[-| :]*)(?:\\n((?:.*[^>\\n ].*(?:\\n|$))*)\\n*|$)/,table:/^ *\\|(.+)\\n *\\|?( *[-:]+[-| :]*)(?:\\n((?: *[^>\\n ].*(?:\\n|$))*)\\n*|$)/}),n.pedantic=y({},n.normal,{html:f(\"^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:\\\"[^\\\"]*\\\"|'[^']*'|\\\\s[^'\\\"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))\").replace(\"comment\",n._comment).replace(/tag/g,\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b\").getRegex(),def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/}),r.rules=n,r.lex=function(e,t){return new r(t).lex(e)},r.prototype.lex=function(e){return e=e.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\"    \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\"),this.token(e,!0)},r.prototype.token=function(e,t){var r,o,i,a,s,l,c,u,p,f,d,h,m,g,y,w;for(e=e.replace(/^ +$/gm,\"\");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:\"space\"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,\"\"),this.tokens.push({type:\"code\",text:this.options.pedantic?i:b(i,\"\\n\")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"code\",lang:i[2]?i[2].trim():i[2],text:i[3]||\"\"});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"heading\",depth:i[1].length,text:i[2]});else if(t&&(i=this.rules.nptable.exec(e))&&(l={type:\"table\",header:v(i[1].replace(/^ *| *\\| *$/g,\"\")),align:i[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:i[3]?i[3].replace(/\\n$/,\"\").split(\"\\n\"):[]}).header.length===l.align.length){for(e=e.substring(i[0].length),d=0;d<l.align.length;d++)/^ *-+: *$/.test(l.align[d])?l.align[d]=\"right\":/^ *:-+: *$/.test(l.align[d])?l.align[d]=\"center\":/^ *:-+ *$/.test(l.align[d])?l.align[d]=\"left\":l.align[d]=null;for(d=0;d<l.cells.length;d++)l.cells[d]=v(l.cells[d],l.header.length);this.tokens.push(l)}else if(i=this.rules.hr.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"hr\"});else if(i=this.rules.blockquote.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"blockquote_start\"}),i=i[0].replace(/^ *> ?/gm,\"\"),this.token(i,t),this.tokens.push({type:\"blockquote_end\"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),c={type:\"list_start\",ordered:g=(a=i[2]).length>1,start:g?+a:\"\",loose:!1},this.tokens.push(c),u=[],r=!1,m=(i=i[0].match(this.rules.item)).length,d=0;d<m;d++)f=(l=i[d]).length,~(l=l.replace(/^ *([*+-]|\\d+\\.) */,\"\")).indexOf(\"\\n \")&&(f-=l.length,l=this.options.pedantic?l.replace(/^ {1,4}/gm,\"\"):l.replace(new RegExp(\"^ {1,\"+f+\"}\",\"gm\"),\"\")),d!==m-1&&(s=n.bullet.exec(i[d+1])[0],(a.length>1?1===s.length:s.length>1||this.options.smartLists&&s!==a)&&(e=i.slice(d+1).join(\"\\n\")+e,d=m-1)),o=r||/\\n\\n(?!\\s*$)/.test(l),d!==m-1&&(r=\"\\n\"===l.charAt(l.length-1),o||(o=r)),o&&(c.loose=!0),w=void 0,(y=/^\\[[ xX]\\] /.test(l))&&(w=\" \"!==l[1],l=l.replace(/^\\[[ xX]\\] +/,\"\")),p={type:\"list_item_start\",task:y,checked:w,loose:o},u.push(p),this.tokens.push(p),this.token(l,!1),this.tokens.push({type:\"list_item_end\"});if(c.loose)for(m=u.length,d=0;d<m;d++)u[d].loose=!0;this.tokens.push({type:\"list_end\"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:!this.options.sanitizer&&(\"pre\"===i[1]||\"script\"===i[1]||\"style\"===i[1]),text:i[0]});else if(t&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),i[3]&&(i[3]=i[3].substring(1,i[3].length-1)),h=i[1].toLowerCase().replace(/\\s+/g,\" \"),this.tokens.links[h]||(this.tokens.links[h]={href:i[2],title:i[3]});else if(t&&(i=this.rules.table.exec(e))&&(l={type:\"table\",header:v(i[1].replace(/^ *| *\\| *$/g,\"\")),align:i[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:i[3]?i[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\"):[]}).header.length===l.align.length){for(e=e.substring(i[0].length),d=0;d<l.align.length;d++)/^ *-+: *$/.test(l.align[d])?l.align[d]=\"right\":/^ *:-+: *$/.test(l.align[d])?l.align[d]=\"center\":/^ *:-+ *$/.test(l.align[d])?l.align[d]=\"left\":l.align[d]=null;for(d=0;d<l.cells.length;d++)l.cells[d]=v(l.cells[d].replace(/^ *\\| *| *\\| *$/g,\"\"),l.header.length);this.tokens.push(l)}else if(i=this.rules.lheading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"heading\",depth:\"=\"===i[2]?1:2,text:i[1]});else if(t&&(i=this.rules.paragraph.exec(e)))e=e.substring(i[0].length),this.tokens.push({type:\"paragraph\",text:\"\\n\"===i[1].charAt(i[1].length-1)?i[1].slice(0,-1):i[1]});else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"text\",text:i[0]});else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0));return this.tokens};var o={escape:/^\\\\([!\"#$%&'()*+,\\-.\\/:;<=>?@\\[\\]\\\\^_`{|}~])/,autolink:/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/,url:g,tag:\"^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>\",link:/^!?\\[(label)\\]\\(href(?:\\s+(title))?\\s*\\)/,reflink:/^!?\\[(label)\\]\\[(?!\\s*\\])((?:\\\\[\\[\\]]?|[^\\[\\]\\\\])+)\\]/,nolink:/^!?\\[(?!\\s*\\])((?:\\[[^\\[\\]]*\\]|\\\\[\\[\\]]|[^\\[\\]])*)\\](?:\\[\\])?/,strong:/^__([^\\s_])__(?!_)|^\\*\\*([^\\s*])\\*\\*(?!\\*)|^__([^\\s][\\s\\S]*?[^\\s])__(?!_)|^\\*\\*([^\\s][\\s\\S]*?[^\\s])\\*\\*(?!\\*)/,em:/^_([^\\s_])_(?!_)|^\\*([^\\s*\"<\\[])\\*(?!\\*)|^_([^\\s][\\s\\S]*?[^\\s_])_(?!_|[^\\spunctuation])|^_([^\\s_][\\s\\S]*?[^\\s])_(?!_|[^\\spunctuation])|^\\*([^\\s\"<\\[][\\s\\S]*?[^\\s*])\\*(?!\\*)|^\\*([^\\s*\"<\\[][\\s\\S]*?[^\\s])\\*(?!\\*)/,code:/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,br:/^( {2,}|\\\\)\\n(?!\\s*$)/,del:g,text:/^(`+|[^`])[\\s\\S]*?(?=[\\\\<!\\[`*]|\\b_| {2,}\\n|$)/};function i(e,t){if(this.options=t||w.defaults,this.links=e,this.rules=o.normal,this.renderer=this.options.renderer||new a,this.renderer.options=this.options,!this.links)throw new Error(\"Tokens array requires a `links` property.\");this.options.pedantic?this.rules=o.pedantic:this.options.gfm&&(this.options.breaks?this.rules=o.breaks:this.rules=o.gfm)}function a(e){this.options=e||w.defaults}function s(){}function l(e){this.tokens=[],this.token=null,this.options=e||w.defaults,this.options.renderer=this.options.renderer||new a,this.renderer=this.options.renderer,this.renderer.options=this.options,this.slugger=new c}function c(){this.seen={}}function u(e,t){if(t){if(u.escapeTest.test(e))return e.replace(u.escapeReplace,function(e){return u.replacements[e]})}else if(u.escapeTestNoEncode.test(e))return e.replace(u.escapeReplaceNoEncode,function(e){return u.replacements[e]});return e}function p(e){return e.replace(/&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/gi,function(e,t){return\"colon\"===(t=t.toLowerCase())?\":\":\"#\"===t.charAt(0)?\"x\"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):\"\"})}function f(e,t){return e=e.source||e,t=t||\"\",{replace:function(t,n){return n=(n=n.source||n).replace(/(^|[^\\[])\\^/g,\"$1\"),e=e.replace(t,n),this},getRegex:function(){return new RegExp(e,t)}}}function d(e,t,n){if(e){try{var r=decodeURIComponent(p(n)).replace(/[^\\w:]/g,\"\").toLowerCase()}catch(e){return null}if(0===r.indexOf(\"javascript:\")||0===r.indexOf(\"vbscript:\")||0===r.indexOf(\"data:\"))return null}t&&!m.test(n)&&(n=function(e,t){h[\" \"+e]||(/^[^:]+:\\/*[^\\/]*$/.test(e)?h[\" \"+e]=e+\"/\":h[\" \"+e]=b(e,\"/\",!0));return e=h[\" \"+e],\"//\"===t.slice(0,2)?e.replace(/:[\\s\\S]*/,\":\")+t:\"/\"===t.charAt(0)?e.replace(/(:\\/*[^\\/]*)[\\s\\S]*/,\"$1\")+t:e+t}(t,n));try{n=encodeURI(n).replace(/%25/g,\"%\")}catch(e){return null}return n}o._punctuation=\"!\\\"#$%&'()*+,\\\\-./:;<=>?@\\\\[^_{|}~\",o.em=f(o.em).replace(/punctuation/g,o._punctuation).getRegex(),o._escapes=/\\\\([!\"#$%&'()*+,\\-.\\/:;<=>?@\\[\\]\\\\^_`{|}~])/g,o._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,o._email=/[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,o.autolink=f(o.autolink).replace(\"scheme\",o._scheme).replace(\"email\",o._email).getRegex(),o._attribute=/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/,o.tag=f(o.tag).replace(\"comment\",n._comment).replace(\"attribute\",o._attribute).getRegex(),o._label=/(?:\\[[^\\[\\]]*\\]|\\\\[\\[\\]]?|`[^`]*`|[^\\[\\]\\\\])*?/,o._href=/\\s*(<(?:\\\\[<>]?|[^\\s<>\\\\])*>|(?:\\\\[()]?|\\([^\\s\\x00-\\x1f\\\\]*\\)|[^\\s\\x00-\\x1f()\\\\])*?)/,o._title=/\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/,o.link=f(o.link).replace(\"label\",o._label).replace(\"href\",o._href).replace(\"title\",o._title).getRegex(),o.reflink=f(o.reflink).replace(\"label\",o._label).getRegex(),o.normal=y({},o),o.pedantic=y({},o.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/,link:f(/^!?\\[(label)\\]\\((.*?)\\)/).replace(\"label\",o._label).getRegex(),reflink:f(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace(\"label\",o._label).getRegex()}),o.gfm=y({},o.normal,{escape:f(o.escape).replace(\"])\",\"~|])\").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\\S)([\\s\\S]*?\\S)~+/,text:f(o.text).replace(\"]|\",\"~]|\").replace(\"|$\",\"|https?://|ftp://|www\\\\.|[a-zA-Z0-9.!#$%&'*+/=?^_`{\\\\|}~-]+@|$\").getRegex()}),o.gfm.url=f(o.gfm.url,\"i\").replace(\"email\",o.gfm._extended_email).getRegex(),o.breaks=y({},o.gfm,{br:f(o.br).replace(\"{2,}\",\"*\").getRegex(),text:f(o.gfm.text).replace(\"{2,}\",\"*\").getRegex()}),i.rules=o,i.output=function(e,t,n){return new i(t,n).output(e)},i.prototype.output=function(e){for(var t,n,r,o,a,s,l=\"\";e;)if(a=this.rules.escape.exec(e))e=e.substring(a[0].length),l+=u(a[1]);else if(a=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(a[0])?this.inLink=!0:this.inLink&&/^<\\/a>/i.test(a[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\\s|>)/i.test(a[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\\/(pre|code|kbd|script)(\\s|>)/i.test(a[0])&&(this.inRawBlock=!1),e=e.substring(a[0].length),l+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0];else if(a=this.rules.link.exec(e))e=e.substring(a[0].length),this.inLink=!0,r=a[2],this.options.pedantic?(t=/^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/.exec(r))?(r=t[1],o=t[3]):o=\"\":o=a[3]?a[3].slice(1,-1):\"\",r=r.trim().replace(/^<([\\s\\S]*)>$/,\"$1\"),l+=this.outputLink(a,{href:i.escapes(r),title:i.escapes(o)}),this.inLink=!1;else if((a=this.rules.reflink.exec(e))||(a=this.rules.nolink.exec(e))){if(e=e.substring(a[0].length),t=(a[2]||a[1]).replace(/\\s+/g,\" \"),!(t=this.links[t.toLowerCase()])||!t.href){l+=a[0].charAt(0),e=a[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(a,t),this.inLink=!1}else if(a=this.rules.strong.exec(e))e=e.substring(a[0].length),l+=this.renderer.strong(this.output(a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.em.exec(e))e=e.substring(a[0].length),l+=this.renderer.em(this.output(a[6]||a[5]||a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.code.exec(e))e=e.substring(a[0].length),l+=this.renderer.codespan(u(a[2].trim(),!0));else if(a=this.rules.br.exec(e))e=e.substring(a[0].length),l+=this.renderer.br();else if(a=this.rules.del.exec(e))e=e.substring(a[0].length),l+=this.renderer.del(this.output(a[1]));else if(a=this.rules.autolink.exec(e))e=e.substring(a[0].length),r=\"@\"===a[2]?\"mailto:\"+(n=u(this.mangle(a[1]))):n=u(a[1]),l+=this.renderer.link(r,null,n);else if(this.inLink||!(a=this.rules.url.exec(e))){if(a=this.rules.text.exec(e))e=e.substring(a[0].length),this.inRawBlock?l+=this.renderer.text(a[0]):l+=this.renderer.text(u(this.smartypants(a[0])));else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0))}else{if(\"@\"===a[2])r=\"mailto:\"+(n=u(a[0]));else{do{s=a[0],a[0]=this.rules._backpedal.exec(a[0])[0]}while(s!==a[0]);n=u(a[0]),r=\"www.\"===a[1]?\"http://\"+n:n}e=e.substring(a[0].length),l+=this.renderer.link(r,null,n)}return l},i.escapes=function(e){return e?e.replace(i.rules._escapes,\"$1\"):e},i.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return\"!\"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},i.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,\"—\").replace(/--/g,\"–\").replace(/(^|[-\\u2014\\/(\\[{\"\\s])'/g,\"$1‘\").replace(/'/g,\"’\").replace(/(^|[-\\u2014\\/(\\[{\\u2018\\s])\"/g,\"$1“\").replace(/\"/g,\"”\").replace(/\\.{3}/g,\"…\"):e},i.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n=\"\",r=e.length,o=0;o<r;o++)t=e.charCodeAt(o),Math.random()>.5&&(t=\"x\"+t.toString(16)),n+=\"&#\"+t+\";\";return n},a.prototype.code=function(e,t,n){var r=(t||\"\").match(/\\S*/)[0];if(this.options.highlight){var o=this.options.highlight(e,r);null!=o&&o!==e&&(n=!0,e=o)}return r?'<pre><code class=\"'+this.options.langPrefix+u(r,!0)+'\">'+(n?e:u(e,!0))+\"</code></pre>\\n\":\"<pre><code>\"+(n?e:u(e,!0))+\"</code></pre>\"},a.prototype.blockquote=function(e){return\"<blockquote>\\n\"+e+\"</blockquote>\\n\"},a.prototype.html=function(e){return e},a.prototype.heading=function(e,t,n,r){return this.options.headerIds?\"<h\"+t+' id=\"'+this.options.headerPrefix+r.slug(n)+'\">'+e+\"</h\"+t+\">\\n\":\"<h\"+t+\">\"+e+\"</h\"+t+\">\\n\"},a.prototype.hr=function(){return this.options.xhtml?\"<hr/>\\n\":\"<hr>\\n\"},a.prototype.list=function(e,t,n){var r=t?\"ol\":\"ul\";return\"<\"+r+(t&&1!==n?' start=\"'+n+'\"':\"\")+\">\\n\"+e+\"</\"+r+\">\\n\"},a.prototype.listitem=function(e){return\"<li>\"+e+\"</li>\\n\"},a.prototype.checkbox=function(e){return\"<input \"+(e?'checked=\"\" ':\"\")+'disabled=\"\" type=\"checkbox\"'+(this.options.xhtml?\" /\":\"\")+\"> \"},a.prototype.paragraph=function(e){return\"<p>\"+e+\"</p>\\n\"},a.prototype.table=function(e,t){return t&&(t=\"<tbody>\"+t+\"</tbody>\"),\"<table>\\n<thead>\\n\"+e+\"</thead>\\n\"+t+\"</table>\\n\"},a.prototype.tablerow=function(e){return\"<tr>\\n\"+e+\"</tr>\\n\"},a.prototype.tablecell=function(e,t){var n=t.header?\"th\":\"td\";return(t.align?\"<\"+n+' align=\"'+t.align+'\">':\"<\"+n+\">\")+e+\"</\"+n+\">\\n\"},a.prototype.strong=function(e){return\"<strong>\"+e+\"</strong>\"},a.prototype.em=function(e){return\"<em>\"+e+\"</em>\"},a.prototype.codespan=function(e){return\"<code>\"+e+\"</code>\"},a.prototype.br=function(){return this.options.xhtml?\"<br/>\":\"<br>\"},a.prototype.del=function(e){return\"<del>\"+e+\"</del>\"},a.prototype.link=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r='<a href=\"'+u(e)+'\"';return t&&(r+=' title=\"'+t+'\"'),r+=\">\"+n+\"</a>\"},a.prototype.image=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r='<img src=\"'+e+'\" alt=\"'+n+'\"';return t&&(r+=' title=\"'+t+'\"'),r+=this.options.xhtml?\"/>\":\">\"},a.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return\"\"+n},s.prototype.br=function(){return\"\"},l.parse=function(e,t){return new l(t).parse(e)},l.prototype.parse=function(e){this.inline=new i(e.links,this.options),this.inlineText=new i(e.links,y({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t=\"\";this.next();)t+=this.tok();return t},l.prototype.next=function(){return this.token=this.tokens.pop()},l.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},l.prototype.parseText=function(){for(var e=this.token.text;\"text\"===this.peek().type;)e+=\"\\n\"+this.next().text;return this.inline.output(e)},l.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return this.renderer.hr();case\"heading\":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,p(this.inlineText.output(this.token.text)),this.slugger);case\"code\":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case\"table\":var e,t,n,r,o=\"\",i=\"\";for(n=\"\",e=0;e<this.token.header.length;e++)n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(o+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n=\"\",r=0;r<t.length;r++)n+=this.renderer.tablecell(this.inline.output(t[r]),{header:!1,align:this.token.align[r]});i+=this.renderer.tablerow(n)}return this.renderer.table(o,i);case\"blockquote_start\":for(i=\"\";\"blockquote_end\"!==this.next().type;)i+=this.tok();return this.renderer.blockquote(i);case\"list_start\":i=\"\";for(var a=this.token.ordered,s=this.token.start;\"list_end\"!==this.next().type;)i+=this.tok();return this.renderer.list(i,a,s);case\"list_item_start\":i=\"\";var l=this.token.loose;for(this.token.task&&(i+=this.renderer.checkbox(this.token.checked));\"list_item_end\"!==this.next().type;)i+=l||\"text\"!==this.token.type?this.tok():this.parseText();return this.renderer.listitem(i);case\"html\":return this.renderer.html(this.token.text);case\"paragraph\":return this.renderer.paragraph(this.inline.output(this.token.text));case\"text\":return this.renderer.paragraph(this.parseText());default:var c='Token with \"'+this.token.type+'\" type was not found.';if(!this.options.silent)throw new Error(c);console.log(c)}},c.prototype.slug=function(e){var t=e.toLowerCase().trim().replace(/[\\u2000-\\u206F\\u2E00-\\u2E7F\\\\'!\"#$%&()*+,.\\/:;<=>?@[\\]^`{|}~]/g,\"\").replace(/\\s/g,\"-\");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+\"-\"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t},u.escapeTest=/[&<>\"']/,u.escapeReplace=/[&<>\"']/g,u.replacements={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"},u.escapeTestNoEncode=/[<>\"']|&(?!#?\\w+;)/,u.escapeReplaceNoEncode=/[<>\"']|&(?!#?\\w+;)/g;var h={},m=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function g(){}function y(e){for(var t,n,r=1;r<arguments.length;r++)for(n in t=arguments[r])Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}function v(e,t){var n=e.replace(/\\|/g,function(e,t,n){for(var r=!1,o=t;--o>=0&&\"\\\\\"===n[o];)r=!r;return r?\"|\":\" |\"}).split(/ \\|/),r=0;if(n.length>t)n.splice(t);else for(;n.length<t;)n.push(\"\");for(;r<n.length;r++)n[r]=n[r].trim().replace(/\\\\\\|/g,\"|\");return n}function b(e,t,n){if(0===e.length)return\"\";for(var r=0;r<e.length;){var o=e.charAt(e.length-r-1);if(o!==t||n){if(o===t||!n)break;r++}else r++}return e.substr(0,e.length-r)}function w(e,t,n){if(null==e)throw new Error(\"marked(): input parameter is undefined or null\");if(\"string\"!=typeof e)throw new Error(\"marked(): input parameter is of type \"+Object.prototype.toString.call(e)+\", string expected\");if(n||\"function\"==typeof t){n||(n=t,t=null);var o,i,a=(t=y({},w.defaults,t||{})).highlight,s=0;try{o=r.lex(e,t)}catch(e){return n(e)}i=o.length;var c=function(e){if(e)return t.highlight=a,n(e);var r;try{r=l.parse(o,t)}catch(t){e=t}return t.highlight=a,e?n(e):n(null,r)};if(!a||a.length<3)return c();if(delete t.highlight,!i)return c();for(;s<o.length;s++)!function(e){\"code\"!==e.type?--i||c():a(e.text,e.lang,function(t,n){return t?c(t):null==n||n===e.text?--i||c():(e.text=n,e.escaped=!0,void(--i||c()))})}(o[s])}else try{return t&&(t=y({},w.defaults,t)),l.parse(r.lex(e,t),t)}catch(e){if(e.message+=\"\\nPlease report this to https://github.com/markedjs/marked.\",(t||w.defaults).silent)return\"<p>An error occurred:</p><pre>\"+u(e.message+\"\",!0)+\"</pre>\";throw e}}g.exec=g,w.options=w.setOptions=function(e){return y(w.defaults,e),w},w.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:\"\",highlight:null,langPrefix:\"language-\",mangle:!0,pedantic:!1,renderer:new a,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},w.defaults=w.getDefaults(),w.Parser=l,w.parser=l.parse,w.Renderer=a,w.TextRenderer=s,w.Lexer=r,w.lexer=r.lex,w.InlineLexer=i,w.inlineLexer=i.output,w.Slugger=c,w.parse=w,e.exports=w}(this||\"undefined\"!=typeof window&&window)}).call(this,n(4))},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){e.exports=function(e){if(null==e)throw TypeError(\"Can't call method on  \"+e);return e}},function(e,t){e.exports=function(e){if(\"function\"!=typeof e)throw TypeError(e+\" is not a function!\");return e}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t,n){\"use strict\";var r=n(195);e.exports=r},function(e,t,n){\"use strict\";function r(e,t){Error.call(this),this.name=\"YAMLException\",this.reason=e,this.mark=t,this.message=(this.reason||\"(unknown reason)\")+(this.mark?\" \"+this.mark.toString():\"\"),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||\"\"}r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r.prototype.toString=function(e){var t=this.name+\": \";return t+=this.reason||\"(unknown reason)\",!e&&this.mark&&(t+=\" \"+this.mark.toString()),t},e.exports=r},function(e,t,n){\"use strict\";var r=n(29);e.exports=new r({include:[n(104)],implicit:[n(205),n(206)],explicit:[n(207),n(208),n(209),n(210)]})},function(e,t,n){\"use strict\";(function(t){!t.version||0===t.version.indexOf(\"v0.\")||0===t.version.indexOf(\"v1.\")&&0!==t.version.indexOf(\"v1.8.\")?e.exports={nextTick:function(e,n,r,o){if(\"function\"!=typeof e)throw new TypeError('\"callback\" argument must be a function');var i,a,s=arguments.length;switch(s){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick(function(){e.call(null,n)});case 3:return t.nextTick(function(){e.call(null,n,r)});case 4:return t.nextTick(function(){e.call(null,n,r,o)});default:for(i=new Array(s-1),a=0;a<i.length;)i[a++]=arguments[a];return t.nextTick(function(){e.apply(null,i)})}}}:e.exports=t}).call(this,n(6))},function(e,t,n){var r=n(9),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if(\"number\"==typeof e)throw new TypeError(\"Argument must not be a number\");return o(e,t,n)},a.alloc=function(e,t,n){if(\"number\"!=typeof e)throw new TypeError(\"Argument must be a number\");var r=o(e);return void 0!==t?\"string\"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if(\"number\"!=typeof e)throw new TypeError(\"Argument must be a number\");return o(e)},a.allocUnsafeSlow=function(e){if(\"number\"!=typeof e)throw new TypeError(\"Argument must be a number\");return r.SlowBuffer(e)}},function(e,t,n){\"use strict\";e.exports=o;var r=n(75);function o(){this.path=void 0,this.value=void 0,this.$refs=void 0,this.pathType=void 0}o.prototype.exists=function(e,t){try{return this.resolve(e,t),!0}catch(e){return!1}},o.prototype.get=function(e,t){return this.resolve(e,t).value},o.prototype.resolve=function(e,t,n){return new r(this,e,n).resolve(this.value,t)},o.prototype.set=function(e,t){var n=new r(this,e);this.value=n.set(this.value,t)},o.is$Ref=function(e){return e&&\"object\"==typeof e&&\"string\"==typeof e.$ref&&e.$ref.length>0},o.isExternal$Ref=function(e){return o.is$Ref(e)&&\"#\"!==e.$ref[0]},o.isAllowed$Ref=function(e,t){if(o.is$Ref(e)){if(\"#/\"===e.$ref.substr(0,2)||\"#\"===e.$ref)return!0;if(\"#\"!==e.$ref[0]&&(!t||t.resolve.external))return!0}},o.isExtended$Ref=function(e){return o.is$Ref(e)&&Object.keys(e).length>1},o.dereference=function(e,t){if(t&&\"object\"==typeof t&&o.isExtended$Ref(e)){var n={};return Object.keys(e).forEach(function(t){\"$ref\"!==t&&(n[t]=e[t])}),Object.keys(t).forEach(function(e){e in n||(n[e]=t[e])}),n}return t}},function(e,t,n){(function(e){function n(e,t){for(var n=0,r=e.length-1;r>=0;r--){var o=e[r];\".\"===o?e.splice(r,1):\"..\"===o?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift(\"..\");return e}var r=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/,o=function(e){return r.exec(e).slice(1)};function i(e,t){if(e.filter)return e.filter(t);for(var n=[],r=0;r<e.length;r++)t(e[r],r,e)&&n.push(e[r]);return n}t.resolve=function(){for(var t=\"\",r=!1,o=arguments.length-1;o>=-1&&!r;o--){var a=o>=0?arguments[o]:e.cwd();if(\"string\"!=typeof a)throw new TypeError(\"Arguments to path.resolve must be strings\");a&&(t=a+\"/\"+t,r=\"/\"===a.charAt(0))}return(r?\"/\":\"\")+(t=n(i(t.split(\"/\"),function(e){return!!e}),!r).join(\"/\"))||\".\"},t.normalize=function(e){var r=t.isAbsolute(e),o=\"/\"===a(e,-1);return(e=n(i(e.split(\"/\"),function(e){return!!e}),!r).join(\"/\"))||r||(e=\".\"),e&&o&&(e+=\"/\"),(r?\"/\":\"\")+e},t.isAbsolute=function(e){return\"/\"===e.charAt(0)},t.join=function(){var e=Array.prototype.slice.call(arguments,0);return t.normalize(i(e,function(e,t){if(\"string\"!=typeof e)throw new TypeError(\"Arguments to path.join must be strings\");return e}).join(\"/\"))},t.relative=function(e,n){function r(e){for(var t=0;t<e.length&&\"\"===e[t];t++);for(var n=e.length-1;n>=0&&\"\"===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=t.resolve(e).substr(1),n=t.resolve(n).substr(1);for(var o=r(e.split(\"/\")),i=r(n.split(\"/\")),a=Math.min(o.length,i.length),s=a,l=0;l<a;l++)if(o[l]!==i[l]){s=l;break}var c=[];for(l=s;l<o.length;l++)c.push(\"..\");return(c=c.concat(i.slice(s))).join(\"/\")},t.sep=\"/\",t.delimiter=\":\",t.dirname=function(e){var t=o(e),n=t[0],r=t[1];return n||r?(r&&(r=r.substr(0,r.length-1)),n+r):\".\"},t.basename=function(e,t){var n=o(e)[2];return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},t.extname=function(e){return o(e)[3]};var a=\"b\"===\"ab\".substr(-1)?function(e,t,n){return e.substr(t,n)}:function(e,t,n){return t<0&&(t=e.length+t),e.substr(t,n)}}).call(this,n(6))},function(e,t,n){\"use strict\";var r=Object.prototype.hasOwnProperty,o=\"~\";function i(){}function a(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function s(e,t,n,r,i){if(\"function\"!=typeof n)throw new TypeError(\"The listener must be a function\");var s=new a(n,r||e,i),l=o?o+t:t;return e._events[l]?e._events[l].fn?e._events[l]=[e._events[l],s]:e._events[l].push(s):(e._events[l]=s,e._eventsCount++),e}function l(e,t){0==--e._eventsCount?e._events=new i:delete e._events[t]}function c(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(o=!1)),c.prototype.eventNames=function(){var e,t,n=[];if(0===this._eventsCount)return n;for(t in e=this._events)r.call(e,t)&&n.push(o?t.slice(1):t);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(e)):n},c.prototype.listeners=function(e){var t=o?o+e:e,n=this._events[t];if(!n)return[];if(n.fn)return[n.fn];for(var r=0,i=n.length,a=new Array(i);r<i;r++)a[r]=n[r].fn;return a},c.prototype.listenerCount=function(e){var t=o?o+e:e,n=this._events[t];return n?n.fn?1:n.length:0},c.prototype.emit=function(e,t,n,r,i,a){var s=o?o+e:e;if(!this._events[s])return!1;var l,c,u=this._events[s],p=arguments.length;if(u.fn){switch(u.once&&this.removeListener(e,u.fn,void 0,!0),p){case 1:return u.fn.call(u.context),!0;case 2:return u.fn.call(u.context,t),!0;case 3:return u.fn.call(u.context,t,n),!0;case 4:return u.fn.call(u.context,t,n,r),!0;case 5:return u.fn.call(u.context,t,n,r,i),!0;case 6:return u.fn.call(u.context,t,n,r,i,a),!0}for(c=1,l=new Array(p-1);c<p;c++)l[c-1]=arguments[c];u.fn.apply(u.context,l)}else{var f,d=u.length;for(c=0;c<d;c++)switch(u[c].once&&this.removeListener(e,u[c].fn,void 0,!0),p){case 1:u[c].fn.call(u[c].context);break;case 2:u[c].fn.call(u[c].context,t);break;case 3:u[c].fn.call(u[c].context,t,n);break;case 4:u[c].fn.call(u[c].context,t,n,r);break;default:if(!l)for(f=1,l=new Array(p-1);f<p;f++)l[f-1]=arguments[f];u[c].fn.apply(u[c].context,l)}}return!0},c.prototype.on=function(e,t,n){return s(this,e,t,n,!1)},c.prototype.once=function(e,t,n){return s(this,e,t,n,!0)},c.prototype.removeListener=function(e,t,n,r){var i=o?o+e:e;if(!this._events[i])return this;if(!t)return l(this,i),this;var a=this._events[i];if(a.fn)a.fn!==t||r&&!a.once||n&&a.context!==n||l(this,i);else{for(var s=0,c=[],u=a.length;s<u;s++)(a[s].fn!==t||r&&!a[s].once||n&&a[s].context!==n)&&c.push(a[s]);c.length?this._events[i]=1===c.length?c[0]:c:l(this,i)}return this},c.prototype.removeAllListeners=function(e){var t;return e?(t=o?o+e:e,this._events[t]&&l(this,t)):(this._events=new i,this._eventsCount=0),this},c.prototype.off=c.prototype.removeListener,c.prototype.addListener=c.prototype.on,c.prefixed=o,c.EventEmitter=c,e.exports=c},function(e,t,n){\"use strict\";e.exports=n(190)},function(e,t,n){(function(t){var n=\"undefined\"!=typeof window?window:\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},r=function(){var e=/\\blang(?:uage)?-([\\w-]+)\\b/i,t=0,r=n.Prism={manual:n.Prism&&n.Prism.manual,disableWorkerMessageHandler:n.Prism&&n.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof o?new o(e.type,r.util.encode(e.content),e.alias):\"Array\"===r.util.type(e)?e.map(r.util.encode):e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/\\u00a0/g,\" \")},type:function(e){return Object.prototype.toString.call(e).match(/\\[object (\\w+)\\]/)[1]},objId:function(e){return e.__id||Object.defineProperty(e,\"__id\",{value:++t}),e.__id},clone:function(e,t){var n=r.util.type(e);switch(t=t||{},n){case\"Object\":if(t[r.util.objId(e)])return t[r.util.objId(e)];var o={};for(var i in t[r.util.objId(e)]=o,e)e.hasOwnProperty(i)&&(o[i]=r.util.clone(e[i],t));return o;case\"Array\":if(t[r.util.objId(e)])return t[r.util.objId(e)];o=[];return t[r.util.objId(e)]=o,e.forEach(function(e,n){o[n]=r.util.clone(e,t)}),o}return e}},languages:{extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var o in t)n[o]=t[o];return n},insertBefore:function(e,t,n,o){var i=(o=o||r.languages)[e];if(2==arguments.length){for(var a in n=arguments[1])n.hasOwnProperty(a)&&(i[a]=n[a]);return i}var s={};for(var l in i)if(i.hasOwnProperty(l)){if(l==t)for(var a in n)n.hasOwnProperty(a)&&(s[a]=n[a]);s[l]=i[l]}return r.languages.DFS(r.languages,function(t,n){n===o[e]&&t!=e&&(this[t]=s)}),o[e]=s},DFS:function(e,t,n,o){for(var i in o=o||{},e)e.hasOwnProperty(i)&&(t.call(e,i,e[i],n||i),\"Object\"!==r.util.type(e[i])||o[r.util.objId(e[i])]?\"Array\"!==r.util.type(e[i])||o[r.util.objId(e[i])]||(o[r.util.objId(e[i])]=!0,r.languages.DFS(e[i],t,i,o)):(o[r.util.objId(e[i])]=!0,r.languages.DFS(e[i],t,null,o)))}},plugins:{},highlightAll:function(e,t){r.highlightAllUnder(document,e,t)},highlightAllUnder:function(e,t,n){var o={callback:n,selector:'code[class*=\"language-\"], [class*=\"language-\"] code, code[class*=\"lang-\"], [class*=\"lang-\"] code'};r.hooks.run(\"before-highlightall\",o);for(var i,a=o.elements||e.querySelectorAll(o.selector),s=0;i=a[s++];)r.highlightElement(i,!0===t,o.callback)},highlightElement:function(t,o,i){for(var a,s,l=t;l&&!e.test(l.className);)l=l.parentNode;l&&(a=(l.className.match(e)||[,\"\"])[1].toLowerCase(),s=r.languages[a]),t.className=t.className.replace(e,\"\").replace(/\\s+/g,\" \")+\" language-\"+a,t.parentNode&&(l=t.parentNode,/pre/i.test(l.nodeName)&&(l.className=l.className.replace(e,\"\").replace(/\\s+/g,\" \")+\" language-\"+a));var c={element:t,language:a,grammar:s,code:t.textContent};if(r.hooks.run(\"before-sanity-check\",c),!c.code||!c.grammar)return c.code&&(r.hooks.run(\"before-highlight\",c),c.element.textContent=c.code,r.hooks.run(\"after-highlight\",c)),void r.hooks.run(\"complete\",c);if(r.hooks.run(\"before-highlight\",c),o&&n.Worker){var u=new Worker(r.filename);u.onmessage=function(e){c.highlightedCode=e.data,r.hooks.run(\"before-insert\",c),c.element.innerHTML=c.highlightedCode,i&&i.call(c.element),r.hooks.run(\"after-highlight\",c),r.hooks.run(\"complete\",c)},u.postMessage(JSON.stringify({language:c.language,code:c.code,immediateClose:!0}))}else c.highlightedCode=r.highlight(c.code,c.grammar,c.language),r.hooks.run(\"before-insert\",c),c.element.innerHTML=c.highlightedCode,i&&i.call(t),r.hooks.run(\"after-highlight\",c),r.hooks.run(\"complete\",c)},highlight:function(e,t,n){var i={code:e,grammar:t,language:n};return r.hooks.run(\"before-tokenize\",i),i.tokens=r.tokenize(i.code,i.grammar),r.hooks.run(\"after-tokenize\",i),o.stringify(r.util.encode(i.tokens),i.language)},matchGrammar:function(e,t,n,o,i,a,s){var l=r.Token;for(var c in n)if(n.hasOwnProperty(c)&&n[c]){if(c==s)return;var u=n[c];u=\"Array\"===r.util.type(u)?u:[u];for(var p=0;p<u.length;++p){var f=u[p],d=f.inside,h=!!f.lookbehind,m=!!f.greedy,g=0,y=f.alias;if(m&&!f.pattern.global){var v=f.pattern.toString().match(/[imuy]*$/)[0];f.pattern=RegExp(f.pattern.source,v+\"g\")}f=f.pattern||f;for(var b=o,w=i;b<t.length;w+=t[b].length,++b){var x=t[b];if(t.length>e.length)return;if(!(x instanceof l)){if(m&&b!=t.length-1){if(f.lastIndex=w,!(C=f.exec(e)))break;for(var k=C.index+(h?C[1].length:0),E=C.index+C[0].length,S=b,_=w,O=t.length;S<O&&(_<E||!t[S].type&&!t[S-1].greedy);++S)k>=(_+=t[S].length)&&(++b,w=_);if(t[b]instanceof l)continue;T=S-b,x=e.slice(w,_),C.index-=w}else{f.lastIndex=0;var C=f.exec(x),T=1}if(C){h&&(g=C[1]?C[1].length:0);E=(k=C.index+g)+(C=C[0].slice(g)).length;var j=x.slice(0,k),A=x.slice(E),I=[b,T];j&&(++b,w+=j.length,I.push(j));var P=new l(c,d?r.tokenize(C,d):C,y,C,m);if(I.push(P),A&&I.push(A),Array.prototype.splice.apply(t,I),1!=T&&r.matchGrammar(e,t,n,b,w,!0,c),a)break}else if(a)break}}}}},tokenize:function(e,t,n){var o=[e],i=t.rest;if(i){for(var a in i)t[a]=i[a];delete t.rest}return r.matchGrammar(e,o,t,0,0,!1),o},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var o,i=0;o=n[i++];)o(t)}}},o=r.Token=function(e,t,n,r,o){this.type=e,this.content=t,this.alias=n,this.length=0|(r||\"\").length,this.greedy=!!o};if(o.stringify=function(e,t,n){if(\"string\"==typeof e)return e;if(\"Array\"===r.util.type(e))return e.map(function(n){return o.stringify(n,t,e)}).join(\"\");var i={type:e.type,content:o.stringify(e.content,t,n),tag:\"span\",classes:[\"token\",e.type],attributes:{},language:t,parent:n};if(e.alias){var a=\"Array\"===r.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,a)}r.hooks.run(\"wrap\",i);var s=Object.keys(i.attributes).map(function(e){return e+'=\"'+(i.attributes[e]||\"\").replace(/\"/g,\"&quot;\")+'\"'}).join(\" \");return\"<\"+i.tag+' class=\"'+i.classes.join(\" \")+'\"'+(s?\" \"+s:\"\")+\">\"+i.content+\"</\"+i.tag+\">\"},!n.document)return n.addEventListener?(r.disableWorkerMessageHandler||n.addEventListener(\"message\",function(e){var t=JSON.parse(e.data),o=t.language,i=t.code,a=t.immediateClose;n.postMessage(r.highlight(i,r.languages[o],o)),a&&n.close()},!1),n.Prism):n.Prism;var i=document.currentScript||[].slice.call(document.getElementsByTagName(\"script\")).pop();return i&&(r.filename=i.src,r.manual||i.hasAttribute(\"data-manual\")||(\"loading\"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(r.highlightAll):window.setTimeout(r.highlightAll,16):document.addEventListener(\"DOMContentLoaded\",r.highlightAll))),n.Prism}();e.exports&&(e.exports=r),void 0!==t&&(t.Prism=r),r.languages.markup={comment:/<!--[\\s\\S]*?-->/,prolog:/<\\?[\\s\\S]+?\\?>/,doctype:/<!DOCTYPE[\\s\\S]+?>/i,cdata:/<!\\[CDATA\\[[\\s\\S]*?]]>/i,tag:{pattern:/<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s+[^\\s>\\/=]+(?:=(?:(\"|')(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1|[^\\s'\">=]+))?)*\\s*\\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\\/?[^\\s>\\/]+/i,inside:{punctuation:/^<\\/?/,namespace:/^[^\\s>\\/:]+:/}},\"attr-value\":{pattern:/=(?:(\"|')(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1|[^\\s'\">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\\\])[\"']/,lookbehind:!0}]}},punctuation:/\\/?>/,\"attr-name\":{pattern:/[^\\s>\\/]+/,inside:{namespace:/^[^\\s>\\/:]+:/}}}},entity:/&#?[\\da-z]{1,8};/i},r.languages.markup.tag.inside[\"attr-value\"].inside.entity=r.languages.markup.entity,r.hooks.add(\"wrap\",function(e){\"entity\"===e.type&&(e.attributes.title=e.content.replace(/&amp;/,\"&\"))}),r.languages.xml=r.languages.markup,r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.css={comment:/\\/\\*[\\s\\S]*?\\*\\//,atrule:{pattern:/@[\\w-]+?.*?(?:;|(?=\\s*\\{))/i,inside:{rule:/@[\\w-]+/}},url:/url\\((?:([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1|.*?)\\)/i,selector:/[^{}\\s][^{};]*?(?=\\s*\\{)/,string:{pattern:/(\"|')(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0},property:/[-_a-z\\xA0-\\uFFFF][-\\w\\xA0-\\uFFFF]*(?=\\s*:)/i,important:/\\B!important\\b/i,function:/[-a-z0-9]+(?=\\()/i,punctuation:/[(){};:]/},r.languages.css.atrule.inside.rest=r.languages.css,r.languages.markup&&(r.languages.insertBefore(\"markup\",\"tag\",{style:{pattern:/(<style[\\s\\S]*?>)[\\s\\S]*?(?=<\\/style>)/i,lookbehind:!0,inside:r.languages.css,alias:\"language-css\",greedy:!0}}),r.languages.insertBefore(\"inside\",\"attr-value\",{\"style-attr\":{pattern:/\\s*style=(\"|')(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1/i,inside:{\"attr-name\":{pattern:/^\\s*style/i,inside:r.languages.markup.tag.inside},punctuation:/^\\s*=\\s*['\"]|['\"]\\s*$/,\"attr-value\":{pattern:/.+/i,inside:r.languages.css}},alias:\"language-css\"}},r.languages.markup.tag)),r.languages.clike={comment:[{pattern:/(^|[^\\\\])\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,lookbehind:!0},{pattern:/(^|[^\\\\:])\\/\\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0},\"class-name\":{pattern:/((?:\\b(?:class|interface|extends|implements|trait|instanceof|new)\\s+)|(?:catch\\s+\\())[\\w.\\\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\\\]/}},keyword:/\\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\\b/,boolean:/\\b(?:true|false)\\b/,function:/[a-z0-9_]+(?=\\()/i,number:/\\b0x[\\da-f]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?/i,operator:/--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*|\\/|~|\\^|%/,punctuation:/[{}[\\];(),.:]/},r.languages.javascript=r.languages.extend(\"clike\",{keyword:/\\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\\b/,number:/\\b(?:0[xX][\\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:[Ee][+-]?\\d+)?/,function:/[_$a-z\\xA0-\\uFFFF][$\\w\\xA0-\\uFFFF]*(?=\\s*\\()/i,operator:/-[-=]?|\\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\\|[|=]?|\\*\\*?=?|\\/=?|~|\\^=?|%=?|\\?|\\.{3}/}),r.languages.insertBefore(\"javascript\",\"keyword\",{regex:{pattern:/((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s])\\s*)\\/(\\[[^\\]\\r\\n]+]|\\\\.|[^\\/\\\\\\[\\r\\n])+\\/[gimyu]{0,5}(?=\\s*($|[\\r\\n,.;})\\]]))/,lookbehind:!0,greedy:!0},\"function-variable\":{pattern:/[_$a-z\\xA0-\\uFFFF][$\\w\\xA0-\\uFFFF]*(?=\\s*=\\s*(?:function\\b|(?:\\([^()]*\\)|[_$a-z\\xA0-\\uFFFF][$\\w\\xA0-\\uFFFF]*)\\s*=>))/i,alias:\"function\"},constant:/\\b[A-Z][A-Z\\d_]*\\b/}),r.languages.insertBefore(\"javascript\",\"string\",{\"template-string\":{pattern:/`(?:\\\\[\\s\\S]|\\${[^}]+}|[^\\\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\\${[^}]+}/,inside:{\"interpolation-punctuation\":{pattern:/^\\${|}$/,alias:\"punctuation\"},rest:null}},string:/[\\s\\S]+/}}}),r.languages.javascript[\"template-string\"].inside.interpolation.inside.rest=r.languages.javascript,r.languages.markup&&r.languages.insertBefore(\"markup\",\"tag\",{script:{pattern:/(<script[\\s\\S]*?>)[\\s\\S]*?(?=<\\/script>)/i,lookbehind:!0,inside:r.languages.javascript,alias:\"language-javascript\",greedy:!0}}),r.languages.js=r.languages.javascript,\"undefined\"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var e={js:\"javascript\",py:\"python\",rb:\"ruby\",ps1:\"powershell\",psm1:\"powershell\",sh:\"bash\",bat:\"batch\",h:\"c\",tex:\"latex\"};Array.prototype.slice.call(document.querySelectorAll(\"pre[data-src]\")).forEach(function(t){for(var n,o=t.getAttribute(\"data-src\"),i=t,a=/\\blang(?:uage)?-([\\w-]+)\\b/i;i&&!a.test(i.className);)i=i.parentNode;if(i&&(n=(t.className.match(a)||[,\"\"])[1]),!n){var s=(o.match(/\\.(\\w+)$/)||[,\"\"])[1];n=e[s]||s}var l=document.createElement(\"code\");l.className=\"language-\"+n,t.textContent=\"\",l.textContent=\"Loading…\",t.appendChild(l);var c=new XMLHttpRequest;c.open(\"GET\",o,!0),c.onreadystatechange=function(){4==c.readyState&&(c.status<400&&c.responseText?(l.textContent=c.responseText,r.highlightElement(l)):c.status>=400?l.textContent=\"✖ Error \"+c.status+\" while fetching file: \"+c.statusText:l.textContent=\"✖ Error: File does not exist or is empty\")},c.send(null)}),r.plugins.toolbar&&r.plugins.toolbar.registerButton(\"download-file\",function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute(\"data-src\")&&t.hasAttribute(\"data-download-link\")){var n=t.getAttribute(\"data-src\"),r=document.createElement(\"a\");return r.textContent=t.getAttribute(\"data-download-link-label\")||\"Download\",r.setAttribute(\"download\",\"\"),r.href=n,r}})},document.addEventListener(\"DOMContentLoaded\",self.Prism.fileHighlight))}).call(this,n(4))},function(e,t,n){\"use strict\";var r=n(57),o={};o[n(2)(\"toStringTag\")]=\"z\",o+\"\"!=\"[object z]\"&&n(21)(Object.prototype,\"toString\",function(){return\"[object \"+r(this)+\"]\"},!0)},function(e,t,n){var r=n(26),o=n(2)(\"toStringTag\"),i=\"Arguments\"==r(function(){return arguments}());e.exports=function(e){var t,n,a;return void 0===e?\"Undefined\":null===e?\"Null\":\"string\"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:i?r(t):\"Object\"==(a=r(t))&&\"function\"==typeof t.callee?\"Arguments\":a}},function(e,t,n){var r=n(7),o=n(5),i=o[\"__core-js_shared__\"]||(o[\"__core-js_shared__\"]={});(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})(\"versions\",[]).push({version:r.version,mode:n(31)?\"pure\":\"global\",copyright:\"© 2018 Denis Pushkarev (zloirock.ru)\"})},function(e,t,n){var r=n(8),o=n(5).document,i=r(o)&&r(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},function(e,t,n){var r=n(8);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&\"function\"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if(\"function\"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&\"function\"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError(\"Can't convert object to primitive value\")}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){\"use strict\";var r=n(31),o=n(18),i=n(21),a=n(22),s=n(33),l=n(138),c=n(36),u=n(142),p=n(2)(\"iterator\"),f=!([].keys&&\"next\"in[].keys()),d=function(){return this};e.exports=function(e,t,n,h,m,g,y){l(n,t,h);var v,b,w,x=function(e){if(!f&&e in _)return _[e];switch(e){case\"keys\":case\"values\":return function(){return new n(this,e)}}return function(){return new n(this,e)}},k=t+\" Iterator\",E=\"values\"==m,S=!1,_=e.prototype,O=_[p]||_[\"@@iterator\"]||m&&_[m],C=O||x(m),T=m?E?x(\"entries\"):C:void 0,j=\"Array\"==t&&_.entries||O;if(j&&(w=u(j.call(new e)))!==Object.prototype&&w.next&&(c(w,k,!0),r||\"function\"==typeof w[p]||a(w,p,d)),E&&O&&\"values\"!==O.name&&(S=!0,C=function(){return O.call(this)}),r&&!y||!f&&!S&&_[p]||a(_,p,C),s[t]=C,s[k]=d,m)if(v={values:E?C:x(\"values\"),keys:g?C:x(\"keys\"),entries:T},y)for(b in v)b in _||i(_,b,v[b]);else o(o.P+o.F*(f||S),t,v);return v}},function(e,t,n){var r=n(14),o=n(139),i=n(66),a=n(65)(\"IE_PROTO\"),s=function(){},l=function(){var e,t=n(59)(\"iframe\"),r=i.length;for(t.style.display=\"none\",n(85).appendChild(t),t.src=\"javascript:\",(e=t.contentWindow.document).open(),e.write(\"<script>document.F=Object<\\/script>\"),e.close(),l=e.F;r--;)delete l.prototype[i[r]];return l()};e.exports=Object.create||function(e,t){var n;return null!==e?(s.prototype=r(e),n=new s,s.prototype=null,n[a]=e):n=l(),void 0===t?n:o(n,t)}},function(e,t,n){var r=n(26);e.exports=Object(\"z\").propertyIsEnumerable(0)?Object:function(e){return\"String\"==r(e)?e.split(\"\"):Object(e)}},function(e,t,n){var r=n(58)(\"keys\"),o=n(32);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t){e.exports=\"constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf\".split(\",\")},function(e,t,n){var r=n(43);e.exports=function(e){return Object(r(e))}},function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+\": incorrect invocation!\");return e}},function(e,t,n){var r=n(24),o=n(145),i=n(146),a=n(14),s=n(35),l=n(147),c={},u={};(t=e.exports=function(e,t,n,p,f){var d,h,m,g,y=f?function(){return e}:l(e),v=r(n,p,t?2:1),b=0;if(\"function\"!=typeof y)throw TypeError(e+\" is not iterable!\");if(i(y)){for(d=s(e.length);d>b;b++)if((g=t?v(a(h=e[b])[0],h[1]):v(e[b]))===c||g===u)return g}else for(m=y.call(e);!(h=m.next()).done;)if((g=o(m,v,h.value,t))===c||g===u)return g}).BREAK=c,t.RETURN=u},function(e,t,n){var r=n(21);e.exports=function(e,t,n){for(var o in t)r(e,o,t[o],n);return e}},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,n){var r=n(32)(\"meta\"),o=n(8),i=n(23),a=n(16).f,s=0,l=Object.isExtensible||function(){return!0},c=!n(27)(function(){return l(Object.preventExtensions({}))}),u=function(e){a(e,r,{value:{i:\"O\"+ ++s,w:{}}})},p=e.exports={KEY:r,NEED:!1,fastKey:function(e,t){if(!o(e))return\"symbol\"==typeof e?e:(\"string\"==typeof e?\"S\":\"P\")+e;if(!i(e,r)){if(!l(e))return\"F\";if(!t)return\"E\";u(e)}return e[r].i},getWeak:function(e,t){if(!i(e,r)){if(!l(e))return!0;if(!t)return!1;u(e)}return e[r].w},onFreeze:function(e){return c&&p.NEED&&l(e)&&!i(e,r)&&u(e),e}}},function(e,t,n){\"use strict\";var r=n(29);e.exports=new r({explicit:[n(198),n(199),n(200)]})},function(e,t,n){\"use strict\";var r=n(29);e.exports=r.DEFAULT=new r({include:[n(48)],explicit:[n(211),n(212),n(213)]})},function(e,t,n){\"use strict\";e.exports=u;var r=n(51),o=n(19),i=n(25),a=/\\//g,s=/~/g,l=/~1/g,c=/~0/g;function u(e,t,n){this.$ref=e,this.path=t,this.originalPath=n||t,this.value=void 0,this.circular=!1,this.indirections=0}function p(e,t){if(r.isAllowed$Ref(e.value,t)){var n=o.resolve(e.path,e.value.$ref);if(n!==e.path){var i=e.$ref.$refs._resolve(n,t);return e.indirections+=i.indirections+1,r.isExtended$Ref(e.value)?(e.value=r.dereference(e.value,i.value),!1):(e.$ref=i.$ref,e.path=i.path,e.value=i.value,!0)}e.circular=!0}}function f(e,t,n){if(!e.value||\"object\"!=typeof e.value)throw i.syntax('Error assigning $ref pointer \"%s\". \\nCannot set \"%s\" of a non-object.',e.path,t);return\"-\"===t&&Array.isArray(e.value)?e.value.push(n):e.value[t]=n,n}u.prototype.resolve=function(e,t){var n=u.parse(this.path);this.value=e;for(var r=0;r<n.length;r++){p(this,t)&&(this.path=u.join(this.path,n.slice(r)));var o=n[r];if(void 0===this.value[o])throw i.syntax('Error resolving $ref pointer \"%s\". \\nToken \"%s\" does not exist.',this.originalPath,o);this.value=this.value[o]}return p(this,t),this},u.prototype.set=function(e,t,n){var r,o=u.parse(this.path);if(0===o.length)return this.value=t,t;this.value=e;for(var i=0;i<o.length-1;i++)p(this,n),r=o[i],this.value&&void 0!==this.value[r]?this.value=this.value[r]:this.value=f(this,r,{});return p(this,n),f(this,r=o[o.length-1],t),e},u.parse=function(e){var t=o.getHash(e).substr(1);if(!t)return[];t=t.split(\"/\");for(var n=0;n<t.length;n++)t[n]=decodeURIComponent(t[n].replace(l,\"/\").replace(c,\"~\"));if(\"\"!==t[0])throw i.syntax('Invalid $ref pointer \"%s\". Pointers must begin with \"#/\"',t);return t.slice(1)},u.join=function(e,t){-1===e.indexOf(\"#\")&&(e+=\"#\"),t=Array.isArray(t)?t:[t];for(var n=0;n<t.length;n++){var r=t[n];e+=\"/\"+encodeURIComponent(r.replace(s,\"~0\").replace(a,\"~1\"))}return e}},function(e,t,n){\"use strict\";function r(e){return e=(e=e.split(\"~1\").join(\"/\")).split(\"~0\").join(\"~\")}e.exports={jptr:function(e,t,n){if(void 0===e)return!1;if(!t||\"#\"===t)return void 0!==n?n:e;if(t.indexOf(\"#\")>=0){var o=t.split(\"#\");if(o[0])return!1;t=o[1],t=decodeURIComponent(t.slice(1)).split(\"+\").join(\" \")}t.startsWith(\"/\")&&(t=t.slice(1));for(var i=t.split(\"/\"),a=0;a<i.length;a++){i[a]=r(i[a]);var s=void 0!==n&&a==i.length-1,l=parseInt(i[a],10);if(!Array.isArray(e)||isNaN(l)||l.toString()!==i[a]?l=Array.isArray(e)&&\"-\"===i[a]?-2:-1:i[a]=a>0?i[a-1]:\"\",-1!=l||e.hasOwnProperty(i[a]))if(l>=0)s&&(e[l]=n),e=e[l];else{if(-2===l)return s?(Array.isArray(e)&&e.push(n),n):void 0;s&&(e[i[a]]=n),e=e[i[a]]}else{if(void 0===n||\"object\"!=typeof e||Array.isArray(e))return!1;e[i[a]]=s?n:\"0\"===i[a+1]||\"-\"===i[a+1]?[]:{},e=e[i[a]]}}return e},jpescape:function(e){return e=(e=e.split(\"~\").join(\"~0\")).split(\"/\").join(\"~1\")},jpunescape:r}},function(e,t,n){\"use strict\";e.exports={nop:function(e){return e},clone:function(e){return JSON.parse(JSON.stringify(e))},shallowClone:function(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},deepClone:function e(t){var n=Array.isArray(t)?[]:{};for(var r in t)(t.hasOwnProperty(r)||Array.isArray(t))&&(n[r]=\"object\"==typeof t[r]?e(t[r]):t[r]);return n},fastClone:function(e){return Object.assign({},e)},circularClone:function e(t,n){if(n||(n=new WeakMap),Object(t)!==t||t instanceof Function)return t;if(n.has(t))return n.get(t);try{var r=new t.constructor}catch(e){r=Object.create(Object.getPrototypeOf(t))}return n.set(t,r),Object.assign.apply(Object,[r].concat(Object.keys(t).map(function(r){var o;return(o={})[r]=e(t[r],n),o})))}}},function(e,t,n){e.exports=function e(t){\"use strict\";var n=/^\\0+/g,r=/[\\0\\r\\f]/g,o=/: */g,i=/zoo|gra/,a=/([,: ])(transform)/g,s=/,+\\s*(?![^(]*[)])/g,l=/ +\\s*(?![^(]*[)])/g,c=/ *[\\0] */g,u=/,\\r+?/g,p=/([\\t\\r\\n ])*\\f?&/g,f=/:global\\(((?:[^\\(\\)\\[\\]]*|\\[.*\\]|\\([^\\(\\)]*\\))*)\\)/g,d=/\\W+/g,h=/@(k\\w+)\\s*(\\S*)\\s*/,m=/::(place)/g,g=/:(read-only)/g,y=/\\s+(?=[{\\];=:>])/g,v=/([[}=:>])\\s+/g,b=/(\\{[^{]+?);(?=\\})/g,w=/\\s{2,}/g,x=/([^\\(])(:+) */g,k=/[svh]\\w+-[tblr]{2}/,E=/\\(\\s*(.*)\\s*\\)/g,S=/([\\s\\S]*?);/g,_=/-self|flex-/g,O=/[^]*?(:[rp][el]a[\\w-]+)[^]*/,C=/stretch|:\\s*\\w+\\-(?:conte|avail)/,T=/([^-])(image-set\\()/,j=\"-webkit-\",A=\"-moz-\",I=\"-ms-\",P=59,R=125,N=123,L=40,M=41,D=91,F=93,U=10,B=13,z=9,$=64,W=32,q=38,H=45,Y=95,V=42,Q=44,G=58,X=39,K=34,J=47,Z=62,ee=43,te=126,ne=0,re=12,oe=11,ie=107,ae=109,se=115,le=112,ce=111,ue=105,pe=99,fe=100,de=112,he=1,me=1,ge=0,ye=1,ve=1,be=1,we=0,xe=0,ke=0,Ee=[],Se=[],_e=0,Oe=null,Ce=-2,Te=-1,je=0,Ae=1,Ie=2,Pe=3,Re=0,Ne=1,Le=\"\",Me=\"\",De=\"\";function Fe(e,t,o,i,a){for(var s,l,u=0,p=0,f=0,d=0,y=0,v=0,b=0,w=0,k=0,S=0,_=0,O=0,C=0,T=0,Y=0,we=0,Se=0,Oe=0,Ce=0,Te=o.length,Be=Te-1,Ye=\"\",Ve=\"\",Qe=\"\",Ge=\"\",Xe=\"\",Ke=\"\";Y<Te;){if(b=o.charCodeAt(Y),Y===Be&&p+d+f+u!==0&&(0!==p&&(b=p===J?U:J),d=f=u=0,Te++,Be++),p+d+f+u===0){if(Y===Be&&(we>0&&(Ve=Ve.replace(r,\"\")),Ve.trim().length>0)){switch(b){case W:case z:case P:case B:case U:break;default:Ve+=o.charAt(Y)}b=P}if(1===Se)switch(b){case N:case R:case P:case K:case X:case L:case M:case Q:Se=0;case z:case B:case U:case W:break;default:for(Se=0,Ce=Y,y=b,Y--,b=P;Ce<Te;)switch(o.charCodeAt(Ce++)){case U:case B:case P:++Y,b=y,Ce=Te;break;case G:we>0&&(++Y,b=y);case N:Ce=Te}}switch(b){case N:for(y=(Ve=Ve.trim()).charCodeAt(0),_=1,Ce=++Y;Y<Te;){switch(b=o.charCodeAt(Y)){case N:_++;break;case R:_--;break;case J:switch(v=o.charCodeAt(Y+1)){case V:case J:Y=He(v,Y,Be,o)}break;case D:b++;case L:b++;case K:case X:for(;Y++<Be&&o.charCodeAt(Y)!==b;);}if(0===_)break;Y++}switch(Qe=o.substring(Ce,Y),y===ne&&(y=(Ve=Ve.replace(n,\"\").trim()).charCodeAt(0)),y){case $:switch(we>0&&(Ve=Ve.replace(r,\"\")),v=Ve.charCodeAt(1)){case fe:case ae:case se:case H:s=t;break;default:s=Ee}if(Ce=(Qe=Fe(t,s,Qe,v,a+1)).length,ke>0&&0===Ce&&(Ce=Ve.length),_e>0&&(s=Ue(Ee,Ve,Oe),l=qe(Pe,Qe,s,t,me,he,Ce,v,a,i),Ve=s.join(\"\"),void 0!==l&&0===(Ce=(Qe=l.trim()).length)&&(v=0,Qe=\"\")),Ce>0)switch(v){case se:Ve=Ve.replace(E,We);case fe:case ae:case H:Qe=Ve+\"{\"+Qe+\"}\";break;case ie:Qe=(Ve=Ve.replace(h,\"$1 $2\"+(Ne>0?Le:\"\")))+\"{\"+Qe+\"}\",Qe=1===ve||2===ve&&$e(\"@\"+Qe,3)?\"@\"+j+Qe+\"@\"+Qe:\"@\"+Qe;break;default:Qe=Ve+Qe,i===de&&(Ge+=Qe,Qe=\"\")}else Qe=\"\";break;default:Qe=Fe(t,Ue(t,Ve,Oe),Qe,i,a+1)}Xe+=Qe,O=0,Se=0,T=0,we=0,Oe=0,C=0,Ve=\"\",Qe=\"\",b=o.charCodeAt(++Y);break;case R:case P:if((Ce=(Ve=(we>0?Ve.replace(r,\"\"):Ve).trim()).length)>1)switch(0===T&&((y=Ve.charCodeAt(0))===H||y>96&&y<123)&&(Ce=(Ve=Ve.replace(\" \",\":\")).length),_e>0&&void 0!==(l=qe(Ae,Ve,t,e,me,he,Ge.length,i,a,i))&&0===(Ce=(Ve=l.trim()).length)&&(Ve=\"\\0\\0\"),y=Ve.charCodeAt(0),v=Ve.charCodeAt(1),y){case ne:break;case $:if(v===ue||v===pe){Ke+=Ve+o.charAt(Y);break}default:if(Ve.charCodeAt(Ce-1)===G)break;Ge+=ze(Ve,y,v,Ve.charCodeAt(2))}O=0,Se=0,T=0,we=0,Oe=0,Ve=\"\",b=o.charCodeAt(++Y)}}switch(b){case B:case U:if(p+d+f+u+xe===0)switch(S){case M:case X:case K:case $:case te:case Z:case V:case ee:case J:case H:case G:case Q:case P:case N:case R:break;default:T>0&&(Se=1)}p===J?p=0:ye+O===0&&i!==ie&&Ve.length>0&&(we=1,Ve+=\"\\0\"),_e*Re>0&&qe(je,Ve,t,e,me,he,Ge.length,i,a,i),he=1,me++;break;case P:case R:if(p+d+f+u===0){he++;break}default:switch(he++,Ye=o.charAt(Y),b){case z:case W:if(d+u+p===0)switch(w){case Q:case G:case z:case W:Ye=\"\";break;default:b!==W&&(Ye=\" \")}break;case ne:Ye=\"\\\\0\";break;case re:Ye=\"\\\\f\";break;case oe:Ye=\"\\\\v\";break;case q:d+p+u===0&&ye>0&&(Oe=1,we=1,Ye=\"\\f\"+Ye);break;case 108:if(d+p+u+ge===0&&T>0)switch(Y-T){case 2:w===le&&o.charCodeAt(Y-3)===G&&(ge=w);case 8:k===ce&&(ge=k)}break;case G:d+p+u===0&&(T=Y);break;case Q:p+f+d+u===0&&(we=1,Ye+=\"\\r\");break;case K:case X:0===p&&(d=d===b?0:0===d?b:d);break;case D:d+p+f===0&&u++;break;case F:d+p+f===0&&u--;break;case M:d+p+u===0&&f--;break;case L:if(d+p+u===0){if(0===O)switch(2*w+3*k){case 533:break;default:_=0,O=1}f++}break;case $:p+f+d+u+T+C===0&&(C=1);break;case V:case J:if(d+u+f>0)break;switch(p){case 0:switch(2*b+3*o.charCodeAt(Y+1)){case 235:p=J;break;case 220:Ce=Y,p=V}break;case V:b===J&&w===V&&Ce+2!==Y&&(33===o.charCodeAt(Ce+2)&&(Ge+=o.substring(Ce,Y+1)),Ye=\"\",p=0)}}if(0===p){if(ye+d+u+C===0&&i!==ie&&b!==P)switch(b){case Q:case te:case Z:case ee:case M:case L:if(0===O){switch(w){case z:case W:case U:case B:Ye+=\"\\0\";break;default:Ye=\"\\0\"+Ye+(b===Q?\"\":\"\\0\")}we=1}else switch(b){case L:T+7===Y&&108===w&&(T=0),O=++_;break;case M:0==(O=--_)&&(we=1,Ye+=\"\\0\")}break;case z:case W:switch(w){case ne:case N:case R:case P:case Q:case re:case z:case W:case U:case B:break;default:0===O&&(we=1,Ye+=\"\\0\")}}Ve+=Ye,b!==W&&b!==z&&(S=b)}}k=w,w=b,Y++}if(Ce=Ge.length,ke>0&&0===Ce&&0===Xe.length&&0===t[0].length==0&&(i!==ae||1===t.length&&(ye>0?Me:De)===t[0])&&(Ce=t.join(\",\").length+2),Ce>0){if(s=0===ye&&i!==ie?function(e){for(var t,n,o=0,i=e.length,a=Array(i);o<i;++o){for(var s=e[o].split(c),l=\"\",u=0,p=0,f=0,d=0,h=s.length;u<h;++u)if(!(0===(p=(n=s[u]).length)&&h>1)){if(f=l.charCodeAt(l.length-1),d=n.charCodeAt(0),t=\"\",0!==u)switch(f){case V:case te:case Z:case ee:case W:case L:break;default:t=\" \"}switch(d){case q:n=t+Me;case te:case Z:case ee:case W:case M:case L:break;case D:n=t+n+Me;break;case G:switch(2*n.charCodeAt(1)+3*n.charCodeAt(2)){case 530:if(be>0){n=t+n.substring(8,p-1);break}default:(u<1||s[u-1].length<1)&&(n=t+Me+n)}break;case Q:t=\"\";default:n=p>1&&n.indexOf(\":\")>0?t+n.replace(x,\"$1\"+Me+\"$2\"):t+n+Me}l+=n}a[o]=l.replace(r,\"\").trim()}return a}(t):t,_e>0&&void 0!==(l=qe(Ie,Ge,s,e,me,he,Ce,i,a,i))&&0===(Ge=l).length)return Ke+Ge+Xe;if(Ge=s.join(\",\")+\"{\"+Ge+\"}\",ve*ge!=0){switch(2!==ve||$e(Ge,2)||(ge=0),ge){case ce:Ge=Ge.replace(g,\":\"+A+\"$1\")+Ge;break;case le:Ge=Ge.replace(m,\"::\"+j+\"input-$1\")+Ge.replace(m,\"::\"+A+\"$1\")+Ge.replace(m,\":\"+I+\"input-$1\")+Ge}ge=0}}return Ke+Ge+Xe}function Ue(e,t,n){var r=t.trim().split(u),o=r,i=r.length,a=e.length;switch(a){case 0:case 1:for(var s=0,l=0===a?\"\":e[0]+\" \";s<i;++s)o[s]=Be(l,o[s],n,a).trim();break;default:s=0;var c=0;for(o=[];s<i;++s)for(var p=0;p<a;++p)o[c++]=Be(e[p]+\" \",r[s],n,a).trim()}return o}function Be(e,t,n,r){var o=t,i=o.charCodeAt(0);switch(i<33&&(i=(o=o.trim()).charCodeAt(0)),i){case q:switch(ye+r){case 0:case 1:if(0===e.trim().length)break;default:return o.replace(p,\"$1\"+e.trim())}break;case G:switch(o.charCodeAt(1)){case 103:if(be>0&&ye>0)return o.replace(f,\"$1\").replace(p,\"$1\"+De);break;default:return e.trim()+o.replace(p,\"$1\"+e.trim())}default:if(n*ye>0&&o.indexOf(\"\\f\")>0)return o.replace(p,(e.charCodeAt(0)===G?\"\":\"$1\")+e.trim())}return e+o}function ze(e,t,n,r){var c,u=0,p=e+\";\",f=2*t+3*n+4*r;if(944===f)return function(e){var t=e.length,n=e.indexOf(\":\",9)+1,r=e.substring(0,n).trim(),o=e.substring(n,t-1).trim();switch(e.charCodeAt(9)*Ne){case 0:break;case H:if(110!==e.charCodeAt(10))break;default:for(var i=o.split((o=\"\",s)),a=0,n=0,t=i.length;a<t;n=0,++a){for(var c=i[a],u=c.split(l);c=u[n];){var p=c.charCodeAt(0);if(1===Ne&&(p>$&&p<90||p>96&&p<123||p===Y||p===H&&c.charCodeAt(1)!==H))switch(isNaN(parseFloat(c))+(-1!==c.indexOf(\"(\"))){case 1:switch(c){case\"infinite\":case\"alternate\":case\"backwards\":case\"running\":case\"normal\":case\"forwards\":case\"both\":case\"none\":case\"linear\":case\"ease\":case\"ease-in\":case\"ease-out\":case\"ease-in-out\":case\"paused\":case\"reverse\":case\"alternate-reverse\":case\"inherit\":case\"initial\":case\"unset\":case\"step-start\":case\"step-end\":break;default:c+=Le}}u[n++]=c}o+=(0===a?\"\":\",\")+u.join(\" \")}}return o=r+o+\";\",1===ve||2===ve&&$e(o,1)?j+o+o:o}(p);if(0===ve||2===ve&&!$e(p,1))return p;switch(f){case 1015:return 97===p.charCodeAt(10)?j+p+p:p;case 951:return 116===p.charCodeAt(3)?j+p+p:p;case 963:return 110===p.charCodeAt(5)?j+p+p:p;case 1009:if(100!==p.charCodeAt(4))break;case 969:case 942:return j+p+p;case 978:return j+p+A+p+p;case 1019:case 983:return j+p+A+p+I+p+p;case 883:return p.charCodeAt(8)===H?j+p+p:p.indexOf(\"image-set(\",11)>0?p.replace(T,\"$1\"+j+\"$2\")+p:p;case 932:if(p.charCodeAt(4)===H)switch(p.charCodeAt(5)){case 103:return j+\"box-\"+p.replace(\"-grow\",\"\")+j+p+I+p.replace(\"grow\",\"positive\")+p;case 115:return j+p+I+p.replace(\"shrink\",\"negative\")+p;case 98:return j+p+I+p.replace(\"basis\",\"preferred-size\")+p}return j+p+I+p+p;case 964:return j+p+I+\"flex-\"+p+p;case 1023:if(99!==p.charCodeAt(8))break;return c=p.substring(p.indexOf(\":\",15)).replace(\"flex-\",\"\").replace(\"space-between\",\"justify\"),j+\"box-pack\"+c+j+p+I+\"flex-pack\"+c+p;case 1005:return i.test(p)?p.replace(o,\":\"+j)+p.replace(o,\":\"+A)+p:p;case 1e3:switch(u=(c=p.substring(13).trim()).indexOf(\"-\")+1,c.charCodeAt(0)+c.charCodeAt(u)){case 226:c=p.replace(k,\"tb\");break;case 232:c=p.replace(k,\"tb-rl\");break;case 220:c=p.replace(k,\"lr\");break;default:return p}return j+p+I+c+p;case 1017:if(-1===p.indexOf(\"sticky\",9))return p;case 975:switch(u=(p=e).length-10,f=(c=(33===p.charCodeAt(u)?p.substring(0,u):p).substring(e.indexOf(\":\",7)+1).trim()).charCodeAt(0)+(0|c.charCodeAt(7))){case 203:if(c.charCodeAt(8)<111)break;case 115:p=p.replace(c,j+c)+\";\"+p;break;case 207:case 102:p=p.replace(c,j+(f>102?\"inline-\":\"\")+\"box\")+\";\"+p.replace(c,j+c)+\";\"+p.replace(c,I+c+\"box\")+\";\"+p}return p+\";\";case 938:if(p.charCodeAt(5)===H)switch(p.charCodeAt(6)){case 105:return c=p.replace(\"-items\",\"\"),j+p+j+\"box-\"+c+I+\"flex-\"+c+p;case 115:return j+p+I+\"flex-item-\"+p.replace(_,\"\")+p;default:return j+p+I+\"flex-line-pack\"+p.replace(\"align-content\",\"\").replace(_,\"\")+p}break;case 973:case 989:if(p.charCodeAt(3)!==H||122===p.charCodeAt(4))break;case 931:case 953:if(!0===C.test(e))return 115===(c=e.substring(e.indexOf(\":\")+1)).charCodeAt(0)?ze(e.replace(\"stretch\",\"fill-available\"),t,n,r).replace(\":fill-available\",\":stretch\"):p.replace(c,j+c)+p.replace(c,A+c.replace(\"fill-\",\"\"))+p;break;case 962:if(p=j+p+(102===p.charCodeAt(5)?I+p:\"\")+p,n+r===211&&105===p.charCodeAt(13)&&p.indexOf(\"transform\",10)>0)return p.substring(0,p.indexOf(\";\",27)+1).replace(a,\"$1\"+j+\"$2\")+p}return p}function $e(e,t){var n=e.indexOf(1===t?\":\":\"{\"),r=e.substring(0,3!==t?n:10),o=e.substring(n+1,e.length-1);return Oe(2!==t?r:r.replace(O,\"$1\"),o,t)}function We(e,t){var n=ze(t,t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2));return n!==t+\";\"?n.replace(S,\" or ($1)\").substring(4):\"(\"+t+\")\"}function qe(e,t,n,r,o,i,a,s,l,c){for(var u,p=0,f=t;p<_e;++p)switch(u=Se[p].call(Ve,e,f,n,r,o,i,a,s,l,c)){case void 0:case!1:case!0:case null:break;default:f=u}if(f!==t)return f}function He(e,t,n,r){for(var o=t+1;o<n;++o)switch(r.charCodeAt(o)){case J:if(e===V&&r.charCodeAt(o-1)===V&&t+2!==o)return o+1;break;case U:if(e===J)return o+1}return o}function Ye(e){for(var t in e){var n=e[t];switch(t){case\"keyframe\":Ne=0|n;break;case\"global\":be=0|n;break;case\"cascade\":ye=0|n;break;case\"compress\":we=0|n;break;case\"semicolon\":xe=0|n;break;case\"preserve\":ke=0|n;break;case\"prefix\":Oe=null,n?\"function\"!=typeof n?ve=1:(ve=2,Oe=n):ve=0}}return Ye}function Ve(t,n){if(void 0!==this&&this.constructor===Ve)return e(t);var o=t,i=o.charCodeAt(0);i<33&&(i=(o=o.trim()).charCodeAt(0)),Ne>0&&(Le=o.replace(d,i===D?\"\":\"-\")),i=1,1===ye?De=o:Me=o;var a,s=[De];_e>0&&void 0!==(a=qe(Te,n,s,s,me,he,0,0,0,0))&&\"string\"==typeof a&&(n=a);var l=Fe(Ee,s,n,0,0);return _e>0&&void 0!==(a=qe(Ce,l,s,s,me,he,l.length,0,0,0))&&\"string\"!=typeof(l=a)&&(i=0),Le=\"\",De=\"\",Me=\"\",ge=0,me=1,he=1,we*i==0?l:l.replace(r,\"\").replace(y,\"\").replace(v,\"$1\").replace(b,\"$1\").replace(w,\" \")}return Ve.use=function e(t){switch(t){case void 0:case null:_e=Se.length=0;break;default:if(\"function\"==typeof t)Se[_e++]=t;else if(\"object\"==typeof t)for(var n=0,r=t.length;n<r;++n)e(t[n]);else Re=0|!!t}return e},Ve.set=Ye,void 0!==t&&Ye(t),Ve}(null)},function(e,t,n){\n/*!***************************************************\n* mark.js v8.11.1\n* https://markjs.io/\n* Copyright (c) 2014–2018, Julian Kühnel\n* Released under the MIT license https://git.io/vwTVl\n*****************************************************/\ne.exports=function(){\"use strict\";var e=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},t=function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")},n=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=function(){function e(n){var r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=o,this.iframesTimeout=i}return n(e,[{key:\"getContexts\",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:\"string\"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach(function(t){var n=e.filter(function(e){return e.contains(t)}).length>0;-1!==e.indexOf(t)||n||e.push(t)}),e}},{key:\"getIframeContents\",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var o=e.contentWindow;if(r=o.document,!o||!r)throw new Error(\"iframe inaccessible\")}catch(e){n()}r&&t(r)}},{key:\"isIframeBlank\",value:function(e){var t=\"about:blank\",n=e.getAttribute(\"src\").trim(),r=e.contentWindow.location.href;return r===t&&n!==t&&n}},{key:\"observeIframeLoad\",value:function(e,t,n){var r=this,o=!1,i=null,a=function a(){if(!o){o=!0,clearTimeout(i);try{r.isIframeBlank(e)||(e.removeEventListener(\"load\",a),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener(\"load\",a),i=setTimeout(a,this.iframesTimeout)}},{key:\"onIframeReady\",value:function(e,t,n){try{\"complete\"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:\"waitForIframes\",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector(\"html\"),function(){--r||t()})},function(e){e||t()})}},{key:\"forEachIframe\",value:function(t,n,r){var o=this,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=t.querySelectorAll(\"iframe\"),s=a.length,l=0;a=Array.prototype.slice.call(a);var c=function(){--s<=0&&i(l)};s||c(),a.forEach(function(t){e.matches(t,o.exclude)?c():o.onIframeReady(t,function(e){n(t)&&(l++,r(e)),c()},c)})}},{key:\"createIterator\",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:\"createInstanceOnIframe\",value:function(t){return new e(t.querySelector(\"html\"),this.iframes)}},{key:\"compareNodeIframe\",value:function(e,t,n){var r=e.compareDocumentPosition(n),o=Node.DOCUMENT_POSITION_PRECEDING;if(r&o){if(null===t)return!0;var i=t.compareDocumentPosition(n),a=Node.DOCUMENT_POSITION_FOLLOWING;if(i&a)return!0}return!1}},{key:\"getIteratorNode\",value:function(e){var t=e.previousNode(),n=void 0;return n=null===t?e.nextNode():e.nextNode()&&e.nextNode(),{prevNode:t,node:n}}},{key:\"checkIframeFilter\",value:function(e,t,n,r){var o=!1,i=!1;return r.forEach(function(e,t){e.val===n&&(o=t,i=e.handled)}),this.compareNodeIframe(e,t,n)?(!1!==o||i?!1===o||i||(r[o].handled=!0):r.push({val:n,handled:!0}),!0):(!1===o&&r.push({val:n,handled:!1}),!1)}},{key:\"handleOpenIframes\",value:function(e,t,n,r){var o=this;e.forEach(function(e){e.handled||o.getIframeContents(e.val,function(e){o.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:\"iterateThroughNodes\",value:function(e,t,n,r,o){for(var i=this,a=this.createIterator(t,e,r),s=[],l=[],c=void 0,u=void 0;p=void 0,p=i.getIteratorNode(a),u=p.prevNode,c=p.node;)this.iframes&&this.forEachIframe(t,function(e){return i.checkIframeFilter(c,u,e,s)},function(t){i.createInstanceOnIframe(t).forEachNode(e,function(e){return l.push(e)},r)}),l.push(c);var p;l.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(s,e,n,r),o()}},{key:\"forEachNode\",value:function(e,t,n){var r=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},i=this.getContexts(),a=i.length;a||o(),i.forEach(function(i){var s=function(){r.iterateThroughNodes(e,i,t,n,function(){--a<=0&&o()})};r.iframes?r.waitForIframes(i,s):s()})}}],[{key:\"matches\",value:function(e,t){var n=\"string\"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var o=!1;return n.every(function(t){return!r.call(e,t)||(o=!0,!1)}),o}return!1}}]),e}(),i=function(){function i(e){t(this,i),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf(\"MSIE\")>-1||n.indexOf(\"Trident\")>-1)&&(this.ie=!0)}return n(i,[{key:\"log\",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:\"debug\",r=this.opt.log;this.opt.debug&&\"object\"===(void 0===r?\"undefined\":e(r))&&\"function\"==typeof r[n]&&r[n](\"mark.js: \"+t)}},{key:\"escapeStr\",value:function(e){return e.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g,\"\\\\$&\")}},{key:\"createRegExp\",value:function(e){return\"disabled\"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),\"disabled\"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e)}},{key:\"createSynonymsRegExp\",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?\"\":\"i\",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?\"\\0\":\"\";for(var o in t)if(t.hasOwnProperty(o)){var i=t[o],a=\"disabled\"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o),s=\"disabled\"!==this.opt.wildcards?this.setupWildcardsRegExp(i):this.escapeStr(i);\"\"!==a&&\"\"!==s&&(e=e.replace(new RegExp(\"(\"+this.escapeStr(a)+\"|\"+this.escapeStr(s)+\")\",\"gm\"+n),r+\"(\"+this.processSynomyms(a)+\"|\"+this.processSynomyms(s)+\")\"+r))}return e}},{key:\"processSynomyms\",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:\"setupWildcardsRegExp\",value:function(e){return(e=e.replace(/(?:\\\\)*\\?/g,function(e){return\"\\\\\"===e.charAt(0)?\"?\":\"\u0001\"})).replace(/(?:\\\\)*\\*/g,function(e){return\"\\\\\"===e.charAt(0)?\"*\":\"\u0002\"})}},{key:\"createWildcardsRegExp\",value:function(e){var t=\"withSpaces\"===this.opt.wildcards;return e.replace(/\\u0001/g,t?\"[\\\\S\\\\s]?\":\"\\\\S?\").replace(/\\u0002/g,t?\"[\\\\S\\\\s]*?\":\"\\\\S*\")}},{key:\"setupIgnoreJoinersRegExp\",value:function(e){return e.replace(/[^(|)\\\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\\\]/.test(r)||\"\"===r?e:e+\"\\0\"})}},{key:\"createJoinersRegExp\",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(\"\"))),this.opt.ignoreJoiners&&t.push(\"\\\\u00ad\\\\u200b\\\\u200c\\\\u200d\"),t.length?e.split(/\\u0000+/).join(\"[\"+t.join(\"\")+\"]*\"):e}},{key:\"createDiacriticsRegExp\",value:function(e){var t=this.opt.caseSensitive?\"\":\"i\",n=this.opt.caseSensitive?[\"aàáảãạăằắẳẵặâầấẩẫậäåāą\",\"AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ\",\"cçćč\",\"CÇĆČ\",\"dđď\",\"DĐĎ\",\"eèéẻẽẹêềếểễệëěēę\",\"EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ\",\"iìíỉĩịîïī\",\"IÌÍỈĨỊÎÏĪ\",\"lł\",\"LŁ\",\"nñňń\",\"NÑŇŃ\",\"oòóỏõọôồốổỗộơởỡớờợöøō\",\"OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ\",\"rř\",\"RŘ\",\"sšśșş\",\"SŠŚȘŞ\",\"tťțţ\",\"TŤȚŢ\",\"uùúủũụưừứửữựûüůū\",\"UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ\",\"yýỳỷỹỵÿ\",\"YÝỲỶỸỴŸ\",\"zžżź\",\"ZŽŻŹ\"]:[\"aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ\",\"cçćčCÇĆČ\",\"dđďDĐĎ\",\"eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ\",\"iìíỉĩịîïīIÌÍỈĨỊÎÏĪ\",\"lłLŁ\",\"nñňńNÑŇŃ\",\"oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ\",\"rřRŘ\",\"sšśșşSŠŚȘŞ\",\"tťțţTŤȚŢ\",\"uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ\",\"yýỳỷỹỵÿYÝỲỶỸỴŸ\",\"zžżźZŽŻŹ\"],r=[];return e.split(\"\").forEach(function(o){n.every(function(n){if(-1!==n.indexOf(o)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp(\"[\"+n+\"]\",\"gm\"+t),\"[\"+n+\"]\"),r.push(n)}return!0})}),e}},{key:\"createMergedBlanksRegExp\",value:function(e){return e.replace(/[\\s]+/gim,\"[\\\\s]+\")}},{key:\"createAccuracyRegExp\",value:function(e){var t=this,n=this.opt.accuracy,r=\"string\"==typeof n?n:n.value,o=\"string\"==typeof n?[]:n.limiters,i=\"\";switch(o.forEach(function(e){i+=\"|\"+t.escapeStr(e)}),r){case\"partially\":default:return\"()(\"+e+\")\";case\"complementary\":return\"()([^\"+(i=\"\\\\s\"+(i||this.escapeStr(\"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~¡¿\")))+\"]*\"+e+\"[^\"+i+\"]*)\";case\"exactly\":return\"(^|\\\\s\"+i+\")(\"+e+\")(?=$|\\\\s\"+i+\")\"}}},{key:\"getSeparatedKeywords\",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(\" \").forEach(function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)}):e.trim()&&-1===n.indexOf(e)&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:\"isNumeric\",value:function(e){return Number(parseFloat(e))==e}},{key:\"checkRanges\",value:function(e){var t=this;if(!Array.isArray(e)||\"[object Object]\"!==Object.prototype.toString.call(e[0]))return this.log(\"markRanges() will only accept an array of objects\"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort(function(e,t){return e.start-t.start}).forEach(function(e){var o=t.callNoMatchOnInvalidRanges(e,r),i=o.start,a=o.end,s=o.valid;s&&(e.start=i,e.length=a-i,n.push(e),r=a)}),n}},{key:\"callNoMatchOnInvalidRanges\",value:function(e,t){var n=void 0,r=void 0,o=!1;return e&&void 0!==e.start?(n=parseInt(e.start,10),r=n+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?o=!0:(this.log(\"Ignoring invalid or overlapping range: \"+JSON.stringify(e)),this.opt.noMatch(e))):(this.log(\"Ignoring invalid range: \"+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:o}}},{key:\"checkWhitespaceRanges\",value:function(e,t,n){var r=void 0,o=!0,i=n.length,a=t-i,s=parseInt(e.start,10)-a;return(r=(s=s>i?i:s)+parseInt(e.length,10))>i&&(r=i,this.log(\"End range automatically set to the max value of \"+i)),s<0||r-s<0||s>i||r>i?(o=!1,this.log(\"Invalid range: \"+JSON.stringify(e)),this.opt.noMatch(e)):\"\"===n.substring(s,r).replace(/\\s+/g,\"\")&&(o=!1,this.log(\"Skipping whitespace only range: \"+JSON.stringify(e)),this.opt.noMatch(e)),{start:s,end:r,valid:o}}},{key:\"getTextNodes\",value:function(e){var t=this,n=\"\",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:\"matchesExclude\",value:function(e){return o.matches(e,this.opt.exclude.concat([\"script\",\"style\",\"title\",\"head\",\"html\"]))}},{key:\"wrapRangeInTextNode\",value:function(e,t,n){var r=this.opt.element?this.opt.element:\"mark\",o=e.splitText(t),i=o.splitText(n-t),a=document.createElement(r);return a.setAttribute(\"data-markjs\",\"true\"),this.opt.className&&a.setAttribute(\"class\",this.opt.className),a.textContent=o.textContent,o.parentNode.replaceChild(a,o),i}},{key:\"wrapRangeInMappedTextNode\",value:function(e,t,n,r,o){var i=this;e.nodes.every(function(a,s){var l=e.nodes[s+1];if(void 0===l||l.start>t){if(!r(a.node))return!1;var c=t-a.start,u=(n>a.end?a.end:n)-a.start,p=e.value.substr(0,a.start),f=e.value.substr(u+a.start);if(a.node=i.wrapRangeInTextNode(a.node,c,u),e.value=p+f,e.nodes.forEach(function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=u),e.nodes[n].end-=u)}),n-=u,o(a.node.previousSibling,a.start),!(n>a.end))return!1;t=a.end}return!0})}},{key:\"wrapMatches\",value:function(e,t,n,r,o){var i=this,a=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var o=void 0;null!==(o=e.exec(t.textContent))&&\"\"!==o[a];)if(n(o[a],t)){var s=o.index;if(0!==a)for(var l=1;l<a;l++)s+=o[l].length;t=i.wrapRangeInTextNode(t,s,s+o[a].length),r(t.previousSibling),e.lastIndex=0}}),o()})}},{key:\"wrapMatchesAcrossElements\",value:function(e,t,n,r,o){var i=this,a=0===t?0:t+1;this.getTextNodes(function(t){for(var s=void 0;null!==(s=e.exec(t.value))&&\"\"!==s[a];){var l=s.index;if(0!==a)for(var c=1;c<a;c++)l+=s[c].length;var u=l+s[a].length;i.wrapRangeInMappedTextNode(t,l,u,function(e){return n(s[a],e)},function(t,n){e.lastIndex=n,r(t)})}o()})}},{key:\"wrapRangeFromIndex\",value:function(e,t,n,r){var o=this;this.getTextNodes(function(i){var a=i.value.length;e.forEach(function(e,r){var s=o.checkWhitespaceRanges(e,a,i.value),l=s.start,c=s.end,u=s.valid;u&&o.wrapRangeInMappedTextNode(i,l,c,function(n){return t(n,e,i.value.substring(l,c),r)},function(t){n(t,e)})}),r()})}},{key:\"unwrapMatches\",value:function(e){for(var t=e.parentNode,n=document.createDocumentFragment();e.firstChild;)n.appendChild(e.removeChild(e.firstChild));t.replaceChild(n,e),this.ie?this.normalizeTextNode(t):t.normalize()}},{key:\"normalizeTextNode\",value:function(e){if(e){if(3===e.nodeType)for(;e.nextSibling&&3===e.nextSibling.nodeType;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}},{key:\"markRegExp\",value:function(e,t){var n=this;this.opt=t,this.log('Searching with expression \"'+e+'\"');var r=0,o=\"wrapMatches\";this.opt.acrossElements&&(o=\"wrapMatchesAcrossElements\"),this[o](e,this.opt.ignoreGroups,function(e,t){return n.opt.filter(t,e,r)},function(e){r++,n.opt.each(e)},function(){0===r&&n.opt.noMatch(e),n.opt.done(r)})}},{key:\"mark\",value:function(e,t){var n=this;this.opt=t;var r=0,o=\"wrapMatches\",i=this.getSeparatedKeywords(\"string\"==typeof e?[e]:e),a=i.keywords,s=i.length,l=this.opt.caseSensitive?\"\":\"i\";this.opt.acrossElements&&(o=\"wrapMatchesAcrossElements\"),0===s?this.opt.done(r):function e(t){var i=new RegExp(n.createRegExp(t),\"gm\"+l),c=0;n.log('Searching with expression \"'+i+'\"'),n[o](i,1,function(e,o){return n.opt.filter(o,t,r,c)},function(e){c++,r++,n.opt.each(e)},function(){0===c&&n.opt.noMatch(t),a[s-1]===t?n.opt.done(r):e(a[a.indexOf(t)+1])})}(a[0])}},{key:\"markRanges\",value:function(e,t){var n=this;this.opt=t;var r=0,o=this.checkRanges(e);o&&o.length?(this.log(\"Starting to mark with the following ranges: \"+JSON.stringify(o)),this.wrapRangeFromIndex(o,function(e,t,r,o){return n.opt.filter(e,t,r,o)},function(e,t){r++,n.opt.each(e,t)},function(){n.opt.done(r)})):this.opt.done(r)}},{key:\"unmark\",value:function(e){var t=this;this.opt=e;var n=this.opt.element?this.opt.element:\"*\";n+=\"[data-markjs]\",this.opt.className&&(n+=\".\"+this.opt.className),this.log('Removal selector \"'+n+'\"'),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,function(e){t.unwrapMatches(e)},function(e){var r=o.matches(e,n),i=t.matchesExclude(e);return!r||i?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}},{key:\"opt\",set:function(e){this._opt=r({},{element:\"\",className:\"\",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:\"partially\",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:\"disabled\",each:function(){},noMatch:function(){},filter:function(){return!0},done:function(){},debug:!1,log:window.console},e)},get:function(){return this._opt}},{key:\"iterator\",get:function(){return new o(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}}]),i}();return function(e){var t=this,n=new i(e);return this.mark=function(e,r){return n.mark(e,r),t},this.markRegExp=function(e,r){return n.markRegExp(e,r),t},this.markRanges=function(e,r){return n.markRanges(e,r),t},this.unmark=function(e){return n.unmark(e),t},this}}()},function(e,t,n){var r;e.exports=function e(t,n,o){function i(s,l){if(!n[s]){if(!t[s]){var c=\"function\"==typeof r&&r;if(!l&&c)return r(s,!0);if(a)return a(s,!0);var u=new Error(\"Cannot find module '\"+s+\"'\");throw u.code=\"MODULE_NOT_FOUND\",u}var p=n[s]={exports:{}};t[s][0].call(p.exports,function(e){var n=t[s][1][e];return i(n||e)},p,p.exports,e,t,n,o)}return n[s].exports}for(var a=\"function\"==typeof r&&r,s=0;s<o.length;s++)i(o[s]);return i}({1:[function(e,t,n){var r=Object.prototype.hasOwnProperty,o=Object.prototype.toString;t.exports=function(e,t,n){if(\"[object Function]\"!==o.call(t))throw new TypeError(\"iterator must be a function\");var i=e.length;if(i===+i)for(var a=0;a<i;a++)t.call(n,e[a],a,e);else for(var s in e)r.call(e,s)&&t.call(n,e[s],s,e)}},{}],2:[function(e,t,n){\"use strict\";var r=e(\"foreach\");function o(e,t,n){if(3===arguments.length)return o.set(e,t,n);if(2===arguments.length)return o.get(e,t);var r=o.bind(o,e);for(var i in o)o.hasOwnProperty(i)&&(r[i]=o[i].bind(r,e));return r}t.exports=o,o.get=function(e,t){for(var n=Array.isArray(t)?t:o.parse(t),r=0;r<n.length;++r){var i=n[r];if(!(\"object\"==typeof e&&i in e))throw new Error(\"Invalid reference token: \"+i);e=e[i]}return e},o.set=function(e,t,n){for(var r=Array.isArray(t)?t:o.parse(t),i=r[0],a=0;a<r.length-1;++a){var s=r[a];\"-\"===s&&Array.isArray(e)&&(s=e.length),i=r[a+1],s in e||(i.match(/^(\\d+|-)$/)?e[s]=[]:e[s]={}),e=e[s]}return\"-\"===i&&Array.isArray(e)&&(i=e.length),e[i]=n,this},o.remove=function(e,t){var n=Array.isArray(t)?t:o.parse(t),r=n[n.length-1];if(void 0===r)throw new Error('Invalid JSON pointer for remove: \"'+t+'\"');var i=o.get(e,n.slice(0,-1));if(Array.isArray(i)){var a=+r;if(\"\"===r&&isNaN(a))throw new Error('Invalid array index: \"'+r+'\"');Array.prototype.splice.call(i,a,1)}else delete i[r]},o.dict=function(e,t){var n={};return o.walk(e,function(e,t){n[t]=e},t),n},o.walk=function(e,t,n){var i=[];n=n||function(e){var t=Object.prototype.toString.call(e);return\"[object Object]\"===t||\"[object Array]\"===t},function e(a){r(a,function(r,a){i.push(String(a)),n(r)?e(r):t(r,o.compile(i)),i.pop()})}(e)},o.has=function(e,t){try{o.get(e,t)}catch(e){return!1}return!0},o.escape=function(e){return e.toString().replace(/~/g,\"~0\").replace(/\\//g,\"~1\")},o.unescape=function(e){return e.replace(/~1/g,\"/\").replace(/~0/g,\"~\")},o.parse=function(e){if(\"\"===e)return[];if(\"/\"!==e.charAt(0))throw new Error(\"Invalid JSON pointer: \"+e);return e.substring(1).split(/\\//).map(o.unescape)},o.compile=function(e){return 0===e.length?\"\":\"/\"+e.map(o.escape).join(\"/\")}},{foreach:1}],3:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e};n.allOfSample=function(e,t,n,a){var s=(0,o.traverse)(e,n,a),l=[],c=!0,u=!1,p=void 0;try{for(var f,d=t[Symbol.iterator]();!(c=(f=d.next()).done);c=!0){var h=f.value,m=(0,o.traverse)(r({type:g},h),n,a),g=m.type,y=m.readOnly,v=m.writeOnly,b=m.value;if(s.type&&g&&g!==s.type)throw new Error(\"allOf: schemas with different types can't be merged\");s.type=s.type||g,s.readOnly=s.readOnly||y,s.writeOnly=s.writeOnly||v,null!=b&&l.push(b)}}catch(e){u=!0,p=e}finally{try{!c&&d.return&&d.return()}finally{if(u)throw p}}if(\"object\"===s.type)return s.value=i.mergeDeep.apply(void 0,[s.value||{}].concat(l)),s;\"array\"===s.type&&console.warn('OpenAPI Sampler: found allOf with \"array\" type. Result may be incorrect');var w=l[l.length-1];return s.value=null!=w?w:s.value,s};var o=e(\"./traverse\"),i=e(\"./utils\")},{\"./traverse\":12,\"./utils\":13}],4:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.inferType=function(e){if(void 0!==e.type)return e.type;for(var t=Object.keys(r),n=0;n<t.length;n++){var o=t[n],i=r[o];if(void 0!==e[o])return i}return null};var r={multipleOf:\"number\",maximum:\"number\",exclusiveMaximum:\"number\",minimum:\"number\",exclusiveMinimum:\"number\",maxLength:\"string\",minLength:\"string\",pattern:\"string\",items:\"array\",maxItems:\"array\",minItems:\"array\",uniqueItems:\"array\",additionalItems:\"array\",maxProperties:\"object\",minProperties:\"object\",required:\"object\",additionalProperties:\"object\",properties:\"object\",patternProperties:\"object\",dependencies:\"object\"}},{}],5:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.inferType=n._samplers=void 0,n.sample=function(e,t,n){var r=Object.assign({},s,t);return(0,o.clearCache)(),(0,o.traverse)(e,r,n).value},n._registerSampler=l;var r=e(\"./infer\");Object.defineProperty(n,\"inferType\",{enumerable:!0,get:function(){return r.inferType}});var o=e(\"./traverse\"),i=e(\"./samplers/index\"),a=n._samplers={},s={skipReadOnly:!1};function l(e,t){a[e]=t}l(\"array\",i.sampleArray),l(\"boolean\",i.sampleBoolean),l(\"integer\",i.sampleNumber),l(\"number\",i.sampleNumber),l(\"object\",i.sampleObject),l(\"string\",i.sampleString)},{\"./infer\":4,\"./samplers/index\":8,\"./traverse\":12}],6:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.sampleArray=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],o=e.minItems||1;Array.isArray(e.items)&&(o=Math.max(o,e.items.length));var i=function(t){return Array.isArray(e.items)?e.items[t]||{}:e.items||{}},a=[];if(!e.items)return a;for(var s=0;s<o;s++){var l=i(s),c=(0,r.traverse)(l,t,n),u=c.value;a.push(u)}return a};var r=e(\"../traverse\")},{\"../traverse\":12}],7:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.sampleBoolean=function(e){return!0}},{}],8:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(\"./array\");Object.defineProperty(n,\"sampleArray\",{enumerable:!0,get:function(){return r.sampleArray}});var o=e(\"./boolean\");Object.defineProperty(n,\"sampleBoolean\",{enumerable:!0,get:function(){return o.sampleBoolean}});var i=e(\"./number\");Object.defineProperty(n,\"sampleNumber\",{enumerable:!0,get:function(){return i.sampleNumber}});var a=e(\"./object\");Object.defineProperty(n,\"sampleObject\",{enumerable:!0,get:function(){return a.sampleObject}});var s=e(\"./string\");Object.defineProperty(n,\"sampleString\",{enumerable:!0,get:function(){return s.sampleString}})},{\"./array\":6,\"./boolean\":7,\"./number\":9,\"./object\":10,\"./string\":11}],9:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.sampleNumber=function(e){var t=void 0;return e.maximum&&e.minimum?(t=e.exclusiveMinimum?Math.floor(e.minimum)+1:e.minimum,(e.exclusiveMaximum&&t>=e.maximum||!e.exclusiveMaximum&&t>e.maximum)&&(t=(e.maximum+e.minimum)/2),t):e.minimum?e.exclusiveMinimum?Math.floor(e.minimum)+1:e.minimum:e.maximum?e.exclusiveMaximum?e.maximum>0?0:Math.floor(e.maximum)-1:e.maximum>0?0:e.maximum:0}},{}],10:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};n.sampleObject=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],i={};if(e&&\"object\"===r(e.properties)){var a=Array.isArray(e.required)?e.required:[],s=a.reduce(function(e,t){return e[t]=!0,e},{});Object.keys(e.properties).forEach(function(r){if(!t.skipNonRequired||s.hasOwnProperty(r)){var a=(0,o.traverse)(e.properties[r],t,n);t.skipReadOnly&&a.readOnly||t.skipWriteOnly&&a.writeOnly||(i[r]=a.value)}})}return e&&\"object\"===r(e.additionalProperties)&&(i.property1=(0,o.traverse)(e.additionalProperties,t,n).value,i.property2=(0,o.traverse)(e.additionalProperties,t,n).value),i};var o=e(\"../traverse\")},{\"../traverse\":12}],11:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.sampleString=function(e){var t=e.format||\"default\";return(s[t]||a)(0|e.minLength,e.maxLength)};var r=e(\"../utils\"),o=\"qwerty!@#$%^123456\";function i(e,t,n){var o=(0,r.toRFCDateTime)(new Date,n,!1);if(o.length<e)throw new Error(\"Using minLength = \"+e+' is incorrect with format \"date-time\"');if(t&&o.length>t)throw new Error(\"Using maxLength = \"+t+' is incorrect with format \"date-time\"');return o}function a(e,t){var n=(0,r.ensureMinLength)(\"string\",e);return t&&n.length>t&&(n=n.substring(0,t)),n}var s={email:function(){return\"user@example.com\"},password:function(e,t){var n=\"pa$$word\";return e>n.length&&(n+=\"_\",n+=(0,r.ensureMinLength)(o,e-n.length).substring(0,e-n.length)),n},\"date-time\":function(e,t){return i(e,t)},date:function(e,t){return i(e,t,!0)},ipv4:function(){return\"192.168.0.1\"},ipv6:function(){return\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\"},hostname:function(){return\"example.com\"},uri:function(){return\"http://example.com\"},default:a}},{\"../utils\":13}],12:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e};n.clearCache=function(){u={}},n.traverse=function e(t,n,o){if(t.$ref){if(!o)throw new Error(\"Your schema contains $ref. You must provide specification in the third parameter.\");var l=decodeURIComponent(t.$ref);l.startsWith(\"#\")&&(l=l.substring(1));var p=c.default.get(o,l),f=void 0;if(!0!==u[l])u[l]=!0,f=e(p,n,o),u[l]=!1;else{var d=(0,s.inferType)(p);f={value:\"object\"===d?{}:\"array\"===d?[]:void 0}}return f}if(void 0!==t.example)return{value:t.example,readOnly:t.readOnly,writeOnly:t.writeOnly,type:t.type};if(void 0!==t.allOf)return(0,a.allOfSample)(r({},t,{allOf:void 0}),t.allOf,n,o);if(t.oneOf&&t.oneOf.length)return t.anyOf&&console.warn(\"oneOf and anyOf are not supported on the same level. Skipping anyOf\"),e(t.oneOf[0],n,o);if(t.anyOf&&t.anyOf.length)return e(t.anyOf[0],n,o);var h=null,m=null;if(void 0!==t.default)h=t.default;else if(void 0!==t.enum&&t.enum.length)h=t.enum[0];else{(m=t.type)||(m=(0,s.inferType)(t));var g=i._samplers[m];g&&(h=g(t,n,o))}return{value:h,readOnly:t.readOnly,writeOnly:t.writeOnly,type:m}};var o,i=e(\"./openapi-sampler\"),a=e(\"./allOf\"),s=e(\"./infer\"),l=e(\"json-pointer\"),c=(o=l)&&o.__esModule?o:{default:o},u={}},{\"./allOf\":3,\"./infer\":4,\"./openapi-sampler\":5,\"json-pointer\":2}],13:[function(e,t,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0});var r=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};function o(e){return e<10?\"0\"+e:e}n.toRFCDateTime=function(e,t,n){var r=e.getUTCFullYear()+\"-\"+o(e.getUTCMonth()+1)+\"-\"+o(e.getUTCDate());return t||(r+=\"T\"+o(e.getUTCHours())+\":\"+o(e.getUTCMinutes())+\":\"+o(e.getUTCSeconds())+(n?\".\"+(e.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5):\"\")+\"Z\"),r},n.ensureMinLength=function(e,t){return t>e.length?e.repeat(Math.trunc(t/e.length)+1).substring(0,t):e},n.mergeDeep=function e(){for(var t=function(e){return e&&\"object\"===(void 0===e?\"undefined\":r(e))},n=arguments.length,o=Array(n),i=0;i<n;i++)o[i]=arguments[i];return o.reduce(function(n,r){return Object.keys(r).forEach(function(o){var i=n[o],a=r[o];t(i)&&t(a)?n[o]=e(i,a):n[o]=a}),n},Array.isArray(o[o.length-1])?[]:{})}},{}]},{},[5])(5)},function(e,t,n){(e.exports=n(268)(!1)).push([e.i,\"/*\\n * Container style\\n */\\n.ps {\\n  overflow: hidden !important;\\n  overflow-anchor: none;\\n  -ms-overflow-style: none;\\n  touch-action: auto;\\n  -ms-touch-action: auto;\\n}\\n\\n/*\\n * Scrollbar rail styles\\n */\\n.ps__rail-x {\\n  display: none;\\n  opacity: 0;\\n  transition: background-color .2s linear, opacity .2s linear;\\n  -webkit-transition: background-color .2s linear, opacity .2s linear;\\n  height: 15px;\\n  /* there must be 'bottom' or 'top' for ps__rail-x */\\n  bottom: 0px;\\n  /* please don't change 'position' */\\n  position: absolute;\\n}\\n\\n.ps__rail-y {\\n  display: none;\\n  opacity: 0;\\n  transition: background-color .2s linear, opacity .2s linear;\\n  -webkit-transition: background-color .2s linear, opacity .2s linear;\\n  width: 15px;\\n  /* there must be 'right' or 'left' for ps__rail-y */\\n  right: 0;\\n  /* please don't change 'position' */\\n  position: absolute;\\n}\\n\\n.ps--active-x > .ps__rail-x,\\n.ps--active-y > .ps__rail-y {\\n  display: block;\\n  background-color: transparent;\\n}\\n\\n.ps:hover > .ps__rail-x,\\n.ps:hover > .ps__rail-y,\\n.ps--focus > .ps__rail-x,\\n.ps--focus > .ps__rail-y,\\n.ps--scrolling-x > .ps__rail-x,\\n.ps--scrolling-y > .ps__rail-y {\\n  opacity: 0.6;\\n}\\n\\n.ps .ps__rail-x:hover,\\n.ps .ps__rail-y:hover,\\n.ps .ps__rail-x:focus,\\n.ps .ps__rail-y:focus,\\n.ps .ps__rail-x.ps--clicking,\\n.ps .ps__rail-y.ps--clicking {\\n  background-color: #eee;\\n  opacity: 0.9;\\n}\\n\\n/*\\n * Scrollbar thumb styles\\n */\\n.ps__thumb-x {\\n  background-color: #aaa;\\n  border-radius: 6px;\\n  transition: background-color .2s linear, height .2s ease-in-out;\\n  -webkit-transition: background-color .2s linear, height .2s ease-in-out;\\n  height: 6px;\\n  /* there must be 'bottom' for ps__thumb-x */\\n  bottom: 2px;\\n  /* please don't change 'position' */\\n  position: absolute;\\n}\\n\\n.ps__thumb-y {\\n  background-color: #aaa;\\n  border-radius: 6px;\\n  transition: background-color .2s linear, width .2s ease-in-out;\\n  -webkit-transition: background-color .2s linear, width .2s ease-in-out;\\n  width: 6px;\\n  /* there must be 'right' for ps__thumb-y */\\n  right: 2px;\\n  /* please don't change 'position' */\\n  position: absolute;\\n}\\n\\n.ps__rail-x:hover > .ps__thumb-x,\\n.ps__rail-x:focus > .ps__thumb-x,\\n.ps__rail-x.ps--clicking .ps__thumb-x {\\n  background-color: #999;\\n  height: 11px;\\n}\\n\\n.ps__rail-y:hover > .ps__thumb-y,\\n.ps__rail-y:focus > .ps__thumb-y,\\n.ps__rail-y.ps--clicking .ps__thumb-y {\\n  background-color: #999;\\n  width: 11px;\\n}\\n\\n/* MS supports */\\n@supports (-ms-overflow-style: none) {\\n  .ps {\\n    overflow: auto !important;\\n  }\\n}\\n\\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\\n  .ps {\\n    overflow: auto !important;\\n  }\\n}\\n\",\"\"])},function(e,t,n){e.exports=!n(17)&&!n(27)(function(){return 7!=Object.defineProperty(n(59)(\"div\"),\"a\",{get:function(){return 7}}).a})},function(e,t,n){\"use strict\";var r=n(137)(!0);n(62)(String,\"String\",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var r=n(23),o=n(28),i=n(140)(!1),a=n(65)(\"IE_PROTO\");e.exports=function(e,t){var n,s=o(e),l=0,c=[];for(n in s)n!=a&&r(s,n)&&c.push(n);for(;t.length>l;)r(s,n=t[l++])&&(~i(c,n)||c.push(n));return c}},function(e,t,n){var r=n(5).document;e.exports=r&&r.documentElement},function(e,t,n){for(var r=n(143),o=n(34),i=n(21),a=n(5),s=n(22),l=n(33),c=n(2),u=c(\"iterator\"),p=c(\"toStringTag\"),f=l.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=o(d),m=0;m<h.length;m++){var g,y=h[m],v=d[y],b=a[y],w=b&&b.prototype;if(w&&(w[u]||s(w,u,f),w[p]||s(w,p,y),l[y]=f,v))for(g in r)w[g]||i(w,g,r[g],!0)}},function(e,t,n){var r=n(2)(\"unscopables\"),o=Array.prototype;null==o[r]&&n(22)(o,r,{}),e.exports=function(e){o[r][e]=!0}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){var r,o,i,a=n(24),s=n(149),l=n(85),c=n(59),u=n(5),p=u.process,f=u.setImmediate,d=u.clearImmediate,h=u.MessageChannel,m=u.Dispatch,g=0,y={},v=function(){var e=+this;if(y.hasOwnProperty(e)){var t=y[e];delete y[e],t()}},b=function(e){v.call(e.data)};f&&d||(f=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return y[++g]=function(){s(\"function\"==typeof e?e:Function(e),t)},r(g),g},d=function(e){delete y[e]},\"process\"==n(26)(p)?r=function(e){p.nextTick(a(v,e,1))}:m&&m.now?r=function(e){m.now(a(v,e,1))}:h?(i=(o=new h).port2,o.port1.onmessage=b,r=a(i.postMessage,i,1)):u.addEventListener&&\"function\"==typeof postMessage&&!u.importScripts?(r=function(e){u.postMessage(e+\"\",\"*\")},u.addEventListener(\"message\",b,!1)):r=\"onreadystatechange\"in c(\"script\")?function(e){l.appendChild(c(\"script\")).onreadystatechange=function(){l.removeChild(this),v.call(e)}}:function(e){setTimeout(a(v,e,1),0)}),e.exports={set:f,clear:d}},function(e,t,n){\"use strict\";var r=n(44);function o(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError(\"Bad Promise constructor\");t=e,n=r}),this.resolve=r(t),this.reject=r(n)}e.exports.f=function(e){return new o(e)}},function(e,t,n){\"use strict\";var r=n(5),o=n(16),i=n(17),a=n(2)(\"species\");e.exports=function(e){var t=r[e];i&&t&&!t[a]&&o.f(t,a,{configurable:!0,get:function(){return this}})}},function(e,t,n){var r=n(2)(\"iterator\"),o=!1;try{var i=[7][r]();i.return=function(){o=!0},Array.from(i,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var i=[7],a=i[r]();a.next=function(){return{done:n=!0}},i[r]=function(){return a},e(i)}catch(e){}return n}},function(e,t,n){var r=n(26);e.exports=Array.isArray||function(e){return\"Array\"==r(e)}},function(e,t,n){var r=n(164),o=n(43);e.exports=function(e,t,n){if(r(t))throw TypeError(\"String#\"+n+\" doesn't accept regex!\");return String(o(e))}},function(e,t,n){var r=n(2)(\"match\");e.exports=function(e){var t=/./;try{\"/./\"[e](t)}catch(n){try{return t[r]=!1,!\"/./\"[e](t)}catch(e){}}return!0}},function(e,t,n){var r=n(8);e.exports=function(e,t){if(!r(e)||e._t!==t)throw TypeError(\"Incompatible receiver, \"+t+\" required!\");return e}},function(e,t,n){var r=n(45),o=n(42),i=n(28),a=n(60),s=n(23),l=n(82),c=Object.getOwnPropertyDescriptor;t.f=n(17)?c:function(e,t){if(e=i(e),t=a(t,!0),l)try{return c(e,t)}catch(e){}if(s(e,t))return o(!r.f.call(e,t),e[t])}},function(e,t,n){t.f=n(2)},function(e,t,n){var r=n(84),o=n(66).concat(\"length\",\"prototype\");t.f=Object.getOwnPropertyNames||function(e){return r(e,o)}},function(e,t,n){\"use strict\";\n/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String(\"abc\");if(e[5]=\"de\",\"5\"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t[\"_\"+String.fromCharCode(n)]=n;if(\"0123456789\"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(\"\"))return!1;var r={};return\"abcdefghijklmnopqrst\".split(\"\").forEach(function(e){r[e]=e}),\"abcdefghijklmnopqrst\"===Object.keys(Object.assign({},r)).join(\"\")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,a,s=function(e){if(null==e)throw new TypeError(\"Object.assign cannot be called with null or undefined\");return Object(e)}(e),l=1;l<arguments.length;l++){for(var c in n=Object(arguments[l]))o.call(n,c)&&(s[c]=n[c]);if(r){a=r(n);for(var u=0;u<a.length;u++)i.call(n,a[u])&&(s[a[u]]=n[a[u]])}}return s}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return\"[object Array]\"==n.call(e)}},function(e,t,n){\"use strict\";var r=n(193),o=n(194),i=n(217),a=n(218),s=n(219),l=n(221);function c(e){u(this,c.defaults),u(this,e)}function u(e,t){if(p(t))for(var n=Object.keys(t),r=0;r<n.length;r++){var o=n[r],i=t[o],a=e[o];p(i)?e[o]=u(a||{},i):void 0!==i&&(e[o]=i)}return e}function p(e){return e&&\"object\"==typeof e&&!Array.isArray(e)&&!(e instanceof RegExp)&&!(e instanceof Date)}e.exports=c,c.defaults={parse:{json:r,yaml:o,text:i,binary:a},resolve:{file:s,http:l,external:!0},dereference:{circular:!0}}},function(e,t,n){\"use strict\";var r=n(46),o=n(25);e.exports={parse:function(e,t){try{return r.safeLoad(e)}catch(e){throw e instanceof Error?e:o(e,e.message)}},stringify:function(e,t,n){try{var i=(\"string\"==typeof n?n.length:n)||2;return r.safeDump(e,{indent:i})}catch(e){throw e instanceof Error?e:o(e,e.message)}}}},function(e,t,n){\"use strict\";var r=n(29);e.exports=new r({include:[n(105)]})},function(e,t,n){\"use strict\";var r=n(29);e.exports=new r({include:[n(73)],implicit:[n(201),n(202),n(203),n(204)]})},function(e,t,n){(function(e){var r=n(222),o=n(108),i=n(231),a=n(232),s=n(10),l=t;l.request=function(t,n){t=\"string\"==typeof t?s.parse(t):i(t);var o=-1===e.location.protocol.search(/^https?:$/)?\"http:\":\"\",a=t.protocol||o,l=t.hostname||t.host,c=t.port,u=t.path||\"/\";l&&-1!==l.indexOf(\":\")&&(l=\"[\"+l+\"]\"),t.url=(l?a+\"//\"+l:\"\")+(c?\":\"+c:\"\")+u,t.method=(t.method||\"GET\").toUpperCase(),t.headers=t.headers||{};var p=new r(t);return n&&p.on(\"response\",n),p},l.get=function(e,t){var n=l.request(e,t);return n.end(),n},l.ClientRequest=r,l.IncomingMessage=o.IncomingMessage,l.Agent=function(){},l.Agent.defaultMaxSockets=4,l.globalAgent=new l.Agent,l.STATUS_CODES=a,l.METHODS=[\"CHECKOUT\",\"CONNECT\",\"COPY\",\"DELETE\",\"GET\",\"HEAD\",\"LOCK\",\"M-SEARCH\",\"MERGE\",\"MKACTIVITY\",\"MKCOL\",\"MOVE\",\"NOTIFY\",\"OPTIONS\",\"PATCH\",\"POST\",\"PROPFIND\",\"PROPPATCH\",\"PURGE\",\"PUT\",\"REPORT\",\"SEARCH\",\"SUBSCRIBE\",\"TRACE\",\"UNLOCK\",\"UNSUBSCRIBE\"]}).call(this,n(4))},function(e,t,n){(function(e){t.fetch=s(e.fetch)&&s(e.ReadableStream),t.writableStream=s(e.WritableStream),t.abortController=s(e.AbortController),t.blobConstructor=!1;try{new Blob([new ArrayBuffer(1)]),t.blobConstructor=!0}catch(e){}var n;function r(){if(void 0!==n)return n;if(e.XMLHttpRequest){n=new e.XMLHttpRequest;try{n.open(\"GET\",e.XDomainRequest?\"/\":\"https://example.com\")}catch(e){n=null}}else n=null;return n}function o(e){var t=r();if(!t)return!1;try{return t.responseType=e,t.responseType===e}catch(e){}return!1}var i=void 0!==e.ArrayBuffer,a=i&&s(e.ArrayBuffer.prototype.slice);function s(e){return\"function\"==typeof e}t.arraybuffer=t.fetch||i&&o(\"arraybuffer\"),t.msstream=!t.fetch&&a&&o(\"ms-stream\"),t.mozchunkedarraybuffer=!t.fetch&&i&&o(\"moz-chunked-arraybuffer\"),t.overrideMimeType=t.fetch||!!r()&&s(r().overrideMimeType),t.vbArray=s(e.VBArray),n=null}).call(this,n(4))},function(e,t,n){(function(e,r,o){var i=n(107),a=n(20),s=n(109),l=t.readyStates={UNSENT:0,OPENED:1,HEADERS_RECEIVED:2,LOADING:3,DONE:4},c=t.IncomingMessage=function(t,n,a,l){var c=this;if(s.Readable.call(c),c._mode=a,c.headers={},c.rawHeaders=[],c.trailers={},c.rawTrailers=[],c.on(\"end\",function(){e.nextTick(function(){c.emit(\"close\")})}),\"fetch\"===a){if(c._fetchResponse=n,c.url=n.url,c.statusCode=n.status,c.statusMessage=n.statusText,n.headers.forEach(function(e,t){c.headers[t.toLowerCase()]=e,c.rawHeaders.push(t,e)}),i.writableStream){var u=new WritableStream({write:function(e){return new Promise(function(t,n){c._destroyed?n():c.push(new r(e))?t():c._resumeFetch=t})},close:function(){o.clearTimeout(l),c._destroyed||c.push(null)},abort:function(e){c._destroyed||c.emit(\"error\",e)}});try{return void n.body.pipeTo(u).catch(function(e){o.clearTimeout(l),c._destroyed||c.emit(\"error\",e)})}catch(e){}}var p=n.body.getReader();!function e(){p.read().then(function(t){if(!c._destroyed){if(t.done)return o.clearTimeout(l),void c.push(null);c.push(new r(t.value)),e()}}).catch(function(e){o.clearTimeout(l),c._destroyed||c.emit(\"error\",e)})}()}else{if(c._xhr=t,c._pos=0,c.url=t.responseURL,c.statusCode=t.status,c.statusMessage=t.statusText,t.getAllResponseHeaders().split(/\\r?\\n/).forEach(function(e){var t=e.match(/^([^:]+):\\s*(.*)/);if(t){var n=t[1].toLowerCase();\"set-cookie\"===n?(void 0===c.headers[n]&&(c.headers[n]=[]),c.headers[n].push(t[2])):void 0!==c.headers[n]?c.headers[n]+=\", \"+t[2]:c.headers[n]=t[2],c.rawHeaders.push(t[1],t[2])}}),c._charset=\"x-user-defined\",!i.overrideMimeType){var f=c.rawHeaders[\"mime-type\"];if(f){var d=f.match(/;\\s*charset=([^;])(;|$)/);d&&(c._charset=d[1].toLowerCase())}c._charset||(c._charset=\"utf-8\")}}};a(c,s.Readable),c.prototype._read=function(){var e=this._resumeFetch;e&&(this._resumeFetch=null,e())},c.prototype._onXHRProgress=function(){var e=this,t=e._xhr,n=null;switch(e._mode){case\"text:vbarray\":if(t.readyState!==l.DONE)break;try{n=new o.VBArray(t.responseBody).toArray()}catch(e){}if(null!==n){e.push(new r(n));break}case\"text\":try{n=t.responseText}catch(t){e._mode=\"text:vbarray\";break}if(n.length>e._pos){var i=n.substr(e._pos);if(\"x-user-defined\"===e._charset){for(var a=new r(i.length),s=0;s<i.length;s++)a[s]=255&i.charCodeAt(s);e.push(a)}else e.push(i,e._charset);e._pos=n.length}break;case\"arraybuffer\":if(t.readyState!==l.DONE||!t.response)break;n=t.response,e.push(new r(new Uint8Array(n)));break;case\"moz-chunked-arraybuffer\":if(n=t.response,t.readyState!==l.LOADING||!n)break;e.push(new r(new Uint8Array(n)));break;case\"ms-stream\":if(n=t.response,t.readyState!==l.LOADING)break;var c=new o.MSStreamReader;c.onprogress=function(){c.result.byteLength>e._pos&&(e.push(new r(new Uint8Array(c.result.slice(e._pos)))),e._pos=c.result.byteLength)},c.onload=function(){e.push(null)},c.readAsArrayBuffer(n)}e._xhr.readyState===l.DONE&&\"ms-stream\"!==e._mode&&e.push(null)}}).call(this,n(6),n(9).Buffer,n(4))},function(e,t,n){(t=e.exports=n(110)).Stream=t,t.Readable=t,t.Writable=n(114),t.Duplex=n(30),t.Transform=n(116),t.PassThrough=n(229)},function(e,t,n){\"use strict\";(function(t,r){var o=n(49);e.exports=b;var i,a=n(101);b.ReadableState=v;n(111).EventEmitter;var s=function(e,t){return e.listeners(t).length},l=n(112),c=n(50).Buffer,u=t.Uint8Array||function(){};var p=n(38);p.inherits=n(20);var f=n(223),d=void 0;d=f&&f.debuglog?f.debuglog(\"stream\"):function(){};var h,m=n(224),g=n(113);p.inherits(b,l);var y=[\"error\",\"close\",\"destroy\",\"pause\",\"resume\"];function v(e,t){e=e||{};var r=t instanceof(i=i||n(30));this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var o=e.highWaterMark,a=e.readableHighWaterMark,s=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(a||0===a)?a:s,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new m,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||\"utf8\",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(h||(h=n(115).StringDecoder),this.decoder=new h(e.encoding),this.encoding=e.encoding)}function b(e){if(i=i||n(30),!(this instanceof b))return new b(e);this._readableState=new v(e,this),this.readable=!0,e&&(\"function\"==typeof e.read&&(this._read=e.read),\"function\"==typeof e.destroy&&(this._destroy=e.destroy)),l.call(this)}function w(e,t,n,r,o){var i,a=e._readableState;null===t?(a.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,S(e)}(e,a)):(o||(i=function(e,t){var n;r=t,c.isBuffer(r)||r instanceof u||\"string\"==typeof t||void 0===t||e.objectMode||(n=new TypeError(\"Invalid non-string/buffer chunk\"));var r;return n}(a,t)),i?e.emit(\"error\",i):a.objectMode||t&&t.length>0?(\"string\"==typeof t||a.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?a.endEmitted?e.emit(\"error\",new Error(\"stream.unshift() after end event\")):x(e,a,t,!0):a.ended?e.emit(\"error\",new Error(\"stream.push() after EOF\")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?x(e,a,t,!1):O(e,a)):x(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(a)}function x(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(e.emit(\"data\",n),e.read(0)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&S(e)),O(e,t)}Object.defineProperty(b.prototype,\"destroyed\",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.push(null),t(e)},b.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:\"string\"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=c.from(e,t),t=\"\"),n=!0),w(this,e,t,!1,n)},b.prototype.unshift=function(e){return w(this,e,null,!0,!1)},b.prototype.isPaused=function(){return!1===this._readableState.flowing},b.prototype.setEncoding=function(e){return h||(h=n(115).StringDecoder),this._readableState.decoder=new h(e),this._readableState.encoding=e,this};var k=8388608;function E(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=k?e=k:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function S(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(d(\"emitReadable\",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(_,e):_(e))}function _(e){d(\"emit readable\"),e.emit(\"readable\"),A(e)}function O(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(C,e,t))}function C(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(d(\"maybeReadMore read 0\"),e.read(0),n!==t.length);)n=t.length;t.readingMore=!1}function T(e){d(\"readable nexttick read 0\"),e.read(0)}function j(e,t){t.reading||(d(\"resume read 0\"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit(\"resume\"),A(e),t.flowing&&!t.reading&&e.read(0)}function A(e){var t=e._readableState;for(d(\"flow\",t.flowing);t.flowing&&null!==e.read(););}function I(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(\"\"):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;e<t.head.data.length?(r=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):r=e===t.head.data.length?t.shift():n?function(e,t){var n=t.head,r=1,o=n.data;e-=o.length;for(;n=n.next;){var i=n.data,a=e>i.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function P(e){var t=e._readableState;if(t.length>0)throw new Error('\"endReadable()\" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(R,t,e))}function R(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit(\"end\"))}function N(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}b.prototype.read=function(e){d(\"read\",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return d(\"read: emitReadable\",t.length,t.ended),0===t.length&&t.ended?P(this):S(this),null;if(0===(e=E(e,t))&&t.ended)return 0===t.length&&P(this),null;var r,o=t.needReadable;return d(\"need readable\",o),(0===t.length||t.length-e<t.highWaterMark)&&d(\"length less than watermark\",o=!0),t.ended||t.reading?d(\"reading or ended\",o=!1):o&&(d(\"do read\"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=E(n,t))),null===(r=e>0?I(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&P(this)),null!==r&&this.emit(\"data\",r),r},b.prototype._read=function(e){this.emit(\"error\",new Error(\"_read() is not implemented\"))},b.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,d(\"pipe count=%d opts=%j\",i.pipesCount,t);var l=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?u:b;function c(t,r){d(\"onunpipe\"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,d(\"cleanup\"),e.removeListener(\"close\",y),e.removeListener(\"finish\",v),e.removeListener(\"drain\",p),e.removeListener(\"error\",g),e.removeListener(\"unpipe\",c),n.removeListener(\"end\",u),n.removeListener(\"end\",b),n.removeListener(\"data\",m),f=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||p())}function u(){d(\"onend\"),e.end()}i.endEmitted?o.nextTick(l):n.once(\"end\",l),e.on(\"unpipe\",c);var p=function(e){return function(){var t=e._readableState;d(\"pipeOnDrain\",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,\"data\")&&(t.flowing=!0,A(e))}}(n);e.on(\"drain\",p);var f=!1;var h=!1;function m(t){d(\"ondata\"),h=!1,!1!==e.write(t)||h||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==N(i.pipes,e))&&!f&&(d(\"false write response, pause\",n._readableState.awaitDrain),n._readableState.awaitDrain++,h=!0),n.pause())}function g(t){d(\"onerror\",t),b(),e.removeListener(\"error\",g),0===s(e,\"error\")&&e.emit(\"error\",t)}function y(){e.removeListener(\"finish\",v),b()}function v(){d(\"onfinish\"),e.removeListener(\"close\",y),b()}function b(){d(\"unpipe\"),n.unpipe(e)}return n.on(\"data\",m),function(e,t,n){if(\"function\"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,\"error\",g),e.once(\"close\",y),e.once(\"finish\",v),e.emit(\"pipe\",n),i.flowing||(d(\"pipe resume\"),n.resume()),e},b.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit(\"unpipe\",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<o;i++)r[i].emit(\"unpipe\",this,n);return this}var a=N(t.pipes,e);return-1===a?this:(t.pipes.splice(a,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit(\"unpipe\",this,n),this)},b.prototype.on=function(e,t){var n=l.prototype.on.call(this,e,t);if(\"data\"===e)!1!==this._readableState.flowing&&this.resume();else if(\"readable\"===e){var r=this._readableState;r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.emittedReadable=!1,r.reading?r.length&&S(this):o.nextTick(T,this))}return n},b.prototype.addListener=b.prototype.on,b.prototype.resume=function(){var e=this._readableState;return e.flowing||(d(\"resume\"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,o.nextTick(j,e,t))}(this,e)),this},b.prototype.pause=function(){return d(\"call pause flowing=%j\",this._readableState.flowing),!1!==this._readableState.flowing&&(d(\"pause\"),this._readableState.flowing=!1,this.emit(\"pause\")),this},b.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var o in e.on(\"end\",function(){if(d(\"wrapped end\"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)}),e.on(\"data\",function(o){(d(\"wrapped data\"),n.decoder&&(o=n.decoder.write(o)),n.objectMode&&null==o)||(n.objectMode||o&&o.length)&&(t.push(o)||(r=!0,e.pause()))}),e)void 0===this[o]&&\"function\"==typeof e[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));for(var i=0;i<y.length;i++)e.on(y[i],this.emit.bind(this,y[i]));return this._read=function(t){d(\"wrapped _read\",t),r&&(r=!1,e.resume())},this},Object.defineProperty(b.prototype,\"readableHighWaterMark\",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),b._fromList=I}).call(this,n(4),n(6))},function(e,t){function n(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return\"function\"==typeof e}function o(e){return\"object\"==typeof e&&null!==e}function i(e){return void 0===e}e.exports=n,n.EventEmitter=n,n.prototype._events=void 0,n.prototype._maxListeners=void 0,n.defaultMaxListeners=10,n.prototype.setMaxListeners=function(e){if(\"number\"!=typeof e||e<0||isNaN(e))throw TypeError(\"n must be a positive number\");return this._maxListeners=e,this},n.prototype.emit=function(e){var t,n,a,s,l,c;if(this._events||(this._events={}),\"error\"===e&&(!this._events.error||o(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var u=new Error('Uncaught, unspecified \"error\" event. ('+t+\")\");throw u.context=t,u}if(i(n=this._events[e]))return!1;if(r(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:s=Array.prototype.slice.call(arguments,1),n.apply(this,s)}else if(o(n))for(s=Array.prototype.slice.call(arguments,1),a=(c=n.slice()).length,l=0;l<a;l++)c[l].apply(this,s);return!0},n.prototype.addListener=function(e,t){var a;if(!r(t))throw TypeError(\"listener must be a function\");return this._events||(this._events={}),this._events.newListener&&this.emit(\"newListener\",e,r(t.listener)?t.listener:t),this._events[e]?o(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,o(this._events[e])&&!this._events[e].warned&&(a=i(this._maxListeners)?n.defaultMaxListeners:this._maxListeners)&&a>0&&this._events[e].length>a&&(this._events[e].warned=!0,console.error(\"(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.\",this._events[e].length),\"function\"==typeof console.trace&&console.trace()),this},n.prototype.on=n.prototype.addListener,n.prototype.once=function(e,t){if(!r(t))throw TypeError(\"listener must be a function\");var n=!1;function o(){this.removeListener(e,o),n||(n=!0,t.apply(this,arguments))}return o.listener=t,this.on(e,o),this},n.prototype.removeListener=function(e,t){var n,i,a,s;if(!r(t))throw TypeError(\"listener must be a function\");if(!this._events||!this._events[e])return this;if(a=(n=this._events[e]).length,i=-1,n===t||r(n.listener)&&n.listener===t)delete this._events[e],this._events.removeListener&&this.emit(\"removeListener\",e,t);else if(o(n)){for(s=a;s-- >0;)if(n[s]===t||n[s].listener&&n[s].listener===t){i=s;break}if(i<0)return this;1===n.length?(n.length=0,delete this._events[e]):n.splice(i,1),this._events.removeListener&&this.emit(\"removeListener\",e,t)}return this},n.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)\"removeListener\"!==t&&this.removeAllListeners(t);return this.removeAllListeners(\"removeListener\"),this._events={},this}if(r(n=this._events[e]))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},n.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},n.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},n.listenerCount=function(e,t){return e.listenerCount(t)}},function(e,t,n){e.exports=n(111).EventEmitter},function(e,t,n){\"use strict\";var r=n(49);function o(e,t){e.emit(\"error\",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){\"use strict\";(function(t,r,o){var i=n(49);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=v;var s,l=!t.browser&&[\"v0.10\",\"v0.9.\"].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;v.WritableState=y;var c=n(38);c.inherits=n(20);var u={deprecate:n(228)},p=n(112),f=n(50).Buffer,d=o.Uint8Array||function(){};var h,m=n(113);function g(){}function y(e,t){s=s||n(30),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,u=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:u,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var p=!1===e.decodeStrings;this.decodeStrings=!p,this.defaultEncoding=e.defaultEncoding||\"utf8\",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit(\"error\",r)):(o(r),e._writableState.errorEmitted=!0,e.emit(\"error\",r),S(e,t))}(e,n,r,t,o);else{var a=k(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||x(e,n),r?l(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function v(e){if(s=s||n(30),!(h.call(v,this)||this instanceof s))return new v(e);this._writableState=new y(e,this),this.writable=!0,e&&(\"function\"==typeof e.write&&(this._write=e.write),\"function\"==typeof e.writev&&(this._writev=e.writev),\"function\"==typeof e.destroy&&(this._destroy=e.destroy),\"function\"==typeof e.final&&(this._final=e.final)),p.call(this)}function b(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit(\"drain\"))}(e,t),t.pendingcb--,r(),S(e,t)}function x(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,l=!0;n;)o[s]=n,n.isBuf||(l=!1),n=n.next,s+=1;o.allBuffers=l,b(e,t,!0,t.length,o,\"\",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,u=n.encoding,p=n.callback;if(b(e,t,!1,t.objectMode?1:c.length,c,u,p),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function k(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function E(e,t){e._final(function(n){t.pendingcb--,n&&e.emit(\"error\",n),t.prefinished=!0,e.emit(\"prefinish\"),S(e,t)})}function S(e,t){var n=k(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||(\"function\"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(E,e,t)):(t.prefinished=!0,e.emit(\"prefinish\")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit(\"finish\"))),n}c.inherits(v,p),y.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(y.prototype,\"buffer\",{get:u.deprecate(function(){return this.getBuffer()},\"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.\",\"DEP0003\")})}catch(e){}}(),\"function\"==typeof Symbol&&Symbol.hasInstance&&\"function\"==typeof Function.prototype[Symbol.hasInstance]?(h=Function.prototype[Symbol.hasInstance],Object.defineProperty(v,Symbol.hasInstance,{value:function(e){return!!h.call(this,e)||this===v&&(e&&e._writableState instanceof y)}})):h=function(e){return e instanceof this},v.prototype.pipe=function(){this.emit(\"error\",new Error(\"Cannot pipe, not readable\"))},v.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,f.isBuffer(r)||r instanceof d);return s&&!f.isBuffer(e)&&(e=function(e){return f.from(e)}(e)),\"function\"==typeof t&&(n=t,t=null),s?t=\"buffer\":t||(t=o.defaultEncoding),\"function\"!=typeof n&&(n=g),o.ended?function(e,t){var n=new Error(\"write after end\");e.emit(\"error\",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError(\"May not write null values to stream\"):\"string\"==typeof n||void 0===n||t.objectMode||(a=new TypeError(\"Invalid non-string/buffer chunk\")),a&&(e.emit(\"error\",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||\"string\"!=typeof t||(t=f.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o=\"buffer\",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var l=t.length<t.highWaterMark;l||(t.needDrain=!0);if(t.writing||t.corked){var c=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:o,isBuf:n,callback:i,next:null},c?c.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else b(e,t,!1,s,r,o,i);return l}(this,o,s,e,t,n)),a},v.prototype.cork=function(){this._writableState.corked++},v.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||x(this,e))},v.prototype.setDefaultEncoding=function(e){if(\"string\"==typeof e&&(e=e.toLowerCase()),!([\"hex\",\"utf8\",\"utf-8\",\"ascii\",\"binary\",\"base64\",\"ucs2\",\"ucs-2\",\"utf16le\",\"utf-16le\",\"raw\"].indexOf((e+\"\").toLowerCase())>-1))throw new TypeError(\"Unknown encoding: \"+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(v.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),v.prototype._write=function(e,t,n){n(new Error(\"_write() is not implemented\"))},v.prototype._writev=null,v.prototype.end=function(e,t,n){var r=this._writableState;\"function\"==typeof e?(n=e,e=null,t=null):\"function\"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,S(e,t),n&&(t.finished?i.nextTick(n):e.once(\"finish\",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(v.prototype,\"destroyed\",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),v.prototype.destroy=m.destroy,v.prototype._undestroy=m.undestroy,v.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(6),n(226).setImmediate,n(4))},function(e,t,n){\"use strict\";var r=n(50).Buffer,o=r.isEncoding||function(e){switch((e=\"\"+e)&&e.toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":case\"raw\":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return\"utf8\";for(var t;;)switch(e){case\"utf8\":case\"utf-8\":return\"utf8\";case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return\"utf16le\";case\"latin1\":case\"binary\":return\"latin1\";case\"base64\":case\"ascii\":case\"hex\":return e;default:if(t)return;e=(\"\"+e).toLowerCase(),t=!0}}(e);if(\"string\"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error(\"Unknown encoding: \"+e);return t||e}(e),this.encoding){case\"utf16le\":this.text=l,this.end=c,t=4;break;case\"utf8\":this.fillLast=s,t=4;break;case\"base64\":this.text=u,this.end=p,t=3;break;default:return this.write=f,void(this.end=d)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,\"�\";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,\"�\";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,\"�\"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function l(e,t){if((e.length-t)%2==0){var n=e.toString(\"utf16le\",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString(\"utf16le\",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):\"\";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString(\"utf16le\",0,n)}return t}function u(e,t){var n=(e.length-t)%3;return 0===n?e.toString(\"base64\",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString(\"base64\",t,e.length-n))}function p(e){var t=e&&e.length?this.write(e):\"\";return this.lastNeed?t+this.lastChar.toString(\"base64\",0,3-this.lastNeed):t}function f(e){return e.toString(this.encoding)}function d(e){return e&&e.length?this.write(e):\"\"}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return\"\";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return\"\";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||\"\"},i.prototype.end=function(e){var t=e&&e.length?this.write(e):\"\";return this.lastNeed?t+\"�\":t},i.prototype.text=function(e,t){var n=function(e,t,n){var r=t.length-1;if(r<n)return 0;var o=a(t[r]);if(o>=0)return o>0&&(e.lastNeed=o-1),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(e.lastNeed=o-2),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString(\"utf8\",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString(\"utf8\",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){\"use strict\";e.exports=i;var r=n(30),o=n(38);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e),this._transformState={afterTransform:function(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit(\"error\",new Error(\"write callback called multiple times\"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&(\"function\"==typeof e.transform&&(this._transform=e.transform),\"function\"==typeof e.flush&&(this._flush=e.flush)),this.on(\"prefinish\",a)}function a(){var e=this;\"function\"==typeof this._flush?this._flush(function(t,n){s(e,t,n)}):s(this,null,null)}function s(e,t,n){if(t)return e.emit(\"error\",t);if(null!=n&&e.push(n),e._writableState.length)throw new Error(\"Calling transform done when ws.length != 0\");if(e._transformState.transforming)throw new Error(\"Calling transform done when still transforming\");return e.push(null)}o.inherits=n(20),o.inherits(i,r),i.prototype.push=function(e,t){return this._transformState.needTransform=!1,r.prototype.push.call(this,e,t)},i.prototype._transform=function(e,t,n){throw new Error(\"_transform() is not implemented\")},i.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var o=this._readableState;(r.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},i.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},i.prototype._destroy=function(e,t){var n=this;r.prototype._destroy.call(this,e,function(e){t(e),n.emit(\"close\")})}},function(e,t,n){\"use strict\";(function(t){var r=n(25),o=n(19),i=n(235);e.exports=function(e,n,a){try{e=o.stripHash(e);var s=n._add(e),l={url:e,extension:o.getExtension(e)};return function(e,t){return new Promise(function(n,o){var a=i.all(t.resolve);a=i.filter(a,\"canRead\",e),i.sort(a),i.run(a,\"read\",e).then(n,function(t){!t||t instanceof SyntaxError?o(r.syntax('Unable to resolve $ref pointer \"%s\"',e.url)):o(t)})})}(l,a).then(function(e){return s.pathType=e.plugin.name,l.data=e.result,function(e,n){return new Promise(function(o,a){var s=i.all(n.parse),l=i.filter(s,\"canParse\",e),c=l.length>0?l:s;i.sort(c),i.run(c,\"parse\",e).then(function(n){!n.plugin.allowEmpty&&(i=n.result,void 0===i||\"object\"==typeof i&&0===Object.keys(i).length||\"string\"==typeof i&&0===i.trim().length||t.isBuffer(i)&&0===i.length)?a(r.syntax('Error parsing \"%s\" as %s. \\nParsed value is empty',e.url,n.plugin.name)):o(n);var i},function(t){t?(t=t instanceof Error?t:new Error(t),a(r.syntax(t,\"Error parsing %s\",e.url))):a(r.syntax(\"Unable to parse %s\",e.url))})})}(l,a)}).then(function(e){return s.value=e.result,e.result})}catch(e){return Promise.reject(e)}}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";(function(t,n){var r=t.process&&n.nextTick||t.setImmediate||function(e){setTimeout(e,0)};e.exports=function(e,t){return e?void t.then(function(t){r(function(){e(null,t)})},function(t){r(function(){e(t)})}):t}}).call(this,n(4),n(6))},function(e,t){},function(t,n){t.exports=e},function(e,t,n){\"use strict\";e.exports={isRef:function(e,t){return\"$ref\"===t&&!!e&&\"string\"==typeof e[t]}}},function(e,t,n){\"use strict\";var r=n(76).jpescape;e.exports={recurse:function e(t,n,o){if(n||(n={depth:0}),n.depth||(n=Object.assign({},{path:\"#\",depth:0,pkey:\"\",parent:{},payload:{},seen:new WeakMap,identity:!1,identityDetection:!1},n)),\"object\"==typeof t){var i=n.path;for(var a in t){if(n.key=a,n.path=n.path+\"/\"+encodeURIComponent(r(a)),n.identityPath=n.seen.get(t[a]),n.identity=void 0!==n.identityPath,o(t,a,n),\"object\"==typeof t[a]&&!n.identity){n.identityDetection&&!Array.isArray(t[a])&&null!==t[a]&&n.seen.set(t[a],n.path);var s={};s.parent=t,s.path=n.path,s.depth=n.depth?n.depth+1:1,s.pkey=a,s.payload=n.payload,s.seen=n.seen,s.identity=!1,s.identityDetection=n.identityDetection,e(t[a],s,o)}n.path=i}}}}},function(e,t,n){\"use strict\";(function(t){var r=n(46),o=t.env.NODE_DISABLE_COLORS?{red:\"\",yellow:\"\",green:\"\",normal:\"\"}:{red:\"\u001b[31m\",yellow:\"\u001b[33;1m\",green:\"\u001b[32m\",normal:\"\u001b[0m\"};function i(e){for(var t=[],n=function(e){t.find(function(t,n,o){return function(e,t){function n(e,t){return r.dump(e)===r.dump(Object.assign({},e,t))}return n(e,t)&&n(t,e)}(t,e)})||t.push(e)},o=0,i=e;o<i.length;o++){n(i[o])}return t}String.prototype.toCamelCase=function(){return this.toLowerCase().replace(/[-_ \\/\\.](.)/g,function(e,t){return t.toUpperCase()})};function a(e){var t=(e=e.replace(\"[]\",\"Array\")).split(\"/\");return t[0]=t[0].replace(/[^A-Za-z0-9_\\-\\.]+|\\s+/gm,\"_\"),t.join(\"/\")}e.exports={colour:o,uniqueOnly:function(e,t,n){return n.indexOf(e)===t},hasDuplicates:function(e){return new Set(e).size!==e.length},allSame:function(e){return new Set(e).size<=1},distinctArray:function(e){return e.length===i(e).length},hash:function(e){var t=0;if(0===e.length)return t;for(var n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return t},parameterTypeProperties:[\"format\",\"minimum\",\"maximum\",\"exclusiveMinimum\",\"exclusiveMaximum\",\"minLength\",\"maxLength\",\"multipleOf\",\"minItems\",\"maxItems\",\"uniqueItems\",\"minProperties\",\"maxProperties\",\"additionalProperties\",\"pattern\",\"enum\",\"default\"],arrayProperties:[\"items\",\"minItems\",\"maxItems\",\"uniqueItems\"],httpMethods:[\"get\",\"post\",\"put\",\"delete\",\"patch\",\"head\",\"options\",\"trace\"],sanitise:a,sanitiseAll:function(e){return a(e.split(\"/\").join(\"_\"))}}}).call(this,n(6))},function(e,t){e.exports=function(){}},function(e,t,n){var r;r=function(){var e=JSON.parse('{\"$\":\"dollar\",\"&\":\"and\",\"<\":\"less\",\">\":\"greater\",\"|\":\"or\",\"¢\":\"cent\",\"£\":\"pound\",\"¤\":\"currency\",\"¥\":\"yen\",\"©\":\"(c)\",\"ª\":\"a\",\"®\":\"(r)\",\"º\":\"o\",\"À\":\"A\",\"Á\":\"A\",\"Â\":\"A\",\"Ã\":\"A\",\"Ä\":\"A\",\"Å\":\"A\",\"Æ\":\"AE\",\"Ç\":\"C\",\"È\":\"E\",\"É\":\"E\",\"Ê\":\"E\",\"Ë\":\"E\",\"Ì\":\"I\",\"Í\":\"I\",\"Î\":\"I\",\"Ï\":\"I\",\"Ð\":\"D\",\"Ñ\":\"N\",\"Ò\":\"O\",\"Ó\":\"O\",\"Ô\":\"O\",\"Õ\":\"O\",\"Ö\":\"O\",\"Ø\":\"O\",\"Ù\":\"U\",\"Ú\":\"U\",\"Û\":\"U\",\"Ü\":\"U\",\"Ý\":\"Y\",\"Þ\":\"TH\",\"ß\":\"ss\",\"à\":\"a\",\"á\":\"a\",\"â\":\"a\",\"ã\":\"a\",\"ä\":\"a\",\"å\":\"a\",\"æ\":\"ae\",\"ç\":\"c\",\"è\":\"e\",\"é\":\"e\",\"ê\":\"e\",\"ë\":\"e\",\"ì\":\"i\",\"í\":\"i\",\"î\":\"i\",\"ï\":\"i\",\"ð\":\"d\",\"ñ\":\"n\",\"ò\":\"o\",\"ó\":\"o\",\"ô\":\"o\",\"õ\":\"o\",\"ö\":\"o\",\"ø\":\"o\",\"ù\":\"u\",\"ú\":\"u\",\"û\":\"u\",\"ü\":\"u\",\"ý\":\"y\",\"þ\":\"th\",\"ÿ\":\"y\",\"Ā\":\"A\",\"ā\":\"a\",\"Ă\":\"A\",\"ă\":\"a\",\"Ą\":\"A\",\"ą\":\"a\",\"Ć\":\"C\",\"ć\":\"c\",\"Č\":\"C\",\"č\":\"c\",\"Ď\":\"D\",\"ď\":\"d\",\"Đ\":\"DJ\",\"đ\":\"dj\",\"Ē\":\"E\",\"ē\":\"e\",\"Ė\":\"E\",\"ė\":\"e\",\"Ę\":\"e\",\"ę\":\"e\",\"Ě\":\"E\",\"ě\":\"e\",\"Ğ\":\"G\",\"ğ\":\"g\",\"Ģ\":\"G\",\"ģ\":\"g\",\"Ĩ\":\"I\",\"ĩ\":\"i\",\"Ī\":\"i\",\"ī\":\"i\",\"Į\":\"I\",\"į\":\"i\",\"İ\":\"I\",\"ı\":\"i\",\"Ķ\":\"k\",\"ķ\":\"k\",\"Ļ\":\"L\",\"ļ\":\"l\",\"Ľ\":\"L\",\"ľ\":\"l\",\"Ł\":\"L\",\"ł\":\"l\",\"Ń\":\"N\",\"ń\":\"n\",\"Ņ\":\"N\",\"ņ\":\"n\",\"Ň\":\"N\",\"ň\":\"n\",\"Ő\":\"O\",\"ő\":\"o\",\"Œ\":\"OE\",\"œ\":\"oe\",\"Ŕ\":\"R\",\"ŕ\":\"r\",\"Ř\":\"R\",\"ř\":\"r\",\"Ś\":\"S\",\"ś\":\"s\",\"Ş\":\"S\",\"ş\":\"s\",\"Š\":\"S\",\"š\":\"s\",\"Ţ\":\"T\",\"ţ\":\"t\",\"Ť\":\"T\",\"ť\":\"t\",\"Ũ\":\"U\",\"ũ\":\"u\",\"Ū\":\"u\",\"ū\":\"u\",\"Ů\":\"U\",\"ů\":\"u\",\"Ű\":\"U\",\"ű\":\"u\",\"Ų\":\"U\",\"ų\":\"u\",\"Ź\":\"Z\",\"ź\":\"z\",\"Ż\":\"Z\",\"ż\":\"z\",\"Ž\":\"Z\",\"ž\":\"z\",\"ƒ\":\"f\",\"Ơ\":\"O\",\"ơ\":\"o\",\"Ư\":\"U\",\"ư\":\"u\",\"ǈ\":\"LJ\",\"ǉ\":\"lj\",\"ǋ\":\"NJ\",\"ǌ\":\"nj\",\"Ș\":\"S\",\"ș\":\"s\",\"Ț\":\"T\",\"ț\":\"t\",\"˚\":\"o\",\"Ά\":\"A\",\"Έ\":\"E\",\"Ή\":\"H\",\"Ί\":\"I\",\"Ό\":\"O\",\"Ύ\":\"Y\",\"Ώ\":\"W\",\"ΐ\":\"i\",\"Α\":\"A\",\"Β\":\"B\",\"Γ\":\"G\",\"Δ\":\"D\",\"Ε\":\"E\",\"Ζ\":\"Z\",\"Η\":\"H\",\"Θ\":\"8\",\"Ι\":\"I\",\"Κ\":\"K\",\"Λ\":\"L\",\"Μ\":\"M\",\"Ν\":\"N\",\"Ξ\":\"3\",\"Ο\":\"O\",\"Π\":\"P\",\"Ρ\":\"R\",\"Σ\":\"S\",\"Τ\":\"T\",\"Υ\":\"Y\",\"Φ\":\"F\",\"Χ\":\"X\",\"Ψ\":\"PS\",\"Ω\":\"W\",\"Ϊ\":\"I\",\"Ϋ\":\"Y\",\"ά\":\"a\",\"έ\":\"e\",\"ή\":\"h\",\"ί\":\"i\",\"ΰ\":\"y\",\"α\":\"a\",\"β\":\"b\",\"γ\":\"g\",\"δ\":\"d\",\"ε\":\"e\",\"ζ\":\"z\",\"η\":\"h\",\"θ\":\"8\",\"ι\":\"i\",\"κ\":\"k\",\"λ\":\"l\",\"μ\":\"m\",\"ν\":\"n\",\"ξ\":\"3\",\"ο\":\"o\",\"π\":\"p\",\"ρ\":\"r\",\"ς\":\"s\",\"σ\":\"s\",\"τ\":\"t\",\"υ\":\"y\",\"φ\":\"f\",\"χ\":\"x\",\"ψ\":\"ps\",\"ω\":\"w\",\"ϊ\":\"i\",\"ϋ\":\"y\",\"ό\":\"o\",\"ύ\":\"y\",\"ώ\":\"w\",\"Ё\":\"Yo\",\"Ђ\":\"DJ\",\"Є\":\"Ye\",\"І\":\"I\",\"Ї\":\"Yi\",\"Ј\":\"J\",\"Љ\":\"LJ\",\"Њ\":\"NJ\",\"Ћ\":\"C\",\"Џ\":\"DZ\",\"А\":\"A\",\"Б\":\"B\",\"В\":\"V\",\"Г\":\"G\",\"Д\":\"D\",\"Е\":\"E\",\"Ж\":\"Zh\",\"З\":\"Z\",\"И\":\"I\",\"Й\":\"J\",\"К\":\"K\",\"Л\":\"L\",\"М\":\"M\",\"Н\":\"N\",\"О\":\"O\",\"П\":\"P\",\"Р\":\"R\",\"С\":\"S\",\"Т\":\"T\",\"У\":\"U\",\"Ф\":\"F\",\"Х\":\"H\",\"Ц\":\"C\",\"Ч\":\"Ch\",\"Ш\":\"Sh\",\"Щ\":\"Sh\",\"Ъ\":\"U\",\"Ы\":\"Y\",\"Ь\":\"\",\"Э\":\"E\",\"Ю\":\"Yu\",\"Я\":\"Ya\",\"а\":\"a\",\"б\":\"b\",\"в\":\"v\",\"г\":\"g\",\"д\":\"d\",\"е\":\"e\",\"ж\":\"zh\",\"з\":\"z\",\"и\":\"i\",\"й\":\"j\",\"к\":\"k\",\"л\":\"l\",\"м\":\"m\",\"н\":\"n\",\"о\":\"o\",\"п\":\"p\",\"р\":\"r\",\"с\":\"s\",\"т\":\"t\",\"у\":\"u\",\"ф\":\"f\",\"х\":\"h\",\"ц\":\"c\",\"ч\":\"ch\",\"ш\":\"sh\",\"щ\":\"sh\",\"ъ\":\"u\",\"ы\":\"y\",\"ь\":\"\",\"э\":\"e\",\"ю\":\"yu\",\"я\":\"ya\",\"ё\":\"yo\",\"ђ\":\"dj\",\"є\":\"ye\",\"і\":\"i\",\"ї\":\"yi\",\"ј\":\"j\",\"љ\":\"lj\",\"њ\":\"nj\",\"ћ\":\"c\",\"џ\":\"dz\",\"Ґ\":\"G\",\"ґ\":\"g\",\"฿\":\"baht\",\"ა\":\"a\",\"ბ\":\"b\",\"გ\":\"g\",\"დ\":\"d\",\"ე\":\"e\",\"ვ\":\"v\",\"ზ\":\"z\",\"თ\":\"t\",\"ი\":\"i\",\"კ\":\"k\",\"ლ\":\"l\",\"მ\":\"m\",\"ნ\":\"n\",\"ო\":\"o\",\"პ\":\"p\",\"ჟ\":\"zh\",\"რ\":\"r\",\"ს\":\"s\",\"ტ\":\"t\",\"უ\":\"u\",\"ფ\":\"f\",\"ქ\":\"k\",\"ღ\":\"gh\",\"ყ\":\"q\",\"შ\":\"sh\",\"ჩ\":\"ch\",\"ც\":\"ts\",\"ძ\":\"dz\",\"წ\":\"ts\",\"ჭ\":\"ch\",\"ხ\":\"kh\",\"ჯ\":\"j\",\"ჰ\":\"h\",\"ẞ\":\"SS\",\"Ạ\":\"A\",\"ạ\":\"a\",\"Ả\":\"A\",\"ả\":\"a\",\"Ấ\":\"A\",\"ấ\":\"a\",\"Ầ\":\"A\",\"ầ\":\"a\",\"Ẩ\":\"A\",\"ẩ\":\"a\",\"Ẫ\":\"A\",\"ẫ\":\"a\",\"Ậ\":\"A\",\"ậ\":\"a\",\"Ắ\":\"A\",\"ắ\":\"a\",\"Ằ\":\"A\",\"ằ\":\"a\",\"Ẳ\":\"A\",\"ẳ\":\"a\",\"Ẵ\":\"A\",\"ẵ\":\"a\",\"Ặ\":\"A\",\"ặ\":\"a\",\"Ẹ\":\"E\",\"ẹ\":\"e\",\"Ẻ\":\"E\",\"ẻ\":\"e\",\"Ẽ\":\"E\",\"ẽ\":\"e\",\"Ế\":\"E\",\"ế\":\"e\",\"Ề\":\"E\",\"ề\":\"e\",\"Ể\":\"E\",\"ể\":\"e\",\"Ễ\":\"E\",\"ễ\":\"e\",\"Ệ\":\"E\",\"ệ\":\"e\",\"Ỉ\":\"I\",\"ỉ\":\"i\",\"Ị\":\"I\",\"ị\":\"i\",\"Ọ\":\"O\",\"ọ\":\"o\",\"Ỏ\":\"O\",\"ỏ\":\"o\",\"Ố\":\"O\",\"ố\":\"o\",\"Ồ\":\"O\",\"ồ\":\"o\",\"Ổ\":\"O\",\"ổ\":\"o\",\"Ỗ\":\"O\",\"ỗ\":\"o\",\"Ộ\":\"O\",\"ộ\":\"o\",\"Ớ\":\"O\",\"ớ\":\"o\",\"Ờ\":\"O\",\"ờ\":\"o\",\"Ở\":\"O\",\"ở\":\"o\",\"Ỡ\":\"O\",\"ỡ\":\"o\",\"Ợ\":\"O\",\"ợ\":\"o\",\"Ụ\":\"U\",\"ụ\":\"u\",\"Ủ\":\"U\",\"ủ\":\"u\",\"Ứ\":\"U\",\"ứ\":\"u\",\"Ừ\":\"U\",\"ừ\":\"u\",\"Ử\":\"U\",\"ử\":\"u\",\"Ữ\":\"U\",\"ữ\":\"u\",\"Ự\":\"U\",\"ự\":\"u\",\"Ỳ\":\"Y\",\"ỳ\":\"y\",\"Ỵ\":\"Y\",\"ỵ\":\"y\",\"Ỷ\":\"Y\",\"ỷ\":\"y\",\"Ỹ\":\"Y\",\"ỹ\":\"y\",\"‘\":\"\\'\",\"’\":\"\\'\",\"“\":\"\\\\\"\",\"”\":\"\\\\\"\",\"†\":\"+\",\"•\":\"*\",\"…\":\"...\",\"₠\":\"ecu\",\"₢\":\"cruzeiro\",\"₣\":\"french franc\",\"₤\":\"lira\",\"₥\":\"mill\",\"₦\":\"naira\",\"₧\":\"peseta\",\"₨\":\"rupee\",\"₩\":\"won\",\"₪\":\"new shequel\",\"₫\":\"dong\",\"€\":\"euro\",\"₭\":\"kip\",\"₮\":\"tugrik\",\"₯\":\"drachma\",\"₰\":\"penny\",\"₱\":\"peso\",\"₲\":\"guarani\",\"₳\":\"austral\",\"₴\":\"hryvnia\",\"₵\":\"cedi\",\"₹\":\"indian rupee\",\"₽\":\"russian ruble\",\"₿\":\"bitcoin\",\"℠\":\"sm\",\"™\":\"tm\",\"∂\":\"d\",\"∆\":\"delta\",\"∑\":\"sum\",\"∞\":\"infinity\",\"♥\":\"love\",\"元\":\"yuan\",\"円\":\"yen\",\"﷼\":\"rial\"}');function t(t,n){if(\"string\"!=typeof t)throw new Error(\"slugify: string argument expected\");n=\"string\"==typeof n?{replacement:n}:n||{};var r=t.split(\"\").reduce(function(t,r){return t+(e[r]||r).replace(n.remove||/[^\\w\\s$*_+~.()'\"!\\-:@]/g,\"\")},\"\").trim().replace(/[-\\s]+/g,n.replacement||\"-\");return n.lower?r.toLowerCase():r}return t.extend=function(t){for(var n in t)e[n]=t[n]},t},e.exports=r(),e.exports.default=r()},function(e,t,n){\"use strict\";n.r(t),function(e){n.d(t,\"css\",function(){return ye}),n.d(t,\"keyframes\",function(){return it}),n.d(t,\"createGlobalStyle\",function(){return rt}),n.d(t,\"isStyledComponent\",function(){return O}),n.d(t,\"ThemeConsumer\",function(){return Ye}),n.d(t,\"ThemeContext\",function(){return He}),n.d(t,\"ThemeProvider\",function(){return Ve}),n.d(t,\"withTheme\",function(){return at}),n.d(t,\"ServerStyleSheet\",function(){return Qe}),n.d(t,\"StyleSheetManager\",function(){return Ke}),n.d(t,\"__DO_NOT_USE_OR_YOU_WILL_BE_HAUNTED_BY_SPOOKY_GHOSTS\",function(){return st});var r=n(78),o=n.n(r),i=n(127),a=n.n(i),s=n(0),l=n.n(s),c=n(128),u=n(54),p=n(39),f=(n(11),n(13),n(133)),d=function(e,t){for(var n=[e[0]],r=0,o=t.length;r<o;r+=1)n.push(t[r],e[r+1]);return n},h=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},m=function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")},g=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),y=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},v=function(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)},b=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},w=function(e,t){if(!e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!t||\"object\"!=typeof t&&\"function\"!=typeof t?e:t},x=function(e){return\"object\"===(void 0===e?\"undefined\":h(e))&&e.constructor===Object},k=Object.freeze([]),E=Object.freeze({});function S(e){return\"function\"==typeof e}function _(e){return e.displayName||e.name||\"Component\"}function O(e){return e&&\"string\"==typeof e.styledComponentId}var C=void 0!==e&&e.env.SC_ATTR||\"data-styled\",T=\"undefined\"!=typeof window&&\"HTMLElement\"in window,j=\"boolean\"==typeof SC_DISABLE_SPEEDY&&SC_DISABLE_SPEEDY||!1,A={};var I=function(e){function t(n){m(this,t);for(var r=arguments.length,o=Array(r>1?r-1:0),i=1;i<r;i++)o[i-1]=arguments[i];var a=w(this,e.call(this,\"An error occurred. See https://github.com/styled-components/styled-components/blob/master/src/utils/errors.md#\"+n+\" for more information. \"+(o?\"Additional arguments: \"+o.join(\", \"):\"\")));return w(a)}return v(t,e),t}(Error),P=/^[^\\S\\n]*?\\/\\* sc-component-id:\\s*(\\S+)\\s+\\*\\//gm,R=function(e){var t=\"\"+(e||\"\"),n=[];return t.replace(P,function(e,t,r){return n.push({componentId:t,matchIndex:r}),e}),n.map(function(e,r){var o=e.componentId,i=e.matchIndex,a=n[r+1];return{componentId:o,cssFromDOM:a?t.slice(i,a.matchIndex):t.slice(i)}})},N=/^\\s*\\/\\/.*$/gm,L=new o.a({global:!1,cascade:!0,keyframe:!1,prefix:!1,compress:!1,semicolon:!0}),M=new o.a({global:!1,cascade:!0,keyframe:!1,prefix:!0,compress:!1,semicolon:!1}),D=[],F=function(e){if(-2===e){var t=D;return D=[],t}},U=a()(function(e){D.push(e)}),B=void 0,z=void 0,$=void 0,W=function(e,t,n){return t>0&&-1!==n.slice(0,t).indexOf(z)&&n.slice(t-z.length,t)!==z?\".\"+B:e};M.use([function(e,t,n){2===e&&n.length&&n[0].lastIndexOf(z)>0&&(n[0]=n[0].replace($,W))},U,F]),L.use([U,F]);function q(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:\"&\",o=e.join(\"\").replace(N,\"\"),i=t&&n?n+\" \"+t+\" { \"+o+\" }\":o;return B=r,z=t,$=new RegExp(\"\\\\\"+z+\"\\\\b\",\"g\"),M(n||!t?\"\":t,i)}var H=function(){return n.nc},Y=function(e,t,n){n&&((e[t]||(e[t]=Object.create(null)))[n]=!0)},V=function(e,t){e[t]=Object.create(null)},Q=function(e){return function(t,n){return void 0!==e[t]&&e[t][n]}},G=function(e){var t=\"\";for(var n in e)t+=Object.keys(e[n]).join(\" \")+\" \";return t.trim()},X=function(e){if(e.sheet)return e.sheet;for(var t=document.styleSheets.length,n=0;n<t;n+=1){var r=document.styleSheets[n];if(r.ownerNode===e)return r}throw new I(10)},K=function(e,t,n){if(!t)return!1;var r=e.cssRules.length;try{e.insertRule(t,n<=r?n:r)}catch(e){return!1}return!0},J=function(e){return\"\\n/* sc-component-id: \"+e+\" */\\n\"},Z=function(e,t){for(var n=0,r=0;r<=t;r+=1)n+=e[r];return n},ee=function(e,t){return function(n){var r=H();return\"<style \"+[r&&'nonce=\"'+r+'\"',C+'=\"'+G(t)+'\"','data-styled-version=\"4.1.1\"',n].filter(Boolean).join(\" \")+\">\"+e()+\"</style>\"}},te=function(e,t){return function(){var n,r=((n={})[C]=G(t),n[\"data-styled-version\"]=\"4.1.1\",n),o=H();return o&&(r.nonce=o),l.a.createElement(\"style\",y({},r,{dangerouslySetInnerHTML:{__html:e()}}))}},ne=function(e){return function(){return Object.keys(e)}},re=function(e){return document.createTextNode(J(e))},oe=function e(t,n){var r=void 0===t?Object.create(null):t,o=void 0===n?Object.create(null):n,i=function(e){var t=o[e];return void 0!==t?t:o[e]=[\"\"]},a=function(){var e=\"\";for(var t in o){var n=o[t][0];n&&(e+=J(t)+n)}return e};return{clone:function(){var t=function(e){var t=Object.create(null);for(var n in e)t[n]=y({},e[n]);return t}(r),n=Object.create(null);for(var i in o)n[i]=[o[i][0]];return e(t,n)},css:a,getIds:ne(o),hasNameForId:Q(r),insertMarker:i,insertRules:function(e,t,n){i(e)[0]+=t.join(\" \"),Y(r,e,n)},removeRules:function(e){var t=o[e];void 0!==t&&(t[0]=\"\",V(r,e))},sealed:!1,styleTag:null,toElement:te(a,r),toHTML:ee(a,r)}},ie=function(e,t,n,r,o){if(T&&!n){var i=function(e,t,n){var r=document.createElement(\"style\");r.setAttribute(C,\"\"),r.setAttribute(\"data-styled-version\",\"4.1.1\");var o=H();if(o&&r.setAttribute(\"nonce\",o),r.appendChild(document.createTextNode(\"\")),e&&!t)e.appendChild(r);else{if(!t||!e||!t.parentNode)throw new I(6);t.parentNode.insertBefore(r,n?t:t.nextSibling)}return r}(e,t,r);return j?function(e,t){var n=Object.create(null),r=Object.create(null),o=void 0!==t,i=!1,a=function(t){var o=r[t];return void 0!==o?o:(r[t]=re(t),e.appendChild(r[t]),n[t]=Object.create(null),r[t])},s=function(){var e=\"\";for(var t in r)e+=r[t].data;return e};return{clone:function(){throw new I(5)},css:s,getIds:ne(r),hasNameForId:Q(n),insertMarker:a,insertRules:function(e,r,s){for(var l=a(e),c=[],u=r.length,p=0;p<u;p+=1){var f=r[p],d=o;if(d&&-1!==f.indexOf(\"@import\"))c.push(f);else{d=!1;var h=p===u-1?\"\":\" \";l.appendData(\"\"+f+h)}}Y(n,e,s),o&&c.length>0&&(i=!0,t().insertRules(e+\"-import\",c))},removeRules:function(a){var s=r[a];if(void 0!==s){var l=re(a);e.replaceChild(l,s),r[a]=l,V(n,a),o&&i&&t().removeRules(a+\"-import\")}},sealed:!1,styleTag:e,toElement:te(s,n),toHTML:ee(s,n)}}(i,o):function(e,t){var n=Object.create(null),r=Object.create(null),o=[],i=void 0!==t,a=!1,s=function(e){var t=r[e];return void 0!==t?t:(r[e]=o.length,o.push(0),V(n,e),r[e])},l=function(){var t=X(e).cssRules,n=\"\";for(var i in r){n+=J(i);for(var a=r[i],s=Z(o,a),l=s-o[a];l<s;l+=1){var c=t[l];void 0!==c&&(n+=c.cssText)}}return n};return{clone:function(){throw new I(5)},css:l,getIds:ne(r),hasNameForId:Q(n),insertMarker:s,insertRules:function(r,l,c){for(var u=s(r),p=X(e),f=Z(o,u),d=0,h=[],m=l.length,g=0;g<m;g+=1){var y=l[g],v=i;v&&-1!==y.indexOf(\"@import\")?h.push(y):K(p,y,f+d)&&(v=!1,d+=1)}i&&h.length>0&&(a=!0,t().insertRules(r+\"-import\",h)),o[u]+=d,Y(n,r,c)},removeRules:function(s){var l=r[s];if(void 0!==l){var c=o[l];!function(e,t,n){for(var r=t-n,o=t;o>r;o-=1)e.deleteRule(o)}(X(e),Z(o,l)-1,c),o[l]=0,V(n,s),i&&a&&t().removeRules(s+\"-import\")}},sealed:!1,styleTag:e,toElement:te(l,n),toHTML:ee(l,n)}}(i,o)}return oe()},ae=/\\s+/,se=void 0;se=T?j?40:1e3:-1;var le=0,ce=void 0,ue=function(){function e(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:T?document.head:null,r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];m(this,e),this.getImportRuleTag=function(){var e=t.importRuleTag;if(void 0!==e)return e;var n=t.tags[0];return t.importRuleTag=ie(t.target,n?n.styleTag:null,t.forceServer,!0)},le+=1,this.id=le,this.forceServer=r,this.target=r?null:n,this.tagMap={},this.deferred={},this.rehydratedNames={},this.ignoreRehydratedNames={},this.tags=[],this.capacity=1,this.clones=[]}return e.prototype.rehydrate=function(){if(!T||this.forceServer)return this;var e=[],t=[],n=!1,r=document.querySelectorAll(\"style[\"+C+'][data-styled-version=\"4.1.1\"]'),o=r.length;if(!o)return this;for(var i=0;i<o;i+=1){var a=r[i];n||(n=!!a.getAttribute(\"data-styled-streamed\"));for(var s,l=(a.getAttribute(C)||\"\").trim().split(ae),c=l.length,u=0;u<c;u+=1)s=l[u],this.rehydratedNames[s]=!0;t.push.apply(t,R(a.textContent)),e.push(a)}var p=t.length;if(!p)return this;var f=this.makeTag(null);!function(e,t,n){for(var r=0,o=n.length;r<o;r+=1){var i=n[r],a=i.componentId,s=i.cssFromDOM,l=L(\"\",s);e.insertRules(a,l)}for(var c=0,u=t.length;c<u;c+=1){var p=t[c];p.parentNode&&p.parentNode.removeChild(p)}}(f,e,t),this.capacity=Math.max(1,se-p),this.tags.push(f);for(var d=0;d<p;d+=1)this.tagMap[t[d].componentId]=f;return this},e.reset=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];ce=new e(void 0,t).rehydrate()},e.prototype.clone=function(){var t=new e(this.target,this.forceServer);return this.clones.push(t),t.tags=this.tags.map(function(e){for(var n=e.getIds(),r=e.clone(),o=0;o<n.length;o+=1)t.tagMap[n[o]]=r;return r}),t.rehydratedNames=y({},this.rehydratedNames),t.deferred=y({},this.deferred),t},e.prototype.sealAllTags=function(){this.capacity=1,this.tags.forEach(function(e){e.sealed=!0})},e.prototype.makeTag=function(e){var t=e?e.styleTag:null;return ie(this.target,t,this.forceServer,!1,this.getImportRuleTag)},e.prototype.getTagForId=function(e){var t=this.tagMap[e];if(void 0!==t&&!t.sealed)return t;var n=this.tags[this.tags.length-1];return this.capacity-=1,0===this.capacity&&(this.capacity=se,n=this.makeTag(n),this.tags.push(n)),this.tagMap[e]=n},e.prototype.hasId=function(e){return void 0!==this.tagMap[e]},e.prototype.hasNameForId=function(e,t){if(void 0===this.ignoreRehydratedNames[e]&&this.rehydratedNames[t])return!0;var n=this.tagMap[e];return void 0!==n&&n.hasNameForId(e,t)},e.prototype.deferredInject=function(e,t){if(void 0===this.tagMap[e]){for(var n=this.clones,r=0;r<n.length;r+=1)n[r].deferredInject(e,t);this.getTagForId(e).insertMarker(e),this.deferred[e]=t}},e.prototype.inject=function(e,t,n){for(var r=this.clones,o=0;o<r.length;o+=1)r[o].inject(e,t,n);var i=this.getTagForId(e);if(void 0!==this.deferred[e]){var a=this.deferred[e].concat(t);i.insertRules(e,a,n),this.deferred[e]=void 0}else i.insertRules(e,t,n)},e.prototype.remove=function(e){var t=this.tagMap[e];if(void 0!==t){for(var n=this.clones,r=0;r<n.length;r+=1)n[r].remove(e);t.removeRules(e),this.ignoreRehydratedNames[e]=!0,this.deferred[e]=void 0}},e.prototype.toHTML=function(){return this.tags.map(function(e){return e.toHTML()}).join(\"\")},e.prototype.toReactElements=function(){var e=this.id;return this.tags.map(function(t,n){var r=\"sc-\"+e+\"-\"+n;return Object(s.cloneElement)(t.toElement(),{key:r})})},g(e,null,[{key:\"master\",get:function(){return ce||(ce=(new e).rehydrate())}},{key:\"instance\",get:function(){return e.master}}]),e}(),pe=function(){function e(t,n){var r=this;m(this,e),this.inject=function(e){e.hasNameForId(r.id,r.name)||e.inject(r.id,r.rules,r.name)},this.toString=function(){throw new I(12,String(r.name))},this.name=t,this.rules=n,this.id=\"sc-keyframes-\"+t}return e.prototype.getName=function(){return this.name},e}(),fe=/([A-Z])/g,de=/^ms-/;var he=function(e){return null==e||!1===e||\"\"===e},me=function e(t,n){var r=Object.keys(t).filter(function(e){return!he(t[e])}).map(function(n){return x(t[n])?e(t[n],n):n.replace(fe,\"-$1\").toLowerCase().replace(de,\"-ms-\")+\": \"+(r=n,null==(o=t[n])||\"boolean\"==typeof o||\"\"===o?\"\":\"number\"!=typeof o||0===o||r in c.a?String(o).trim():o+\"px\")+\";\";var r,o}).join(\" \");return n?n+\" {\\n  \"+r+\"\\n}\":r};function ge(e,t,n){if(Array.isArray(e)){for(var r,o=[],i=0,a=e.length;i<a;i+=1)null!==(r=ge(e[i],t,n))&&(Array.isArray(r)?o.push.apply(o,r):o.push(r));return o}if(he(e))return null;if(O(e))return\".\"+e.styledComponentId;if(S(e)){if(t){var s=!1;try{Object(u.isElement)(new e(t))&&(s=!0)}catch(e){}if(s)throw new I(13,_(e));return ge(e(t),t,n)}return e}return e instanceof pe?n?(e.inject(n),e.getName()):e:x(e)?me(e):e.toString()}function ye(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return S(e)||x(e)?ge(d(k,[e].concat(n))):ge(d(e,n))}function ve(e){for(var t,n=0|e.length,r=0|n,o=0;n>=4;)t=1540483477*(65535&(t=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(t>>>16)&65535)<<16),r=1540483477*(65535&r)+((1540483477*(r>>>16)&65535)<<16)^(t=1540483477*(65535&(t^=t>>>24))+((1540483477*(t>>>16)&65535)<<16)),n-=4,++o;switch(n){case 3:r^=(255&e.charCodeAt(o+2))<<16;case 2:r^=(255&e.charCodeAt(o+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(o)))+((1540483477*(r>>>16)&65535)<<16)}return((r=1540483477*(65535&(r^=r>>>13))+((1540483477*(r>>>16)&65535)<<16))^r>>>15)>>>0}var be=52,we=function(e){return String.fromCharCode(e+(e>25?39:97))};function xe(e){var t=\"\",n=void 0;for(n=e;n>be;n=Math.floor(n/be))t=we(n%be)+t;return we(n%be)+t}function ke(e,t){for(var n=0;n<e.length;n+=1){var r=e[n];if(Array.isArray(r)&&!ke(r,t))return!1;if(S(r)&&!O(r))return!1}return!t.some(function(e){return S(e)||function(e){for(var t in e)if(S(e[t]))return!0;return!1}(e)})}var Ee,Se=!1,_e=function(e){return xe(ve(e))},Oe=function(){function e(t,n,r){m(this,e),this.rules=t,this.isStatic=!Se&&ke(t,n),this.componentId=r,ue.master.hasId(r)||ue.master.deferredInject(r,[])}return e.prototype.generateAndInjectStyles=function(e,t){var n=this.isStatic,r=this.componentId,o=this.lastClassName;if(T&&n&&\"string\"==typeof o&&t.hasNameForId(r,o))return o;var i=ge(this.rules,e,t),a=_e(this.componentId+i.join(\"\"));return t.hasNameForId(r,a)||t.inject(this.componentId,q(i,\".\"+a,void 0,r),a),this.lastClassName=a,a},e.generateName=function(e){return _e(e)},e}(),Ce=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:E,r=!!n&&e.theme===n.theme;return e.theme&&!r?e.theme:t||n.theme},Te=/[[\\].#*$><+~=|^:(),\"'`-]+/g,je=/(^-|-$)/g;function Ae(e){return e.replace(Te,\"-\").replace(je,\"\")}function Ie(e){return\"string\"==typeof e}var Pe={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDerivedStateFromProps:!0,propTypes:!0,type:!0},Re={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},Ne=((Ee={})[u.ForwardRef]={$$typeof:!0,render:!0},Ee),Le=Object.defineProperty,Me=Object.getOwnPropertyNames,De=Object.getOwnPropertySymbols,Fe=void 0===De?function(){return[]}:De,Ue=Object.getOwnPropertyDescriptor,Be=Object.getPrototypeOf,ze=Object.prototype,$e=Array.prototype;function We(e,t,n){if(\"string\"!=typeof t){var r=Be(t);r&&r!==ze&&We(e,r,n);for(var o=$e.concat(Me(t),Fe(t)),i=Ne[e.$$typeof]||Pe,a=Ne[t.$$typeof]||Pe,s=o.length,l=void 0,c=void 0;s--;)if(c=o[s],!(Re[c]||n&&n[c]||a&&a[c]||i&&i[c])&&(l=Ue(t,c)))try{Le(e,c,l)}catch(e){}return e}return e}var qe=function(e){var t=!1;return function(){t||(t=!0,e.apply(void 0,arguments))}},He=Object(s.createContext)(),Ye=He.Consumer,Ve=function(e){function t(n){m(this,t);var r=w(this,e.call(this,n));return r.getContext=Object(p.a)(r.getContext.bind(r)),r.renderInner=r.renderInner.bind(r),r}return v(t,e),t.prototype.render=function(){return this.props.children?l.a.createElement(He.Consumer,null,this.renderInner):null},t.prototype.renderInner=function(e){var t=this.getContext(this.props.theme,e);return l.a.createElement(He.Provider,{value:t},l.a.Children.only(this.props.children))},t.prototype.getTheme=function(e,t){if(S(e))return e(t);if(null===e||Array.isArray(e)||\"object\"!==(void 0===e?\"undefined\":h(e)))throw new I(8);return y({},t,e)},t.prototype.getContext=function(e,t){return this.getTheme(e,t)},t}(s.Component),Qe=function(){function e(){m(this,e),this.masterSheet=ue.master,this.instance=this.masterSheet.clone(),this.sealed=!1}return e.prototype.seal=function(){if(!this.sealed){var e=this.masterSheet.clones.indexOf(this.instance);this.masterSheet.clones.splice(e,1),this.sealed=!0}},e.prototype.collectStyles=function(e){if(this.sealed)throw new I(2);return l.a.createElement(Ke,{sheet:this.instance},e)},e.prototype.getStyleTags=function(){return this.seal(),this.instance.toHTML()},e.prototype.getStyleElement=function(){return this.seal(),this.instance.toReactElements()},e.prototype.interleaveWithNodeStream=function(e){throw new I(3)},e}(),Ge=Object(s.createContext)(),Xe=Ge.Consumer,Ke=function(e){function t(n){m(this,t);var r=w(this,e.call(this,n));return r.getContext=Object(p.a)(r.getContext),r}return v(t,e),t.prototype.getContext=function(e,t){if(e)return e;if(t)return new ue(t);throw new I(4)},t.prototype.render=function(){var e=this.props,t=e.children,n=e.sheet,r=e.target;return l.a.createElement(Ge.Provider,{value:this.getContext(n,r)},t)},t}(s.Component),Je=(new Set,{});qe(function(){return console.warn('The \"innerRef\" API has been removed in styled-components v4 in favor of React 16 ref forwarding, use \"ref\" instead like a typical component.')}),qe(function(e,t){return console.warn('Functions as object-form attrs({}) keys are now deprecated and will be removed in a future version of styled-components. Switch to the new attrs(props => ({})) syntax instead for easier and more powerful composition. The attrs key in question is \"'+e+'\" on component \"'+t+'\".')}),qe(function(e,t){return console.warn(\"It looks like you've used a non styled-component as the value for the \\\"\"+e+'\" prop in an object-form attrs constructor of \"'+t+\"\\\".\\nYou should use the new function-form attrs constructor which avoids this issue: attrs(props => ({ yourStuff }))\\nTo continue using the deprecated object syntax, you'll need to wrap your component prop in a function to make it available inside the styled component (you'll still get the deprecation warning though.)\\nFor example, { \"+e+\": () => InnerComponent } instead of { \"+e+\": InnerComponent }\")});var Ze=function(e){function t(){m(this,t);var n=w(this,e.call(this));return n.attrs={},n.renderOuter=n.renderOuter.bind(n),n.renderInner=n.renderInner.bind(n),n}return v(t,e),t.prototype.render=function(){return l.a.createElement(Xe,null,this.renderOuter)},t.prototype.renderOuter=function(e){return this.styleSheet=e,this.props.forwardedClass.componentStyle.isStatic?this.renderInner():l.a.createElement(Ye,null,this.renderInner)},t.prototype.renderInner=function(e){var t=this.props.forwardedClass,n=t.componentStyle,r=t.defaultProps,o=t.styledComponentId,i=t.target,a=void 0;a=n.isStatic?this.generateAndInjectStyles(E,this.props,this.styleSheet):void 0!==e?this.generateAndInjectStyles(Ce(this.props,e,r),this.props,this.styleSheet):this.generateAndInjectStyles(this.props.theme||E,this.props,this.styleSheet);var l=this.props.as||this.attrs.as||i,c=Ie(l),u={},p=y({},this.attrs,this.props),d=void 0;for(d in p)\"forwardedClass\"!==d&&\"as\"!==d&&(\"forwardedRef\"===d?u.ref=p[d]:c&&!Object(f.a)(d)||(u[d]=p[d]));return this.props.style&&this.attrs.style&&(u.style=y({},this.attrs.style,this.props.style)),u.className=[this.props.className,o,this.attrs.className,a].filter(Boolean).join(\" \"),Object(s.createElement)(l,u)},t.prototype.buildExecutionContext=function(e,t,n){var r=this,o=y({},t,{theme:e});return n.length?(this.attrs={},n.forEach(function(e){var n,i=e,a=!1,s=void 0,l=void 0;for(l in S(i)&&(i=i(t),a=!0),i)s=i[l],a||!S(s)||(n=s)&&n.prototype&&n.prototype.isReactComponent||O(s)||(s=s(o)),r.attrs[l]=s,o[l]=s}),o):o},t.prototype.generateAndInjectStyles=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:ue.master,r=t.forwardedClass,o=r.attrs,i=r.componentStyle;r.warnTooManyClasses;return i.isStatic&&!o.length?i.generateAndInjectStyles(E,n):i.generateAndInjectStyles(this.buildExecutionContext(e,t,o),n)},t}(s.Component);function et(e,t,n){var r=O(e),o=!Ie(e),i=t.displayName,a=void 0===i?function(e){return Ie(e)?\"styled.\"+e:\"Styled(\"+_(e)+\")\"}(e):i,s=t.componentId,c=void 0===s?function(e,t,n){var r=\"string\"!=typeof t?\"sc\":Ae(t),o=(Je[r]||0)+1;Je[r]=o;var i=r+\"-\"+e.generateName(r+o);return n?n+\"-\"+i:i}(Oe,t.displayName,t.parentComponentId):s,u=t.ParentComponent,p=void 0===u?Ze:u,f=t.attrs,d=void 0===f?k:f,h=t.displayName&&t.componentId?Ae(t.displayName)+\"-\"+t.componentId:t.componentId||c,m=r&&e.attrs?Array.prototype.concat(e.attrs,d).filter(Boolean):d,g=new Oe(r?e.componentStyle.rules.concat(n):n,m,h),v=l.a.forwardRef(function(e,t){return l.a.createElement(p,y({},e,{forwardedClass:v,forwardedRef:t}))});return v.attrs=m,v.componentStyle=g,v.displayName=a,v.styledComponentId=h,v.target=r?e.target:e,v.withComponent=function(e){var r=t.componentId,o=b(t,[\"componentId\"]),i=r&&r+\"-\"+(Ie(e)?e:Ae(_(e)));return et(e,y({},o,{attrs:m,componentId:i,ParentComponent:p}),n)},v.toString=function(){return\".\"+v.styledComponentId},o&&We(v,e,{attrs:!0,componentStyle:!0,displayName:!0,styledComponentId:!0,target:!0,withComponent:!0}),v}var tt=function(e){return function e(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:E;if(!Object(u.isValidElementType)(n))throw new I(1,String(n));var o=function(){return t(n,r,ye.apply(void 0,arguments))};return o.withConfig=function(o){return e(t,n,y({},r,o))},o.attrs=function(o){return e(t,n,y({},r,{attrs:Array.prototype.concat(r.attrs,o).filter(Boolean)}))},o}(et,e)};[\"a\",\"abbr\",\"address\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"data\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dialog\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"kbd\",\"keygen\",\"label\",\"legend\",\"li\",\"link\",\"main\",\"map\",\"mark\",\"marquee\",\"menu\",\"menuitem\",\"meta\",\"meter\",\"nav\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"picture\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"u\",\"ul\",\"var\",\"video\",\"wbr\",\"circle\",\"clipPath\",\"defs\",\"ellipse\",\"foreignObject\",\"g\",\"image\",\"line\",\"linearGradient\",\"mask\",\"path\",\"pattern\",\"polygon\",\"polyline\",\"radialGradient\",\"rect\",\"stop\",\"svg\",\"text\",\"tspan\"].forEach(function(e){tt[e]=tt(e)});var nt=function(){function e(t,n){m(this,e),this.rules=t,this.componentId=n,this.isStatic=ke(t,k),ue.master.hasId(n)||ue.master.deferredInject(n,[])}return e.prototype.createStyles=function(e,t){var n=q(ge(this.rules,e,t),\"\");t.inject(this.componentId,n)},e.prototype.removeStyles=function(e){var t=this.componentId;e.hasId(t)&&e.remove(t)},e.prototype.renderStyles=function(e,t){this.removeStyles(t),this.createStyles(e,t)},e}();function rt(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var o=ye.apply(void 0,[e].concat(n)),i=\"sc-global-\"+ve(JSON.stringify(o)),a=new nt(o,i),s=function(e){function t(){m(this,t);var n=w(this,e.call(this)),r=n.constructor,o=r.globalStyle,i=r.styledComponentId;return T&&(window.scCGSHMRCache[i]=(window.scCGSHMRCache[i]||0)+1),n.state={globalStyle:o,styledComponentId:i},n}return v(t,e),t.prototype.componentDidMount=function(){0},t.prototype.componentWillUnmount=function(){window.scCGSHMRCache[this.state.styledComponentId]&&(window.scCGSHMRCache[this.state.styledComponentId]-=1),0===window.scCGSHMRCache[this.state.styledComponentId]&&this.state.globalStyle.removeStyles(this.styleSheet)},t.prototype.render=function(){var e=this;return l.a.createElement(Xe,null,function(t){e.styleSheet=t||ue.master;var n=e.state.globalStyle;return n.isStatic?(n.renderStyles(A,e.styleSheet),null):l.a.createElement(Ye,null,function(t){var r=e.constructor.defaultProps,o=y({},e.props);return void 0!==t&&(o.theme=Ce(e.props,t,r)),n.renderStyles(o,e.styleSheet),null})})},t}(l.a.Component);return s.defaultProps={suppressMultiMountWarning:!1},s.globalStyle=a,s.styledComponentId=i,s}T&&(window.scCGSHMRCache={});var ot=function(e){return e.replace(/\\s|\\\\n/g,\"\")};function it(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var o=ye.apply(void 0,[e].concat(n)),i=xe(ve(ot(JSON.stringify(o))));return new pe(i,q(o,i,\"@keyframes\"))}var at=function(e){var t=l.a.forwardRef(function(t,n){return l.a.createElement(Ye,null,function(r){var o=e.defaultProps,i=Ce(t,r,o);return l.a.createElement(e,y({},t,{theme:i,ref:n}))})});return We(t,e),t.displayName=\"WithTheme(\"+_(e)+\")\",t},st={StyleSheet:ue};t.default=tt}.call(this,n(6))},function(e,t,n){e.exports=function(){\"use strict\";return function(e){function t(t){if(t)try{e(t+\"}\")}catch(e){}}return function(n,r,o,i,a,s,l,c,u,p){switch(n){case 1:if(0===u&&64===r.charCodeAt(0))return e(r+\";\"),\"\";break;case 2:if(0===c)return r+\"/*|*/\";break;case 3:switch(c){case 102:case 112:return e(o[0]+r),\"\";default:return r+(0===p?\"/*|*/\":\"\")}case-2:r.split(\"/*|*/}\").forEach(t)}}}}()},function(e,t,n){\"use strict\";t.a={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1}},function(e,t,n){\"use strict\";(function(t){n(102);var r=n(234),o=n(117),i=n(236),a=n(237),s=n(238),l=n(239),c=n(19),u=n(118),p=n(25);function f(){this.schema=null,this.$refs=new r}e.exports=f,e.exports.YAML=n(103),f.parse=function(e,t,n,r){var o=new this;return o.parse.apply(o,arguments)},f.prototype.parse=function(e,n,a,s){var l,f=i(arguments);if(!f.path&&!f.schema){var d=p(\"Expected a file path, URL, or object. Got %s\",f.path||f.schema);return u(f.callback,Promise.reject(d))}this.schema=null,this.$refs=new r;var h=\"http\";if(c.isFileSystemPath(f.path)&&(f.path=c.fromFileSystemPath(f.path),h=\"file\"),f.path=c.resolve(c.cwd(),f.path),f.schema&&\"object\"==typeof f.schema){var m=this.$refs._add(f.path);m.value=f.schema,m.pathType=h,l=Promise.resolve(f.schema)}else l=o(f.path,this.$refs,f.options);var g=this;return l.then(function(e){if(!e||\"object\"!=typeof e||t.isBuffer(e))throw p.syntax('\"%s\" is not a valid JSON Schema',g.$refs._root$Ref.path||e);return g.schema=e,u(f.callback,Promise.resolve(g.schema))}).catch(function(e){return u(f.callback,Promise.reject(e))})},f.resolve=function(e,t,n,r){var o=new this;return o.resolve.apply(o,arguments)},f.prototype.resolve=function(e,t,n,r){var o=this,s=i(arguments);return this.parse(s.path,s.schema,s.options).then(function(){return a(o,s.options)}).then(function(){return u(s.callback,Promise.resolve(o.$refs))}).catch(function(e){return u(s.callback,Promise.reject(e))})},f.bundle=function(e,t,n,r){var o=new this;return o.bundle.apply(o,arguments)},f.prototype.bundle=function(e,t,n,r){var o=this,a=i(arguments);return this.resolve(a.path,a.schema,a.options).then(function(){return s(o,a.options),u(a.callback,Promise.resolve(o.schema))}).catch(function(e){return u(a.callback,Promise.reject(e))})},f.dereference=function(e,t,n,r){var o=new this;return o.dereference.apply(o,arguments)},f.prototype.dereference=function(e,t,n,r){var o=this,a=i(arguments);return this.resolve(a.path,a.schema,a.options).then(function(){return l(o,a.options),u(a.callback,Promise.resolve(o.schema))}).catch(function(e){return u(a.callback,Promise.reject(e))})}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";var r,o=n(119),i=n(10),a=(n(52),n(118)),s=n(120),l=n(46),c=n(76),u=c.jptr,p=n(121).isRef,f=n(77).clone,d=n(77).circularClone,h=n(122).recurse,m=n(240),g=n(243),y=n(123),v=n(244).statusCodes,b=n(245).version,w=\"3.0.0\";function x(e,t){var n=new Error(e);if(n.options=t,!t.promise)throw n;t.promise.reject(n)}function k(e,t,n){n.warnOnly?t[n.warnProperty||\"x-s2o-warning\"]=e:x(e,n)}function E(e,t){g.walkSchema(e,{},{},function(e,n,r){!function(e,t){if(e[\"x-required\"]&&Array.isArray(e[\"x-required\"])&&(e.required||(e.required=[]),e.required=e.required.concat(e[\"x-required\"]),delete e[\"x-required\"]),e[\"x-anyOf\"]&&(e.anyOf=e[\"x-anyOf\"],delete e[\"x-anyOf\"]),e[\"x-oneOf\"]&&(e.oneOf=e[\"x-oneOf\"],delete e[\"x-oneOf\"]),e[\"x-not\"]&&(e.not=e[\"x-not\"],delete e[\"x-not\"]),\"boolean\"==typeof e[\"x-nullable\"]&&(e.nullable=e[\"x-nullable\"],delete e[\"x-nullable\"]),\"object\"==typeof e[\"x-discriminator\"]&&\"string\"==typeof e[\"x-discriminator\"].propertyName)for(var n in e.discriminator=e[\"x-discriminator\"],delete e[\"x-discriminator\"],e.discriminator.mapping){var r=e.discriminator.mapping[n];r.startsWith(\"#/definitions/\")&&(e.discriminator.mapping[n]=r.replace(\"#/definitions/\",\"#/components/schemas/\"))}}(e),function(e,t,n){if(e.discriminator&&\"string\"==typeof e.discriminator&&(e.discriminator={propertyName:e.discriminator}),e.items&&Array.isArray(e.items)&&(0===e.items.length?e.items={}:1===e.items.length?e.items=e.items[0]:e.items={anyOf:e.items}),e.type&&Array.isArray(e.type))if(n.patch){if(0===e.type.length)delete e.type;else{e.oneOf||(e.oneOf=[]);for(var r=0,o=e.type;r<o.length;r++){var i=o[r],a={};if(\"null\"===i)e.nullable=!0;else{a.type=i;for(var s=0,l=y.arrayProperties;s<l.length;s++){var c=l[s];void 0!==e.prop&&(a[c]=e[c],delete e[c])}}a.type&&e.oneOf.push(a)}delete e.type,0===e.oneOf.length?delete e.oneOf:e.oneOf.length<2&&(e.type=e.oneOf[0].type,Object.keys(e.oneOf[0]).length>1&&k(\"Lost properties from oneOf\",e,n),delete e.oneOf)}e.type&&Array.isArray(e.type)&&1===e.type.length&&(e.type=e.type[0])}else x(\"(Patchable) schema type must not be an array\",n);e.type&&\"null\"===e.type&&(delete e.type,e.nullable=!0),\"array\"!==e.type||e.items||(e.items={}),\"boolean\"==typeof e.required&&(e.required&&e.name&&(void 0===t.required&&(t.required=[]),Array.isArray(t.required)&&t.required.push(e.name)),delete e.required),e.xml&&\"string\"==typeof e.xml.namespace&&(e.xml.namespace||delete e.xml.namespace)}(e,n,t)})}function S(e,t,n){var o,i=n.payload.options;if(p(e,t))if(e[t].startsWith(\"#/components/\"));else if(e[t].startsWith(\"#/definitions/\")){var a=e[t].replace(\"#/definitions/\",\"\").split(\"/\");(b=r.schemas[decodeURIComponent(a[0])])?a[0]=b:k(\"Could not resolve reference \"+e[t],e,i),e[t]=\"#/components/schemas/\"+a.join(\"/\")}else if(e[t].startsWith(\"#/parameters/\"))e[t]=\"#/components/parameters/\"+y.sanitise(e[t].replace(\"#/parameters/\",\"\"));else if(e[t].startsWith(\"#/responses/\"))e[t]=\"#/components/responses/\"+y.sanitise(e[t].replace(\"#/responses/\",\"\"));else if(e[t].startsWith(\"#\")){var s=f(c.jptr(i.openapi,e[t]));if(!1===s)k(\"direct $ref not found \"+e[t],e,i);else if(i.refmap[e[t]])e[t]=i.refmap[e[t]];else{var l=e[t],u=\"schemas\",d=(l=(l=(l=(l=l.replace(\"/properties/headers/\",\"\")).replace(\"/properties/responses/\",\"\")).replace(\"/properties/parameters/\",\"\")).replace(\"/properties/schemas/\",\"\")).lastIndexOf(\"/schema\");if(\"schemas\"===(u=l.indexOf(\"/headers/\")>d?\"headers\":l.indexOf(\"/responses/\")>d?\"responses\":l.indexOf(\"/example\")>d?\"examples\":l.indexOf(\"/parameters/\")>d?\"parameters\":\"schemas\")&&E(s,i),\"responses\"!==u){var h=u.substr(0,u.length-1);\"parameter\"===h&&s.name&&s.name===y.sanitise(s.name)&&(h=encodeURIComponent(s.name));var m=1;for(e[\"x-miro\"]&&(o=(o=e[\"x-miro\"]).indexOf(\"#\")>=0?o.split(\"#\")[1].split(\"/\").pop():o.split(\"/\").pop().split(\".\")[0],h=encodeURIComponent(y.sanitise(o)),m=\"\");c.jptr(i.openapi,\"#/components/\"+u+\"/\"+h+m);)m=\"\"===m?2:++m;var g=\"#/components/\"+u+\"/\"+h+m,v=\"\";\"examples\"===u&&(s={value:s},v=\"/value\"),c.jptr(i.openapi,g,s),i.refmap[e[t]]=g+v,e[t]=g+v}}}if(delete e[\"x-miro\"],\"x-ms-odata\"===t&&\"string\"==typeof e[t]&&e[t].startsWith(\"#/\")){var b;a=e[t].replace(\"#/definitions/\",\"\").replace(\"#/components/schemas/\",\"\").split(\"/\");(b=r.schemas[decodeURIComponent(a[0])])?a[0]=b:k(\"Could not resolve reference \"+e[t],e,i),e[t]=\"#/components/schemas/\"+a.join(\"/\")}}function _(e){for(var t in e)for(var n in e[t]){var r=y.sanitise(n);n!=r&&(e[t][r]=e[t][n],delete e[t][n])}}function O(e,t){if(\"basic\"===e.type&&(e.type=\"http\",e.scheme=\"basic\"),\"oauth2\"===e.type){var n={},r=e.flow;\"application\"===e.flow&&(r=\"clientCredentials\"),\"accessCode\"===e.flow&&(r=\"authorizationCode\"),void 0!==e.authorizationUrl&&(n.authorizationUrl=e.authorizationUrl.split(\"?\")[0].trim()||\"/\"),void 0!==e.tokenUrl&&(n.tokenUrl=e.tokenUrl.split(\"?\")[0].trim()||\"/\"),n.scopes=e.scopes||{},e.flows={},e.flows[r]=n,delete e.flow,delete e.authorizationUrl,delete e.tokenUrl,delete e.scopes,void 0!==e.name&&(t.patch?delete e.name:x(\"(Patchable) oauth2 securitySchemes should not have name property\",t))}}function C(e){return!e[\"x-s2o-delete\"]}function T(e,t){if(e.$ref)e.$ref=e.$ref.replace(\"#/responses/\",\"#/components/responses/\");else{e.type&&!e.schema&&(e.schema={}),e.type&&(e.schema.type=e.type),e.items&&e.items.collectionFormat&&e.items.type&&\"array\"!=e.items.type&&(e.items.collectionFormat!=e.collectionFormat&&k(\"Nested collectionFormats are not supported\",e,t),delete e.items.collectionFormat),void 0!==e.collectionFormat&&(\"array\"!=e.type&&(t.patch?delete e.collectionFormat:x(\"(Patchable) collectionFormat is only applicable to header.type array\",t)),\"csv\"===e.collectionFormat&&(e.style=\"simple\"),\"ssv\"===e.collectionFormat&&k(\"collectionFormat:ssv is no longer supported for headers\",e,t),\"pipes\"===e.collectionFormat&&k(\"collectionFormat:pipes is no longer supported for headers\",e,t),\"multi\"===e.collectionFormat&&(e.explode=!0),\"tsv\"===e.collectionFormat&&(k(\"collectionFormat:tsv is no longer supported\",e,t),e[\"x-collectionFormat\"]=\"tsv\"),delete e.collectionFormat),delete e.type;for(var n=0,r=y.parameterTypeProperties;n<r.length;n++){void 0!==e[a=r[n]]&&(e.schema[a]=e[a],delete e[a])}for(var o=0,i=y.arrayProperties;o<i.length;o++){var a;void 0!==e[a=i[o]]&&(e.schema[a]=e[a],delete e[a])}}}function j(e,t){if(e.$ref.indexOf(\"#/parameters/\")>=0){var n=e.$ref.split(\"#/parameters/\");e.$ref=n[0]+\"#/components/parameters/\"+y.sanitise(n[1])}e.$ref.indexOf(\"#/definitions/\")>=0&&k(\"Definition used as parameter\",e,t)}function A(e,t,n,r,o,i){var a={},s=!0,l=(t&&t.consumes||o.consumes||[]).filter(y.uniqueOnly);if(e.$ref&&\"string\"==typeof e.$ref){j(e,i);var c=decodeURIComponent(e.$ref.replace(\"#/components/parameters/\",\"\")),p=!1;if((O=o.components.parameters[c])&&!O[\"x-s2o-delete\"]||!e.$ref.startsWith(\"#/\")||(e[\"x-s2o-delete\"]=!0,p=!0),p){var d=e.$ref,m=u(o,e.$ref);!m&&d.startsWith(\"#/\")?k(\"Could not resolve reference \"+d,e,i):m&&(e=m)}}if(e.name||e.in){\"boolean\"==typeof e[\"x-deprecated\"]&&(e.deprecated=e[\"x-deprecated\"],delete e[\"x-deprecated\"]),void 0!==e[\"x-example\"]&&(e.example=e[\"x-example\"],delete e[\"x-example\"]),\"body\"==e.in||e.type||(i.patch?e.type=\"string\":x(\"(Patchable) parameter.type is mandatory for non-body parameters\",i)),e.type&&\"object\"==typeof e.type&&e.type.$ref&&(e.type=u(o,e.type.$ref)),e.description&&\"object\"==typeof e.description&&e.description.$ref&&(e.description=u(o,e.description.$ref)),null===e.description&&delete e.description;var g=e.collectionFormat;if(e.collectionFormat&&(\"array\"!=e.type&&(i.patch?delete e.collectionFormat:x(\"(Patchable) collectionFormat is only applicable to param.type array\",i)),\"csv\"!==e.collectionFormat||\"query\"!==e.in&&\"cookie\"!==e.in||(e.style=\"form\",e.explode=!1),\"csv\"!==e.collectionFormat||\"path\"!==e.in&&\"header\"!==e.in||(e.style=\"simple\"),\"ssv\"===e.collectionFormat&&(\"query\"===e.in?e.style=\"spaceDelimited\":k(\"collectionFormat:ssv is no longer supported except for in:query parameters\",e,i)),\"pipes\"===e.collectionFormat&&(\"query\"===e.in?e.style=\"pipeDelimited\":k(\"collectionFormat:pipes is no longer supported except for in:query parameters\",e,i)),\"multi\"===e.collectionFormat&&(e.explode=!0),\"tsv\"===e.collectionFormat&&(k(\"collectionFormat:tsv is no longer supported\",e,i),e[\"x-collectionFormat\"]=\"tsv\"),delete e.collectionFormat),e.type&&\"object\"!=e.type&&\"body\"!=e.type&&\"formData\"!=e.in)if(e.items&&e.schema)k(\"parameter has array,items and schema\",e,i);else{e.schema&&\"object\"==typeof e.schema||(e.schema={}),e.schema.type=e.type,e.items&&(e.schema.items=e.items,delete e.items,h(e.schema.items,null,function(t,n,r){\"collectionFormat\"===n&&\"string\"==typeof t[n]&&(g&&t[n]!==g&&k(\"Nested collectionFormats are not supported\",e,i),delete t[n])}));for(var v=0,b=y.parameterTypeProperties;v<b.length;v++){var w=b[v];void 0!==e[w]&&(e.schema[w]=e[w]),delete e[w]}}e.schema&&E(e.schema,i),e[\"x-ms-skip-url-encoding\"]&&\"query\"===e.in&&(e.allowReserved=!0,delete e[\"x-ms-skip-url-encoding\"])}if(\"formData\"===e.in){s=!1,a.content={};var S=\"application/x-www-form-urlencoded\";if(l.length&&l.indexOf(\"multipart/form-data\")>=0&&(S=\"multipart/form-data\"),a.content[S]={},e.schema)a.content[S].schema=e.schema,e.schema.$ref&&(a[\"x-s2o-name\"]=decodeURIComponent(e.schema.$ref.replace(\"#/components/schemas/\",\"\")));else{a.content[S].schema={},a.content[S].schema.type=\"object\",a.content[S].schema.properties={},a.content[S].schema.properties[e.name]={};var _=a.content[S].schema,O=a.content[S].schema.properties[e.name];e.description&&(O.description=e.description),e.example&&(O.example=e.example),e.type&&(O.type=e.type);for(var C=0,T=y.parameterTypeProperties;C<T.length;C++){w=T[C];void 0!==e[w]&&(O[w]=e[w])}!0===e.required&&(_.required||(_.required=[]),_.required.push(e.name)),void 0!==e.default&&(O.default=e.default),O.properties&&(O.properties=e.properties),e.allOf&&(O.allOf=e.allOf),\"array\"===e.type&&e.items&&(O.items=e.items,O.items.collectionFormat&&delete O.items.collectionFormat),\"file\"===e.type&&(O.type=\"string\",O.format=\"binary\")}}else\"file\"===e.type&&(e.required&&(a.required=e.required),a.content={},a.content[\"application/octet-stream\"]={},a.content[\"application/octet-stream\"].schema={},a.content[\"application/octet-stream\"].schema.type=\"string\",a.content[\"application/octet-stream\"].schema.format=\"binary\");if(\"body\"===e.in){a.content={},e.name&&(a[\"x-s2o-name\"]=(t&&t.operationId?y.sanitiseAll(t.operationId):\"\")+(\"_\"+e.name).toCamelCase()),e.description&&(a.description=e.description),e.required&&(a.required=e.required),e.schema&&e.schema.$ref?a[\"x-s2o-name\"]=decodeURIComponent(e.schema.$ref.replace(\"#/components/schemas/\",\"\")):e.schema&&\"array\"===e.schema.type&&e.schema.items&&e.schema.items.$ref&&(a[\"x-s2o-name\"]=decodeURIComponent(e.schema.items.$ref.replace(\"#/components/schemas/\",\"\"))+\"Array\"),l.length||l.push(\"application/json\");for(var A=0,I=l;A<I.length;A++){var P=I[A];a.content[P]={},a.content[P].schema=f(e.schema)||{},E(a.content[P].schema,i)}}Object.keys(a).length>0&&(e[\"x-s2o-delete\"]=!0,t&&(t.requestBody&&s?(t.requestBody[\"x-s2o-overloaded\"]=!0,k(\"Operation \"+(t.operationId||r)+\" has multiple requestBodies\",t,i)):(t.requestBody=Object.assign({},t.requestBody),t.requestBody.content&&t.requestBody.content[\"multipart/form-data\"]&&a.content[\"multipart/form-data\"]?(t.requestBody.content[\"multipart/form-data\"].schema.properties=Object.assign(t.requestBody.content[\"multipart/form-data\"].schema.properties,a.content[\"multipart/form-data\"].schema.properties),t.requestBody.content[\"multipart/form-data\"].schema.required=(t.requestBody.content[\"multipart/form-data\"].schema.required||[]).concat(a.content[\"multipart/form-data\"].schema.required||[]),t.requestBody.content[\"multipart/form-data\"].schema.required.length||delete t.requestBody.content[\"multipart/form-data\"].schema.required):t.requestBody.content&&t.requestBody.content[\"application/x-www-form-urlencoded\"]&&a.content[\"application/x-www-form-urlencoded\"]?(t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.properties=Object.assign(t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.properties,a.content[\"application/x-www-form-urlencoded\"].schema.properties),t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.required=(t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.required||[]).concat(a.content[\"application/x-www-form-urlencoded\"].schema.required||[]),t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.required.length||delete t.requestBody.content[\"application/x-www-form-urlencoded\"].schema.required):(t.requestBody=Object.assign(t.requestBody,a),t.requestBody[\"x-s2o-name\"]||(t.requestBody.schema&&t.requestBody.schema.$ref?t.requestBody[\"x-s2o-name\"]=decodeURIComponent(t.requestBody.schema.$ref.replace(\"#/components/schemas/\",\"\")).split(\"/\").join(\"\"):t.operationId&&(t.requestBody[\"x-s2o-name\"]=y.sanitiseAll(t.operationId)))))));delete e.type;for(var R=0,N=y.parameterTypeProperties;R<N.length;R++){w=N[R];delete e[w]}return\"path\"!==e.in||void 0!==e.required&&!0===e.required||(i.patch?e.required=!0:x(\"(Patchable) path parameters must be required:true\",i)),a}function I(e,t,n,r,o){if(e.$ref&&\"string\"==typeof e.$ref)e.$ref.indexOf(\"#/definitions/\")>=0?k(\"definition used as response: \"+e.$ref,e,o):e.$ref.startsWith(\"#/responses/\")&&(e.$ref=\"#/components/responses/\"+y.sanitise(decodeURIComponent(e.$ref.replace(\"#/responses/\",\"\"))));else{if(void 0===e.description||null===e.description||\"\"===e.description&&o.patch)if(o.patch){var i=v.find(function(e){return e.code===t});\"object\"!=typeof e||Array.isArray(e)||(e.description=i?i.phrase:\"\")}else x(\"(Patchable) response.description is mandatory\",o);if(e.schema){E(e.schema,o),e.schema.$ref&&\"string\"==typeof e.schema.$ref&&e.schema.$ref.startsWith(\"#/responses/\")&&(e.schema.$ref=\"#/components/responses/\"+y.sanitise(decodeURIComponent(e.schema.$ref.replace(\"#/responses/\",\"\"))));var a=(n&&n.produces||r.produces||[]).filter(y.uniqueOnly);a.length||a.push(\"*/*\"),e.content={};for(var s=0,l=a;s<l.length;s++){var c=l[s];if(e.content[c]={},e.content[c].schema=f(e.schema),e.examples&&e.examples[c]){var u={};u.value=e.examples[c],e.content[c].examples={},e.content[c].examples.response=u,delete e.examples[c]}\"file\"===e.content[c].schema.type&&(e.content[c].schema={type:\"string\",format:\"binary\"})}delete e.schema}for(var c in e.examples)e.content||(e.content={}),e.content[c]||(e.content[c]={}),e.content[c].examples={},e.content[c].examples.response={},e.content[c].examples.response.value=e.examples[c];if(delete e.examples,e.headers)for(var p in e.headers)\"status code\"===p.toLowerCase()?o.patch?delete e.headers[p]:x('(Patchable) \"Status Code\" is not a valid header',o):T(e.headers[p],o)}}function P(e,t,n,r,o){for(var a in e){var s=e[a];for(var l in s[\"x-trace\"]&&\"object\"==typeof s[\"x-trace\"]&&(s.trace=s[\"x-trace\"],delete s[\"x-trace\"]),s[\"x-summary\"]&&\"string\"==typeof s[\"x-summary\"]&&(s.summary=s[\"x-summary\"],delete s[\"x-summary\"]),s[\"x-description\"]&&\"string\"==typeof s[\"x-description\"]&&(s.description=s[\"x-description\"],delete s[\"x-description\"]),s[\"x-servers\"]&&Array.isArray(s[\"x-servers\"])&&(s.servers=s[\"x-servers\"],delete s[\"x-servers\"]),s)if(y.httpMethods.indexOf(l)>=0||\"x-amazon-apigateway-any-method\"===l){var p=s[l];if(p.parameters&&Array.isArray(p.parameters)){if(s.parameters)for(var d=function(e){\"string\"==typeof e.$ref&&(j(e,n),e=u(o,e.$ref)),p.parameters.find(function(t,n,r){return t.name===e.name&&t.in===e.in})||\"formData\"!==e.in&&\"body\"!==e.in&&\"file\"!==e.type||A(e,p,0,a,o,n)},h=0,m=s.parameters;h<m.length;h++){d(J=m[h])}for(var g=0,v=p.parameters;g<v.length;g++){A(J=v[g],p,0,l+\":\"+a,o,n)}n.debug||(p.parameters=p.parameters.filter(C))}if(null===p.parameters&&delete p.parameters,p.security&&_(p.security),!p.responses){var b={description:\"Default response\"};p.responses={default:b}}for(var w in p.responses){I(p.responses[w],w,p,o,n)}if(p[\"x-servers\"]&&Array.isArray(p[\"x-servers\"]))p.servers=p[\"x-servers\"],delete p[\"x-servers\"];else if(p.schemes&&p.schemes.length)for(var x=0,k=p.schemes;x<k.length;x++){var E=k[x];if(!o.schemes||o.schemes.indexOf(E)<0){p.servers||(p.servers=[]);for(var S=0,O=o.servers;S<O.length;S++){var T=O[S],P=f(T),R=i.parse(P.url);R.protocol=E,P.url=R.format(),p.servers.push(P)}}}if(n.debug&&(p[\"x-s2o-consumes\"]=p.consumes||[],p[\"x-s2o-produces\"]=p.produces||[]),delete p.consumes,delete p.produces,delete p.schemes,p[\"x-ms-examples\"]){for(var N in p[\"x-ms-examples\"]){var L=p[\"x-ms-examples\"][N],M=y.sanitiseAll(N);if(L.parameters)for(var D in L.parameters)for(var F=L.parameters[D],U=0,B=(p.parameters||[]).concat(s.parameters||[]);U<B.length;U++){(J=B[U]).$ref&&(J=c.jptr(o,J.$ref)),J.name!==D||J.example||(J.examples||(J.examples={}),J.examples[N]={value:F})}if(L.responses)for(var w in L.responses){if(L.responses[w].headers)for(var z in L.responses[w].headers){F=L.responses[w].headers[z];for(var $ in p.responses[w].headers){if($===z)p.responses[w].headers[$].example=F}}if(L.responses[w].body&&(o.components.examples[M]={value:f(L.responses[w].body)},p.responses[w]&&p.responses[w].content))for(var W in p.responses[w].content){var q=p.responses[w].content[W];q.examples||(q.examples={}),q.examples[N]={$ref:\"#/components/examples/\"+M}}}}delete p[\"x-ms-examples\"]}if(p.parameters&&0===p.parameters.length&&delete p.parameters,p.requestBody){var H=p.operationId?y.sanitiseAll(p.operationId):y.sanitiseAll(l+a).toCamelCase(),Y=y.sanitise(p.requestBody[\"x-s2o-name\"]||H||\"\");delete p.requestBody[\"x-s2o-name\"];var V=JSON.stringify(p.requestBody),Q=y.hash(V);if(!r[Q]){var G={};G.name=Y,G.body=p.requestBody,G.refs=[],r[Q]=G}var X=\"#/\"+t+\"/\"+encodeURIComponent(c.jpescape(a))+\"/\"+l+\"/requestBody\";r[Q].refs.push(X)}}if(null===s.parameters&&delete s.parameters,s.parameters){for(var K in s.parameters){var J;A(J=s.parameters[K],null,0,a,o,n)}n.debug||(s.parameters=s.parameters.filter(C))}}}function R(e,t){var n={};for(var o in r={schemas:{}},e.security&&_(e.security),e.components.securitySchemes){o!=(l=y.sanitise(o))&&(e.components.securitySchemes[l]&&x(\"Duplicate sanitised securityScheme name \"+l,t),e.components.securitySchemes[l]=e.components.securitySchemes[o],delete e.components.securitySchemes[o]),O(e.components.securitySchemes[l],t)}for(var o in e.components.schemas){var i=\"\";if(o!=(l=y.sanitiseAll(o))){for(;e.components.schemas[l+i];)i=i?++i:2;e.components.schemas[l+i]=e.components.schemas[o],delete e.components.schemas[o]}r.schemas[o]=l+i,E(e.components.schemas[l+i],t)}for(var a in t.refmap={},h(e,{payload:{options:t}},S),function(e,t){for(var n in t.refmap)c.jptr(e,n,{$ref:t.refmap[n]})}(e,t),e.components.parameters){a!=(l=y.sanitise(a))&&(e.components.parameters[l]&&x(\"Duplicate sanitised parameter name \"+l,t),e.components.parameters[l]=e.components.parameters[a],delete e.components.parameters[a]),A(e.components.parameters[l],null,0,l,e,t)}for(var s in e.components.responses){var l;s!=(l=y.sanitise(s))&&(e.components.responses[l]&&x(\"Duplicate sanitised response name \"+l,t),e.components.responses[l]=e.components.responses[s],delete e.components.responses[s]);var u=e.components.responses[l];if(I(u,l,null,e,t),u.headers)for(var p in u.headers)\"status code\"===p.toLowerCase()?t.patch?delete u.headers[p]:x('(Patchable) \"Status Code\" is not a valid header',t):T(u.headers[p],t)}for(var s in e.components.requestBodies){var d=e.components.requestBodies[s],m=JSON.stringify(d),g=y.hash(m);(k={}).name=s,k.body=d,k.refs=[],n[g]=k}if(P(e.paths,\"paths\",t,n,e),e[\"x-ms-paths\"]&&P(e[\"x-ms-paths\"],\"x-ms-paths\",t,n,e),!t.debug)for(var a in e.components.parameters){e.components.parameters[a][\"x-s2o-delete\"]&&delete e.components.parameters[a]}t.debug&&(e[\"x-s2o-consumes\"]=e.consumes||[],e[\"x-s2o-produces\"]=e.produces||[]),delete e.consumes,delete e.produces,delete e.schemes;var v=[];e.components.requestBodies={};var b=1;for(var w in n){var k;if((k=n[w]).refs.length>1){i=\"\";for(k.name||(k.name=\"requestBody\",i=b++);v.indexOf(k.name+i)>=0;)i=i?++i:2;for(var s in k.name=k.name+i,v.push(k.name),e.components.requestBodies[k.name]=f(k.body),k.refs){var C={};C.$ref=\"#/components/requestBodies/\"+k.name,c.jptr(e,k.refs[s],C)}}}return e.components.responses&&0===Object.keys(e.components.responses).length&&delete e.components.responses,e.components.parameters&&0===Object.keys(e.components.parameters).length&&delete e.components.parameters,e.components.examples&&0===Object.keys(e.components.examples).length&&delete e.components.examples,e.components.requestBodies&&0===Object.keys(e.components.requestBodies).length&&delete e.components.requestBodies,e.components.securitySchemes&&0===Object.keys(e.components.securitySchemes).length&&delete e.components.securitySchemes,e.components.headers&&0===Object.keys(e.components.headers).length&&delete e.components.headers,e.components.schemas&&0===Object.keys(e.components.schemas).length&&delete e.components.schemas,e.components&&0===Object.keys(e.components).length&&delete e.components,e}function N(e){e.url=e.url.split(\"{{\").join(\"{\"),e.url=e.url.split(\"}}\").join(\"}\"),e.url.replace(/\\{(.+?)\\}/g,function(t,n){e.variables||(e.variables={}),e.variables[n]={default:\"unknown\"}})}function L(e,t,n){if(void 0===e.info||null===e.info){if(!t.patch)return n(new Error(\"(Patchable) info object is mandatory\"));e.info={version:\"\",title:\"\"}}if(\"object\"!=typeof e.info||Array.isArray(e.info))return n(new Error(\"info must be an object\"));if(void 0===e.info.title||null===e.info.title){if(!t.patch)return n(new Error(\"(Patchable) info.title cannot be null\"));e.info.title=\"\"}if(void 0===e.info.version||null===e.info.version){if(!t.patch)return n(new Error(\"(Patchable) info.version cannot be null\"));e.info.version=\"\"}if(\"string\"!=typeof e.info.version){if(!t.patch)return n(new Error(\"(Patchable) info.version must be a string\"));e.info.version=e.info.version.toString()}if(void 0!==e.info.logo){if(!t.patch)return n(new Error(\"(Patchable) info should not have logo property\"));e.info[\"x-logo\"]=e.info.logo,delete e.info.logo}if(void 0!==e.info.termsOfService){if(null===e.info.termsOfService){if(!t.patch)return n(new Error(\"(Patchable) info.termsOfService cannot be null\"));e.info.termsOfService=\"\"}if(i.URL&&t.whatwg)try{i.URL.parse(e.info.termsOfService)}catch(r){if(!t.patch)return n(new Error(\"(Patchable) info.termsOfService must be a URL\"));delete e.info.termsOfService}}}function M(e,t,n){if(void 0===e.paths){if(!t.patch)return n(new Error(\"(Patchable) paths object is mandatory\"));e.paths={}}}function D(e,t,n){return a(n,new Promise(function(n,r){if(t.externals=[],t.externalRefs={},t.rewriteRefs=!0,t.preserveMiro=!0,t.promise={},t.promise.resolve=n,t.promise.reject=r,t.cache||(t.cache={}),e.openapi&&\"string\"==typeof e.openapi&&e.openapi.startsWith(\"3.\"))return t.openapi=d(e),L(t.openapi,t,r),M(t.openapi,t,r),void m.optionalResolve(t).then(function(){return t.direct?n(t.openapi):n(t)}).catch(function(e){console.warn(e),r(e)});if(!e.swagger||\"2.0\"!=e.swagger)return r(new Error(\"Unsupported swagger/OpenAPI version: \"+(e.openapi?e.openapi:e.swagger)));var o=t.openapi={};if(o.openapi=w,t.origin){o[\"x-origin\"]||(o[\"x-origin\"]=[]);var i={};i.url=t.source||t.origin,i.format=\"swagger\",i.version=e.swagger,i.converter={},i.converter.url=\"https://github.com/mermade/oas-kit\",i.converter.version=b,o[\"x-origin\"].push(i)}if(delete(o=Object.assign(o,d(e))).swagger,e.host)for(var a=0,s=e.schemes||[\"\"];a<s.length;a++){var l=s[a];(p={}).url=(l?l+\":\":\"\")+\"//\"+e.host+(e.basePath?e.basePath:\"\"),N(p),o.servers||(o.servers=[]),o.servers.push(p)}else if(e.basePath){(p={}).url=e.basePath,N(p),o.servers||(o.servers=[]),o.servers.push(p)}if(delete o.host,delete o.basePath,o[\"x-servers\"]&&Array.isArray(o[\"x-servers\"])&&(o.servers=o[\"x-servers\"],delete o[\"x-servers\"]),e[\"x-ms-parameterized-host\"]){var c=e[\"x-ms-parameterized-host\"],p={};for(var h in p.url=c.hostTemplate,p.variables={},c.parameters){var g=c.parameters[h];g.$ref&&(g=f(u(o,g.$ref))),h.startsWith(\"x-\")||(delete g.required,delete g.type,delete g.in,void 0===g.default&&(g.enum?g.default=g.enum[0]:g.default=\"\"),p.variables[g.name]=g,delete g.name)}o.servers||(o.servers=[]),o.servers.push(p),delete o[\"x-ms-parameterized-host\"]}L(o,t,r),M(o,t,r),o.components={},o[\"x-callbacks\"]&&(o.components.callbacks=o[\"x-callbacks\"],delete o[\"x-callbacks\"]),o.components.examples={},o.components.headers={},o[\"x-links\"]&&(o.components.links=o[\"x-links\"],delete o[\"x-links\"]),o.components.parameters=o.parameters||{},o.components.responses=o.responses||{},o.components.requestBodies={},o.components.securitySchemes=o.securityDefinitions||{},o.components.schemas=o.definitions||{},delete o.definitions,delete o.responses,delete o.parameters,delete o.securityDefinitions,m.optionalResolve(t).then(function(){R(o,t),t.direct?n(t.openapi):n(t)}).catch(function(e){console.warn(e),r(e)})}))}function F(e,t,n){return a(n,new Promise(function(n,r){var o=null;try{o=JSON.parse(e)}catch(n){try{o=l.safeLoad(e,{json:!0}),t.sourceYaml=!0}catch(e){}}o?(t.original=o,D(o,t).then(function(e){return n(e)}).catch(function(e){return r(e)})):r(new Error(\"Could not parse string\"))}))}e.exports={targetVersion:w,convert:D,convertObj:D,convertUrl:function(e,t,n){return a(n,new Promise(function(n,r){t.origin=!0,t.source||(t.source=e),t.verbose&&console.log(\"GET \"+e),s(e,{agent:t.agent}).then(function(e){if(200!==e.status)throw new Error(\"Received status code \"+e.status);return e.text()}).then(function(e){F(e,t).then(function(e){return n(e)}).catch(function(e){return r(e)})}).catch(function(e){r(e)})}))},convertStr:F,convertFile:function(e,t,n){return a(n,new Promise(function(n,r){o.readFile(e,t.encoding||\"utf8\",function(o,i){o?r(o):(t.sourceFile=e,F(i,t).then(function(e){return n(e)}).catch(function(e){return r(e)}))})}))},convertStream:function(e,t,n){return a(n,new Promise(function(n,r){var o=\"\";e.on(\"data\",function(e){o+=e}).on(\"end\",function(){F(o,t).then(function(e){return n(e)}).catch(function(e){return r(e)})})}))}}},function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),o=n(0),i=l(o),a=l(n(13)),s=l(n(12));function l(e){return e&&e.__esModule?e:{default:e}}function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var u=\"Select...\",p=function(e){function t(e){!function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!t||\"object\"!=typeof t&&\"function\"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.state={selected:n.parseValue(e.value,e.options)||{label:void 0===e.placeholder?u:e.placeholder,value:\"\"},isOpen:!1},n.mounted=!0,n.handleDocumentClick=n.handleDocumentClick.bind(n),n.fireChangeEvent=n.fireChangeEvent.bind(n),n}return function(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,o.Component),r(t,[{key:\"componentWillReceiveProps\",value:function(e){if(e.value){var t=this.parseValue(e.value,e.options);t!==this.state.selected&&this.setState({selected:t})}else this.setState({selected:{label:void 0===e.placeholder?u:e.placeholder,value:\"\"}})}},{key:\"componentDidMount\",value:function(){document.addEventListener(\"click\",this.handleDocumentClick,!1),document.addEventListener(\"touchend\",this.handleDocumentClick,!1)}},{key:\"componentWillUnmount\",value:function(){this.mounted=!1,document.removeEventListener(\"click\",this.handleDocumentClick,!1),document.removeEventListener(\"touchend\",this.handleDocumentClick,!1)}},{key:\"handleMouseDown\",value:function(e){this.props.onFocus&&\"function\"==typeof this.props.onFocus&&this.props.onFocus(this.state.isOpen),\"mousedown\"===e.type&&0!==e.button||(e.stopPropagation(),e.preventDefault(),this.props.disabled||this.setState({isOpen:!this.state.isOpen}))}},{key:\"parseValue\",value:function(e,t){var n=void 0;if(\"string\"==typeof e)for(var r=0,o=t.length;r<o;r++)if(\"group\"===t[r].type){var i=t[r].items.filter(function(t){return t.value===e});i.length&&(n=i[0])}else void 0!==t[r].value&&t[r].value===e&&(n=t[r]);return n||e}},{key:\"setValue\",value:function(e,t){var n={selected:{value:e,label:t},isOpen:!1};this.fireChangeEvent(n),this.setState(n)}},{key:\"fireChangeEvent\",value:function(e){e.selected!==this.state.selected&&this.props.onChange&&this.props.onChange(e.selected)}},{key:\"renderOption\",value:function(e){var t,n=e.value;void 0===n&&(n=e.label||e);var r=e.label||e.value||e,o=(c(t={},this.props.baseClassName+\"-option\",!0),c(t,e.className,!!e.className),c(t,\"is-selected\",n===this.state.selected.value||n===this.state.selected),t),a=(0,s.default)(o);return i.default.createElement(\"div\",{key:n,className:a,onMouseDown:this.setValue.bind(this,n,r),onClick:this.setValue.bind(this,n,r)},r)}},{key:\"buildMenu\",value:function(){var e=this,t=this.props,n=t.options,r=t.baseClassName,o=n.map(function(t){if(\"group\"===t.type){var n=i.default.createElement(\"div\",{className:r+\"-title\"},t.name),o=t.items.map(function(t){return e.renderOption(t)});return i.default.createElement(\"div\",{className:r+\"-group\",key:t.name},n,o)}return e.renderOption(t)});return o.length?o:i.default.createElement(\"div\",{className:r+\"-noresults\"},\"No options found\")}},{key:\"handleDocumentClick\",value:function(e){this.mounted&&(a.default.findDOMNode(this).contains(e.target)||this.state.isOpen&&this.setState({isOpen:!1}))}},{key:\"isValueSelected\",value:function(){return\"string\"==typeof this.state.selected||\"\"!==this.state.selected.value}},{key:\"render\",value:function(){var e,t,n,r,o,a=this.props,l=a.baseClassName,u=a.controlClassName,p=a.placeholderClassName,f=a.menuClassName,d=a.arrowClassName,h=a.arrowClosed,m=a.arrowOpen,g=a.className,y=this.props.disabled?\"Dropdown-disabled\":\"\",v=\"string\"==typeof this.state.selected?this.state.selected:this.state.selected.label,b=(0,s.default)((c(e={},l+\"-root\",!0),c(e,g,!!g),c(e,\"is-open\",this.state.isOpen),e)),w=(0,s.default)((c(t={},l+\"-control\",!0),c(t,u,!!u),c(t,y,!!y),t)),x=(0,s.default)((c(n={},l+\"-placeholder\",!0),c(n,p,!!p),c(n,\"is-selected\",this.isValueSelected()),n)),k=(0,s.default)((c(r={},l+\"-menu\",!0),c(r,f,!!f),r)),E=(0,s.default)((c(o={},l+\"-arrow\",!0),c(o,d,!!d),o)),S=i.default.createElement(\"div\",{className:x},v),_=this.state.isOpen?i.default.createElement(\"div\",{className:k},this.buildMenu()):null;return i.default.createElement(\"div\",{className:b},i.default.createElement(\"div\",{className:w,onMouseDown:this.handleMouseDown.bind(this),onTouchEnd:this.handleMouseDown.bind(this)},S,i.default.createElement(\"div\",{className:l+\"-arrow-wrapper\"},m&&h?this.state.isOpen?m:h:i.default.createElement(\"span\",{className:E}))),_)}}]),t}();p.defaultProps={baseClassName:\"Dropdown\"},t.default=p},function(e,t,n){e.exports=function(){\"use strict\";var e=[\"a\",\"abbr\",\"acronym\",\"address\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"bdi\",\"bdo\",\"big\",\"blink\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"center\",\"cite\",\"code\",\"col\",\"colgroup\",\"content\",\"data\",\"datalist\",\"dd\",\"decorator\",\"del\",\"details\",\"dfn\",\"dir\",\"div\",\"dl\",\"dt\",\"element\",\"em\",\"fieldset\",\"figcaption\",\"figure\",\"font\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"img\",\"input\",\"ins\",\"kbd\",\"label\",\"legend\",\"li\",\"main\",\"map\",\"mark\",\"marquee\",\"menu\",\"menuitem\",\"meter\",\"nav\",\"nobr\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"section\",\"select\",\"shadow\",\"small\",\"source\",\"spacer\",\"span\",\"strike\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"template\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"tr\",\"track\",\"tt\",\"u\",\"ul\",\"var\",\"video\",\"wbr\"],t=[\"svg\",\"a\",\"altglyph\",\"altglyphdef\",\"altglyphitem\",\"animatecolor\",\"animatemotion\",\"animatetransform\",\"audio\",\"canvas\",\"circle\",\"clippath\",\"defs\",\"desc\",\"ellipse\",\"filter\",\"font\",\"g\",\"glyph\",\"glyphref\",\"hkern\",\"image\",\"line\",\"lineargradient\",\"marker\",\"mask\",\"metadata\",\"mpath\",\"path\",\"pattern\",\"polygon\",\"polyline\",\"radialgradient\",\"rect\",\"stop\",\"style\",\"switch\",\"symbol\",\"text\",\"textpath\",\"title\",\"tref\",\"tspan\",\"video\",\"view\",\"vkern\"],n=[\"feBlend\",\"feColorMatrix\",\"feComponentTransfer\",\"feComposite\",\"feConvolveMatrix\",\"feDiffuseLighting\",\"feDisplacementMap\",\"feDistantLight\",\"feFlood\",\"feFuncA\",\"feFuncB\",\"feFuncG\",\"feFuncR\",\"feGaussianBlur\",\"feMerge\",\"feMergeNode\",\"feMorphology\",\"feOffset\",\"fePointLight\",\"feSpecularLighting\",\"feSpotLight\",\"feTile\",\"feTurbulence\"],r=[\"math\",\"menclose\",\"merror\",\"mfenced\",\"mfrac\",\"mglyph\",\"mi\",\"mlabeledtr\",\"mmuliscripts\",\"mn\",\"mo\",\"mover\",\"mpadded\",\"mphantom\",\"mroot\",\"mrow\",\"ms\",\"mpspace\",\"msqrt\",\"mystyle\",\"msub\",\"msup\",\"msubsup\",\"mtable\",\"mtd\",\"mtext\",\"mtr\",\"munder\",\"munderover\"],o=[\"#text\"],i=[\"accept\",\"action\",\"align\",\"alt\",\"autocomplete\",\"background\",\"bgcolor\",\"border\",\"cellpadding\",\"cellspacing\",\"checked\",\"cite\",\"class\",\"clear\",\"color\",\"cols\",\"colspan\",\"coords\",\"crossorigin\",\"datetime\",\"default\",\"dir\",\"disabled\",\"download\",\"enctype\",\"face\",\"for\",\"headers\",\"height\",\"hidden\",\"high\",\"href\",\"hreflang\",\"id\",\"integrity\",\"ismap\",\"label\",\"lang\",\"list\",\"loop\",\"low\",\"max\",\"maxlength\",\"media\",\"method\",\"min\",\"multiple\",\"name\",\"noshade\",\"novalidate\",\"nowrap\",\"open\",\"optimum\",\"pattern\",\"placeholder\",\"poster\",\"preload\",\"pubdate\",\"radiogroup\",\"readonly\",\"rel\",\"required\",\"rev\",\"reversed\",\"role\",\"rows\",\"rowspan\",\"spellcheck\",\"scope\",\"selected\",\"shape\",\"size\",\"sizes\",\"span\",\"srclang\",\"start\",\"src\",\"srcset\",\"step\",\"style\",\"summary\",\"tabindex\",\"title\",\"type\",\"usemap\",\"valign\",\"value\",\"width\",\"xmlns\"],a=[\"accent-height\",\"accumulate\",\"additivive\",\"alignment-baseline\",\"ascent\",\"attributename\",\"attributetype\",\"azimuth\",\"basefrequency\",\"baseline-shift\",\"begin\",\"bias\",\"by\",\"class\",\"clip\",\"clip-path\",\"clip-rule\",\"color\",\"color-interpolation\",\"color-interpolation-filters\",\"color-profile\",\"color-rendering\",\"cx\",\"cy\",\"d\",\"dx\",\"dy\",\"diffuseconstant\",\"direction\",\"display\",\"divisor\",\"dur\",\"edgemode\",\"elevation\",\"end\",\"fill\",\"fill-opacity\",\"fill-rule\",\"filter\",\"flood-color\",\"flood-opacity\",\"font-family\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\"font-style\",\"font-variant\",\"font-weight\",\"fx\",\"fy\",\"g1\",\"g2\",\"glyph-name\",\"glyphref\",\"gradientunits\",\"gradienttransform\",\"height\",\"href\",\"id\",\"image-rendering\",\"in\",\"in2\",\"k\",\"k1\",\"k2\",\"k3\",\"k4\",\"kerning\",\"keypoints\",\"keysplines\",\"keytimes\",\"lang\",\"lengthadjust\",\"letter-spacing\",\"kernelmatrix\",\"kernelunitlength\",\"lighting-color\",\"local\",\"marker-end\",\"marker-mid\",\"marker-start\",\"markerheight\",\"markerunits\",\"markerwidth\",\"maskcontentunits\",\"maskunits\",\"max\",\"mask\",\"media\",\"method\",\"mode\",\"min\",\"name\",\"numoctaves\",\"offset\",\"operator\",\"opacity\",\"order\",\"orient\",\"orientation\",\"origin\",\"overflow\",\"paint-order\",\"path\",\"pathlength\",\"patterncontentunits\",\"patterntransform\",\"patternunits\",\"points\",\"preservealpha\",\"preserveaspectratio\",\"r\",\"rx\",\"ry\",\"radius\",\"refx\",\"refy\",\"repeatcount\",\"repeatdur\",\"restart\",\"result\",\"rotate\",\"scale\",\"seed\",\"shape-rendering\",\"specularconstant\",\"specularexponent\",\"spreadmethod\",\"stddeviation\",\"stitchtiles\",\"stop-color\",\"stop-opacity\",\"stroke-dasharray\",\"stroke-dashoffset\",\"stroke-linecap\",\"stroke-linejoin\",\"stroke-miterlimit\",\"stroke-opacity\",\"stroke\",\"stroke-width\",\"style\",\"surfacescale\",\"tabindex\",\"targetx\",\"targety\",\"transform\",\"text-anchor\",\"text-decoration\",\"text-rendering\",\"textlength\",\"type\",\"u1\",\"u2\",\"unicode\",\"values\",\"viewbox\",\"visibility\",\"vert-adv-y\",\"vert-origin-x\",\"vert-origin-y\",\"width\",\"word-spacing\",\"wrap\",\"writing-mode\",\"xchannelselector\",\"ychannelselector\",\"x\",\"x1\",\"x2\",\"xmlns\",\"y\",\"y1\",\"y2\",\"z\",\"zoomandpan\"],s=[\"accent\",\"accentunder\",\"align\",\"bevelled\",\"close\",\"columnsalign\",\"columnlines\",\"columnspan\",\"denomalign\",\"depth\",\"dir\",\"display\",\"displaystyle\",\"fence\",\"frame\",\"height\",\"href\",\"id\",\"largeop\",\"length\",\"linethickness\",\"lspace\",\"lquote\",\"mathbackground\",\"mathcolor\",\"mathsize\",\"mathvariant\",\"maxsize\",\"minsize\",\"movablelimits\",\"notation\",\"numalign\",\"open\",\"rowalign\",\"rowlines\",\"rowspacing\",\"rowspan\",\"rspace\",\"rquote\",\"scriptlevel\",\"scriptminsize\",\"scriptsizemultiplier\",\"selection\",\"separator\",\"separators\",\"stretchy\",\"subscriptshift\",\"supscriptshift\",\"symmetric\",\"voffset\",\"width\",\"xmlns\"],l=[\"xlink:href\",\"xml:id\",\"xlink:title\",\"xml:space\",\"xmlns:xlink\"];function c(e,t){for(var n=t.length;n--;)\"string\"==typeof t[n]&&(t[n]=t[n].toLowerCase()),e[t[n]]=!0;return e}function u(e){var t={},n=void 0;for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t}var p=/\\{\\{[\\s\\S]*|[\\s\\S]*\\}\\}/gm,f=/<%[\\s\\S]*|[\\s\\S]*%>/gm,d=/^data-[\\-\\w.\\u00B7-\\uFFFF]/,h=/^aria-[\\-\\w]+$/,m=/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i,g=/^(?:\\w+script|data):/i,y=/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205f\\u3000]/g,v=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e};function b(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}var w=function(){return\"undefined\"==typeof window?null:window};return function x(){var k=arguments.length>0&&void 0!==arguments[0]?arguments[0]:w(),E=function(e){return x(e)};if(E.version=\"1.0.8\",E.removed=[],!k||!k.document||9!==k.document.nodeType)return E.isSupported=!1,E;var S=k.document,_=!1,O=!1,C=k.document,T=k.DocumentFragment,j=k.HTMLTemplateElement,A=k.Node,I=k.NodeFilter,P=k.NamedNodeMap,R=void 0===P?k.NamedNodeMap||k.MozNamedAttrMap:P,N=k.Text,L=k.Comment,M=k.DOMParser;if(\"function\"==typeof j){var D=C.createElement(\"template\");D.content&&D.content.ownerDocument&&(C=D.content.ownerDocument)}var F=C,U=F.implementation,B=F.createNodeIterator,z=F.getElementsByTagName,$=F.createDocumentFragment,W=S.importNode,q={};E.isSupported=U&&void 0!==U.createHTMLDocument&&9!==C.documentMode;var H=p,Y=f,V=d,Q=h,G=g,X=y,K=m,J=null,Z=c({},[].concat(b(e),b(t),b(n),b(r),b(o))),ee=null,te=c({},[].concat(b(i),b(a),b(s),b(l))),ne=null,re=null,oe=!0,ie=!0,ae=!1,se=!1,le=!1,ce=!1,ue=!1,pe=!1,fe=!1,de=!1,he=!1,me=!0,ge=!0,ye=!1,ve={},be=c({},[\"audio\",\"head\",\"math\",\"script\",\"style\",\"template\",\"svg\",\"video\"]),we=c({},[\"audio\",\"video\",\"img\",\"source\",\"image\"]),xe=c({},[\"alt\",\"class\",\"for\",\"id\",\"label\",\"name\",\"pattern\",\"placeholder\",\"summary\",\"title\",\"value\",\"style\",\"xmlns\"]),ke=null,Ee=C.createElement(\"form\"),Se=function(p){\"object\"!==(void 0===p?\"undefined\":v(p))&&(p={}),J=\"ALLOWED_TAGS\"in p?c({},p.ALLOWED_TAGS):Z,ee=\"ALLOWED_ATTR\"in p?c({},p.ALLOWED_ATTR):te,ne=\"FORBID_TAGS\"in p?c({},p.FORBID_TAGS):{},re=\"FORBID_ATTR\"in p?c({},p.FORBID_ATTR):{},ve=\"USE_PROFILES\"in p&&p.USE_PROFILES,oe=!1!==p.ALLOW_ARIA_ATTR,ie=!1!==p.ALLOW_DATA_ATTR,ae=p.ALLOW_UNKNOWN_PROTOCOLS||!1,se=p.SAFE_FOR_JQUERY||!1,le=p.SAFE_FOR_TEMPLATES||!1,ce=p.WHOLE_DOCUMENT||!1,fe=p.RETURN_DOM||!1,de=p.RETURN_DOM_FRAGMENT||!1,he=p.RETURN_DOM_IMPORT||!1,pe=p.FORCE_BODY||!1,me=!1!==p.SANITIZE_DOM,ge=!1!==p.KEEP_CONTENT,ye=p.IN_PLACE||!1,K=p.ALLOWED_URI_REGEXP||K,le&&(ie=!1),de&&(fe=!0),ve&&(J=c({},[].concat(b(o))),ee=[],!0===ve.html&&(c(J,e),c(ee,i)),!0===ve.svg&&(c(J,t),c(ee,a),c(ee,l)),!0===ve.svgFilters&&(c(J,n),c(ee,a),c(ee,l)),!0===ve.mathMl&&(c(J,r),c(ee,s),c(ee,l))),p.ADD_TAGS&&(J===Z&&(J=u(J)),c(J,p.ADD_TAGS)),p.ADD_ATTR&&(ee===te&&(ee=u(ee)),c(ee,p.ADD_ATTR)),p.ADD_URI_SAFE_ATTR&&c(xe,p.ADD_URI_SAFE_ATTR),ge&&(J[\"#text\"]=!0),ce&&c(J,[\"html\",\"head\",\"body\"]),J.table&&c(J,[\"tbody\"]),Object&&\"freeze\"in Object&&Object.freeze(p),ke=p},_e=function(e){E.removed.push({element:e});try{e.parentNode.removeChild(e)}catch(t){e.outerHTML=\"\"}},Oe=function(e,t){try{E.removed.push({attribute:t.getAttributeNode(e),from:t})}catch(e){E.removed.push({attribute:null,from:t})}t.removeAttribute(e)},Ce=function(e){var t=void 0;if(pe&&(e=\"<remove></remove>\"+e),_)try{t=(new M).parseFromString(e,\"text/html\")}catch(e){}if(O&&c(ne,[\"title\"]),!t||!t.documentElement){var n=t=U.createHTMLDocument(\"\"),r=n.body;r.parentNode.removeChild(r.parentNode.firstElementChild),r.outerHTML=e}return z.call(t,ce?\"html\":\"body\")[0]};E.isSupported&&(function(){try{var e=Ce('<svg><p><style><img src=\"</style><img src=x onerror=alert(1)//\">');e.querySelector(\"svg img\")&&(_=!0)}catch(e){}}(),function(){try{var e=Ce(\"<x/><title>&lt;/title&gt;&lt;img&gt;\");e.querySelector(\"title\").textContent.match(/<\\/title/)&&(O=!0)}catch(e){}}());var Te=function(e){return B.call(e.ownerDocument||e,e,I.SHOW_ELEMENT|I.SHOW_COMMENT|I.SHOW_TEXT,function(){return I.FILTER_ACCEPT},!1)},je=function(e){return\"object\"===(void 0===A?\"undefined\":v(A))?e instanceof A:e&&\"object\"===(void 0===e?\"undefined\":v(e))&&\"number\"==typeof e.nodeType&&\"string\"==typeof e.nodeName},Ae=function(e,t,n){q[e]&&q[e].forEach(function(e){e.call(E,t,n,ke)})},Ie=function(e){var t,n=void 0;if(Ae(\"beforeSanitizeElements\",e,null),!((t=e)instanceof N||t instanceof L||\"string\"==typeof t.nodeName&&\"string\"==typeof t.textContent&&\"function\"==typeof t.removeChild&&t.attributes instanceof R&&\"function\"==typeof t.removeAttribute&&\"function\"==typeof t.setAttribute))return _e(e),!0;var r=e.nodeName.toLowerCase();if(Ae(\"uponSanitizeElement\",e,{tagName:r,allowedTags:J}),!J[r]||ne[r]){if(ge&&!be[r]&&\"function\"==typeof e.insertAdjacentHTML)try{e.insertAdjacentHTML(\"AfterEnd\",e.innerHTML)}catch(e){}return _e(e),!0}return!se||e.firstElementChild||e.content&&e.content.firstElementChild||!/</g.test(e.textContent)||(E.removed.push({element:e.cloneNode()}),e.innerHTML?e.innerHTML=e.innerHTML.replace(/</g,\"&lt;\"):e.innerHTML=e.textContent.replace(/</g,\"&lt;\")),le&&3===e.nodeType&&(n=(n=(n=e.textContent).replace(H,\" \")).replace(Y,\" \"),e.textContent!==n&&(E.removed.push({element:e.cloneNode()}),e.textContent=n)),Ae(\"afterSanitizeElements\",e,null),!1},Pe=function(e,t,n){if(me&&(\"id\"===t||\"name\"===t)&&(n in C||n in Ee))return!1;if(le&&(n=(n=n.replace(H,\" \")).replace(Y,\" \")),ie&&V.test(t));else if(oe&&Q.test(t));else{if(!ee[t]||re[t])return!1;if(xe[t]);else if(K.test(n.replace(X,\"\")));else if(\"src\"!==t&&\"xlink:href\"!==t||\"script\"===e||0!==n.indexOf(\"data:\")||!we[e])if(ae&&!G.test(n.replace(X,\"\")));else if(n)return!1}return!0},Re=function(e){var t=void 0,n=void 0,r=void 0,o=void 0,i=void 0;Ae(\"beforeSanitizeAttributes\",e,null);var a=e.attributes;if(a){var s={attrName:\"\",attrValue:\"\",keepAttr:!0,allowedAttributes:ee};for(i=a.length;i--;){var l=t=a[i],c=l.name,u=l.namespaceURI;if(n=t.value.trim(),r=c.toLowerCase(),s.attrName=r,s.attrValue=n,s.keepAttr=!0,Ae(\"uponSanitizeAttribute\",e,s),n=s.attrValue,\"name\"===r&&\"IMG\"===e.nodeName&&a.id)o=a.id,a=Array.prototype.slice.apply(a),Oe(\"id\",e),Oe(c,e),a.indexOf(o)>i&&e.setAttribute(\"id\",o.value);else{if(\"INPUT\"===e.nodeName&&\"type\"===r&&\"file\"===n&&(ee[r]||!re[r]))continue;\"id\"===c&&e.setAttribute(c,\"\"),Oe(c,e)}if(s.keepAttr){var p=e.nodeName.toLowerCase();if(Pe(p,r,n))try{u?e.setAttributeNS(u,c,n):e.setAttribute(c,n),E.removed.pop()}catch(e){}}}Ae(\"afterSanitizeAttributes\",e,null)}},Ne=function e(t){var n=void 0,r=Te(t);for(Ae(\"beforeSanitizeShadowDOM\",t,null);n=r.nextNode();)Ae(\"uponSanitizeShadowNode\",n,null),Ie(n)||(n.content instanceof T&&e(n.content),Re(n));Ae(\"afterSanitizeShadowDOM\",t,null)};return E.sanitize=function(e,t){var n=void 0,r=void 0,o=void 0,i=void 0,a=void 0;if(e||(e=\"\\x3c!--\\x3e\"),\"string\"!=typeof e&&!je(e)){if(\"function\"!=typeof e.toString)throw new TypeError(\"toString is not a function\");if(\"string\"!=typeof(e=e.toString()))throw new TypeError(\"dirty is not a string, aborting\")}if(!E.isSupported){if(\"object\"===v(k.toStaticHTML)||\"function\"==typeof k.toStaticHTML){if(\"string\"==typeof e)return k.toStaticHTML(e);if(je(e))return k.toStaticHTML(e.outerHTML)}return e}if(ue||Se(t),E.removed=[],ye);else if(e instanceof A)n=Ce(\"\\x3c!--\\x3e\"),1===(r=n.ownerDocument.importNode(e,!0)).nodeType&&\"BODY\"===r.nodeName?n=r:n.appendChild(r);else{if(!fe&&!ce&&-1===e.indexOf(\"<\"))return e;if(!(n=Ce(e)))return fe?null:\"\"}n&&pe&&_e(n.firstChild);for(var s=Te(ye?e:n);o=s.nextNode();)3===o.nodeType&&o===i||Ie(o)||(o.content instanceof T&&Ne(o.content),Re(o),i=o);if(ye)return e;if(fe){if(de)for(a=$.call(n.ownerDocument);n.firstChild;)a.appendChild(n.firstChild);else a=n;return he&&(a=W.call(S,a,!0)),a}return ce?n.outerHTML:n.innerHTML},E.setConfig=function(e){Se(e),ue=!0},E.clearConfig=function(){ke=null,ue=!1},E.isValidAttribute=function(e,t,n){ke||Se({});var r=e.toLowerCase(),o=t.toLowerCase();return Pe(r,o,n)},E.addHook=function(e,t){\"function\"==typeof t&&(q[e]=q[e]||[],q[e].push(t))},E.removeHook=function(e){q[e]&&q[e].pop()},E.removeHooks=function(e){q[e]&&(q[e]=[])},E.removeAllHooks=function(){q={}},E}()}()},function(e,t,n){\"use strict\";var r=/^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|default|defer|dir|disabled|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|itemProp|itemScope|itemType|itemID|itemRef|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class)|(on[A-Z].*)|((data|aria|x)-.*))$/i,o=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e(n)),t[n]}}(r.test.bind(r));t.a=o},function(e,t,n){n(135),e.exports=n(270)},function(e,t,n){\"use strict\";n.r(t);n(136),n(154),n(159),n(162),n(165),n(167),n(173)},function(e,t,n){n(56),n(83),n(86),n(144),e.exports=n(7).Promise},function(e,t,n){var r=n(61),o=n(43);e.exports=function(e){return function(t,n){var i,a,s=String(o(t)),l=r(n),c=s.length;return l<0||l>=c?e?\"\":void 0:(i=s.charCodeAt(l))<55296||i>56319||l+1===c||(a=s.charCodeAt(l+1))<56320||a>57343?e?s.charAt(l):i:e?s.slice(l,l+2):a-56320+(i-55296<<10)+65536}}},function(e,t,n){\"use strict\";var r=n(63),o=n(42),i=n(36),a={};n(22)(a,n(2)(\"iterator\"),function(){return this}),e.exports=function(e,t,n){e.prototype=r(a,{next:o(1,n)}),i(e,t+\" Iterator\")}},function(e,t,n){var r=n(16),o=n(14),i=n(34);e.exports=n(17)?Object.defineProperties:function(e,t){o(e);for(var n,a=i(t),s=a.length,l=0;s>l;)r.f(e,n=a[l++],t[n]);return e}},function(e,t,n){var r=n(28),o=n(35),i=n(141);e.exports=function(e){return function(t,n,a){var s,l=r(t),c=o(l.length),u=i(a,c);if(e&&n!=n){for(;c>u;)if((s=l[u++])!=s)return!0}else for(;c>u;u++)if((e||u in l)&&l[u]===n)return e||u||0;return!e&&-1}}},function(e,t,n){var r=n(61),o=Math.max,i=Math.min;e.exports=function(e,t){return(e=r(e))<0?o(e+t,0):i(e,t)}},function(e,t,n){var r=n(23),o=n(67),i=n(65)(\"IE_PROTO\"),a=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=o(e),r(e,i)?e[i]:\"function\"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?a:null}},function(e,t,n){\"use strict\";var r=n(87),o=n(88),i=n(33),a=n(28);e.exports=n(62)(Array,\"Array\",function(e,t){this._t=a(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,o(1)):o(0,\"keys\"==t?n:\"values\"==t?e[n]:[n,e[n]])},\"values\"),i.Arguments=i.Array,r(\"keys\"),r(\"values\"),r(\"entries\")},function(e,t,n){\"use strict\";var r,o,i,a,s=n(31),l=n(5),c=n(24),u=n(57),p=n(18),f=n(8),d=n(44),h=n(68),m=n(69),g=n(148),y=n(89).set,v=n(150)(),b=n(90),w=n(151),x=n(152),k=n(153),E=l.TypeError,S=l.process,_=S&&S.versions,O=_&&_.v8||\"\",C=l.Promise,T=\"process\"==u(S),j=function(){},A=o=b.f,I=!!function(){try{var e=C.resolve(1),t=(e.constructor={})[n(2)(\"species\")]=function(e){e(j,j)};return(T||\"function\"==typeof PromiseRejectionEvent)&&e.then(j)instanceof t&&0!==O.indexOf(\"6.6\")&&-1===x.indexOf(\"Chrome/66\")}catch(e){}}(),P=function(e){var t;return!(!f(e)||\"function\"!=typeof(t=e.then))&&t},R=function(e,t){if(!e._n){e._n=!0;var n=e._c;v(function(){for(var r=e._v,o=1==e._s,i=0,a=function(t){var n,i,a,s=o?t.ok:t.fail,l=t.resolve,c=t.reject,u=t.domain;try{s?(o||(2==e._h&&M(e),e._h=1),!0===s?n=r:(u&&u.enter(),n=s(r),u&&(u.exit(),a=!0)),n===t.promise?c(E(\"Promise-chain cycle\")):(i=P(n))?i.call(n,l,c):l(n)):c(r)}catch(e){u&&!a&&u.exit(),c(e)}};n.length>i;)a(n[i++]);e._c=[],e._n=!1,t&&!e._h&&N(e)})}},N=function(e){y.call(l,function(){var t,n,r,o=e._v,i=L(e);if(i&&(t=w(function(){T?S.emit(\"unhandledRejection\",o,e):(n=l.onunhandledrejection)?n({promise:e,reason:o}):(r=l.console)&&r.error&&r.error(\"Unhandled promise rejection\",o)}),e._h=T||L(e)?2:1),e._a=void 0,i&&t.e)throw t.v})},L=function(e){return 1!==e._h&&0===(e._a||e._c).length},M=function(e){y.call(l,function(){var t;T?S.emit(\"rejectionHandled\",e):(t=l.onrejectionhandled)&&t({promise:e,reason:e._v})})},D=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),R(t,!0))},F=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw E(\"Promise can't be resolved itself\");(t=P(e))?v(function(){var r={_w:n,_d:!1};try{t.call(e,c(F,r,1),c(D,r,1))}catch(e){D.call(r,e)}}):(n._v=e,n._s=1,R(n,!1))}catch(e){D.call({_w:n,_d:!1},e)}}};I||(C=function(e){h(this,C,\"Promise\",\"_h\"),d(e),r.call(this);try{e(c(F,this,1),c(D,this,1))}catch(e){D.call(this,e)}},(r=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=n(70)(C.prototype,{then:function(e,t){var n=A(g(this,C));return n.ok=\"function\"!=typeof e||e,n.fail=\"function\"==typeof t&&t,n.domain=T?S.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&R(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),i=function(){var e=new r;this.promise=e,this.resolve=c(F,e,1),this.reject=c(D,e,1)},b.f=A=function(e){return e===C||e===a?new i(e):o(e)}),p(p.G+p.W+p.F*!I,{Promise:C}),n(36)(C,\"Promise\"),n(91)(\"Promise\"),a=n(7).Promise,p(p.S+p.F*!I,\"Promise\",{reject:function(e){var t=A(this);return(0,t.reject)(e),t.promise}}),p(p.S+p.F*(s||!I),\"Promise\",{resolve:function(e){return k(s&&this===a?C:this,e)}}),p(p.S+p.F*!(I&&n(92)(function(e){C.all(e).catch(j)})),\"Promise\",{all:function(e){var t=this,n=A(t),r=n.resolve,o=n.reject,i=w(function(){var n=[],i=0,a=1;m(e,!1,function(e){var s=i++,l=!1;n.push(void 0),a++,t.resolve(e).then(function(e){l||(l=!0,n[s]=e,--a||r(n))},o)}),--a||r(n)});return i.e&&o(i.v),n.promise},race:function(e){var t=this,n=A(t),r=n.reject,o=w(function(){m(e,!1,function(e){t.resolve(e).then(n.resolve,r)})});return o.e&&r(o.v),n.promise}})},function(e,t,n){var r=n(14);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){var i=e.return;throw void 0!==i&&r(i.call(e)),t}}},function(e,t,n){var r=n(33),o=n(2)(\"iterator\"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(r.Array===e||i[o]===e)}},function(e,t,n){var r=n(57),o=n(2)(\"iterator\"),i=n(33);e.exports=n(7).getIteratorMethod=function(e){if(null!=e)return e[o]||e[\"@@iterator\"]||i[r(e)]}},function(e,t,n){var r=n(14),o=n(44),i=n(2)(\"species\");e.exports=function(e,t){var n,a=r(e).constructor;return void 0===a||null==(n=r(a)[i])?t:o(n)}},function(e,t){e.exports=function(e,t,n){var r=void 0===n;switch(t.length){case 0:return r?e():e.call(n);case 1:return r?e(t[0]):e.call(n,t[0]);case 2:return r?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return r?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return r?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}return e.apply(n,t)}},function(e,t,n){var r=n(5),o=n(89).set,i=r.MutationObserver||r.WebKitMutationObserver,a=r.process,s=r.Promise,l=\"process\"==n(26)(a);e.exports=function(){var e,t,n,c=function(){var r,o;for(l&&(r=a.domain)&&r.exit();e;){o=e.fn,e=e.next;try{o()}catch(r){throw e?n():t=void 0,r}}t=void 0,r&&r.enter()};if(l)n=function(){a.nextTick(c)};else if(!i||r.navigator&&r.navigator.standalone)if(s&&s.resolve){var u=s.resolve(void 0);n=function(){u.then(c)}}else n=function(){o.call(r,c)};else{var p=!0,f=document.createTextNode(\"\");new i(c).observe(f,{characterData:!0}),n=function(){f.data=p=!p}}return function(r){var o={fn:r,next:void 0};t&&(t.next=o),e||(e=o,n()),t=o}}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,n){var r=n(5).navigator;e.exports=r&&r.userAgent||\"\"},function(e,t,n){var r=n(14),o=n(8),i=n(90);e.exports=function(e,t){if(r(e),o(t)&&t.constructor===e)return t;var n=i.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){n(155),e.exports=n(7).Array.find},function(e,t,n){\"use strict\";var r=n(18),o=n(156)(5),i=!0;\"find\"in[]&&Array(1).find(function(){i=!1}),r(r.P+r.F*i,\"Array\",{find:function(e){return o(this,e,arguments.length>1?arguments[1]:void 0)}}),n(87)(\"find\")},function(e,t,n){var r=n(24),o=n(64),i=n(67),a=n(35),s=n(157);e.exports=function(e,t){var n=1==e,l=2==e,c=3==e,u=4==e,p=6==e,f=5==e||p,d=t||s;return function(t,s,h){for(var m,g,y=i(t),v=o(y),b=r(s,h,3),w=a(v.length),x=0,k=n?d(t,w):l?d(t,0):void 0;w>x;x++)if((f||x in v)&&(g=b(m=v[x],x,y),e))if(n)k[x]=g;else if(g)switch(e){case 3:return!0;case 5:return m;case 6:return x;case 2:k.push(m)}else if(u)return!1;return p?-1:c||u?u:k}}},function(e,t,n){var r=n(158);e.exports=function(e,t){return new(r(e))(t)}},function(e,t,n){var r=n(8),o=n(93),i=n(2)(\"species\");e.exports=function(e){var t;return o(e)&&(\"function\"!=typeof(t=e.constructor)||t!==Array&&!o(t.prototype)||(t=void 0),r(t)&&null===(t=t[i])&&(t=void 0)),void 0===t?Array:t}},function(e,t,n){n(160),e.exports=n(7).Object.assign},function(e,t,n){var r=n(18);r(r.S+r.F,\"Object\",{assign:n(161)})},function(e,t,n){\"use strict\";var r=n(34),o=n(71),i=n(45),a=n(67),s=n(64),l=Object.assign;e.exports=!l||n(27)(function(){var e={},t={},n=Symbol(),r=\"abcdefghijklmnopqrst\";return e[n]=7,r.split(\"\").forEach(function(e){t[e]=e}),7!=l({},e)[n]||Object.keys(l({},t)).join(\"\")!=r})?function(e,t){for(var n=a(e),l=arguments.length,c=1,u=o.f,p=i.f;l>c;)for(var f,d=s(arguments[c++]),h=u?r(d).concat(u(d)):r(d),m=h.length,g=0;m>g;)p.call(d,f=h[g++])&&(n[f]=d[f]);return n}:l},function(e,t,n){n(163),e.exports=n(7).String.endsWith},function(e,t,n){\"use strict\";var r=n(18),o=n(35),i=n(94),a=\"\".endsWith;r(r.P+r.F*n(95)(\"endsWith\"),\"String\",{endsWith:function(e){var t=i(this,e,\"endsWith\"),n=arguments.length>1?arguments[1]:void 0,r=o(t.length),s=void 0===n?r:Math.min(o(n),r),l=String(e);return a?a.call(t,l,s):t.slice(s-l.length,s)===l}})},function(e,t,n){var r=n(8),o=n(26),i=n(2)(\"match\");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[i])?!!t:\"RegExp\"==o(e))}},function(e,t,n){n(166),e.exports=n(7).String.startsWith},function(e,t,n){\"use strict\";var r=n(18),o=n(35),i=n(94),a=\"\".startsWith;r(r.P+r.F*n(95)(\"startsWith\"),\"String\",{startsWith:function(e){var t=i(this,e,\"startsWith\"),n=o(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),r=String(e);return a?a.call(t,r,n):t.slice(n,n+r.length)===r}})},function(e,t,n){n(56),n(83),n(86),n(168),e.exports=n(7).Map},function(e,t,n){\"use strict\";var r=n(169),o=n(96);e.exports=n(170)(\"Map\",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{get:function(e){var t=r.getEntry(o(this,\"Map\"),e);return t&&t.v},set:function(e,t){return r.def(o(this,\"Map\"),0===e?0:e,t)}},r,!0)},function(e,t,n){\"use strict\";var r=n(16).f,o=n(63),i=n(70),a=n(24),s=n(68),l=n(69),c=n(62),u=n(88),p=n(91),f=n(17),d=n(72).fastKey,h=n(96),m=f?\"_s\":\"size\",g=function(e,t){var n,r=d(t);if(\"F\"!==r)return e._i[r];for(n=e._f;n;n=n.n)if(n.k==t)return n};e.exports={getConstructor:function(e,t,n,c){var u=e(function(e,r){s(e,u,t,\"_i\"),e._t=t,e._i=o(null),e._f=void 0,e._l=void 0,e[m]=0,null!=r&&l(r,n,e[c],e)});return i(u.prototype,{clear:function(){for(var e=h(this,t),n=e._i,r=e._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete n[r.i];e._f=e._l=void 0,e[m]=0},delete:function(e){var n=h(this,t),r=g(n,e);if(r){var o=r.n,i=r.p;delete n._i[r.i],r.r=!0,i&&(i.n=o),o&&(o.p=i),n._f==r&&(n._f=o),n._l==r&&(n._l=i),n[m]--}return!!r},forEach:function(e){h(this,t);for(var n,r=a(e,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(r(n.v,n.k,this);n&&n.r;)n=n.p},has:function(e){return!!g(h(this,t),e)}}),f&&r(u.prototype,\"size\",{get:function(){return h(this,t)[m]}}),u},def:function(e,t,n){var r,o,i=g(e,t);return i?i.v=n:(e._l=i={i:o=d(t,!0),k:t,v:n,p:r=e._l,n:void 0,r:!1},e._f||(e._f=i),r&&(r.n=i),e[m]++,\"F\"!==o&&(e._i[o]=i)),e},getEntry:g,setStrong:function(e,t,n){c(e,t,function(e,n){this._t=h(e,t),this._k=n,this._l=void 0},function(){for(var e=this._k,t=this._l;t&&t.r;)t=t.p;return this._t&&(this._l=t=t?t.n:this._t._f)?u(0,\"keys\"==e?t.k:\"values\"==e?t.v:[t.k,t.v]):(this._t=void 0,u(1))},n?\"entries\":\"values\",!n,!0),p(t)}}},function(e,t,n){\"use strict\";var r=n(5),o=n(18),i=n(21),a=n(70),s=n(72),l=n(69),c=n(68),u=n(8),p=n(27),f=n(92),d=n(36),h=n(171);e.exports=function(e,t,n,m,g,y){var v=r[e],b=v,w=g?\"set\":\"add\",x=b&&b.prototype,k={},E=function(e){var t=x[e];i(x,e,\"delete\"==e?function(e){return!(y&&!u(e))&&t.call(this,0===e?0:e)}:\"has\"==e?function(e){return!(y&&!u(e))&&t.call(this,0===e?0:e)}:\"get\"==e?function(e){return y&&!u(e)?void 0:t.call(this,0===e?0:e)}:\"add\"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,n){return t.call(this,0===e?0:e,n),this})};if(\"function\"==typeof b&&(y||x.forEach&&!p(function(){(new b).entries().next()}))){var S=new b,_=S[w](y?{}:-0,1)!=S,O=p(function(){S.has(1)}),C=f(function(e){new b(e)}),T=!y&&p(function(){for(var e=new b,t=5;t--;)e[w](t,t);return!e.has(-0)});C||((b=t(function(t,n){c(t,b,e);var r=h(new v,t,b);return null!=n&&l(n,g,r[w],r),r})).prototype=x,x.constructor=b),(O||T)&&(E(\"delete\"),E(\"has\"),g&&E(\"get\")),(T||_)&&E(w),y&&x.clear&&delete x.clear}else b=m.getConstructor(t,e,g,w),a(b.prototype,n),s.NEED=!0;return d(b,e),k[e]=b,o(o.G+o.W+o.F*(b!=v),k),y||m.setStrong(b,e,g),b}},function(e,t,n){var r=n(8),o=n(172).set;e.exports=function(e,t,n){var i,a=t.constructor;return a!==n&&\"function\"==typeof a&&(i=a.prototype)!==n.prototype&&r(i)&&o&&o(e,i),e}},function(e,t,n){var r=n(8),o=n(14),i=function(e,t){if(o(e),!r(t)&&null!==t)throw TypeError(t+\": can't set as prototype!\")};e.exports={set:Object.setPrototypeOf||(\"__proto__\"in{}?function(e,t,r){try{(r=n(24)(Function.call,n(97).f(Object.prototype,\"__proto__\").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,n){return i(e,n),t?e.__proto__=n:r(e,n),e}}({},!1):void 0),check:i}},function(e,t,n){n(174),n(56),e.exports=n(7).Symbol},function(e,t,n){\"use strict\";var r=n(5),o=n(23),i=n(17),a=n(18),s=n(21),l=n(72).KEY,c=n(27),u=n(58),p=n(36),f=n(32),d=n(2),h=n(98),m=n(175),g=n(176),y=n(93),v=n(14),b=n(8),w=n(28),x=n(60),k=n(42),E=n(63),S=n(177),_=n(97),O=n(16),C=n(34),T=_.f,j=O.f,A=S.f,I=r.Symbol,P=r.JSON,R=P&&P.stringify,N=d(\"_hidden\"),L=d(\"toPrimitive\"),M={}.propertyIsEnumerable,D=u(\"symbol-registry\"),F=u(\"symbols\"),U=u(\"op-symbols\"),B=Object.prototype,z=\"function\"==typeof I,$=r.QObject,W=!$||!$.prototype||!$.prototype.findChild,q=i&&c(function(){return 7!=E(j({},\"a\",{get:function(){return j(this,\"a\",{value:7}).a}})).a})?function(e,t,n){var r=T(B,t);r&&delete B[t],j(e,t,n),r&&e!==B&&j(B,t,r)}:j,H=function(e){var t=F[e]=E(I.prototype);return t._k=e,t},Y=z&&\"symbol\"==typeof I.iterator?function(e){return\"symbol\"==typeof e}:function(e){return e instanceof I},V=function(e,t,n){return e===B&&V(U,t,n),v(e),t=x(t,!0),v(n),o(F,t)?(n.enumerable?(o(e,N)&&e[N][t]&&(e[N][t]=!1),n=E(n,{enumerable:k(0,!1)})):(o(e,N)||j(e,N,k(1,{})),e[N][t]=!0),q(e,t,n)):j(e,t,n)},Q=function(e,t){v(e);for(var n,r=g(t=w(t)),o=0,i=r.length;i>o;)V(e,n=r[o++],t[n]);return e},G=function(e){var t=M.call(this,e=x(e,!0));return!(this===B&&o(F,e)&&!o(U,e))&&(!(t||!o(this,e)||!o(F,e)||o(this,N)&&this[N][e])||t)},X=function(e,t){if(e=w(e),t=x(t,!0),e!==B||!o(F,t)||o(U,t)){var n=T(e,t);return!n||!o(F,t)||o(e,N)&&e[N][t]||(n.enumerable=!0),n}},K=function(e){for(var t,n=A(w(e)),r=[],i=0;n.length>i;)o(F,t=n[i++])||t==N||t==l||r.push(t);return r},J=function(e){for(var t,n=e===B,r=A(n?U:w(e)),i=[],a=0;r.length>a;)!o(F,t=r[a++])||n&&!o(B,t)||i.push(F[t]);return i};z||(s((I=function(){if(this instanceof I)throw TypeError(\"Symbol is not a constructor!\");var e=f(arguments.length>0?arguments[0]:void 0),t=function(n){this===B&&t.call(U,n),o(this,N)&&o(this[N],e)&&(this[N][e]=!1),q(this,e,k(1,n))};return i&&W&&q(B,e,{configurable:!0,set:t}),H(e)}).prototype,\"toString\",function(){return this._k}),_.f=X,O.f=V,n(99).f=S.f=K,n(45).f=G,n(71).f=J,i&&!n(31)&&s(B,\"propertyIsEnumerable\",G,!0),h.f=function(e){return H(d(e))}),a(a.G+a.W+a.F*!z,{Symbol:I});for(var Z=\"hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables\".split(\",\"),ee=0;Z.length>ee;)d(Z[ee++]);for(var te=C(d.store),ne=0;te.length>ne;)m(te[ne++]);a(a.S+a.F*!z,\"Symbol\",{for:function(e){return o(D,e+=\"\")?D[e]:D[e]=I(e)},keyFor:function(e){if(!Y(e))throw TypeError(e+\" is not a symbol!\");for(var t in D)if(D[t]===e)return t},useSetter:function(){W=!0},useSimple:function(){W=!1}}),a(a.S+a.F*!z,\"Object\",{create:function(e,t){return void 0===t?E(e):Q(E(e),t)},defineProperty:V,defineProperties:Q,getOwnPropertyDescriptor:X,getOwnPropertyNames:K,getOwnPropertySymbols:J}),P&&a(a.S+a.F*(!z||c(function(){var e=I();return\"[null]\"!=R([e])||\"{}\"!=R({a:e})||\"{}\"!=R(Object(e))})),\"JSON\",{stringify:function(e){for(var t,n,r=[e],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=t=r[1],(b(t)||void 0!==e)&&!Y(e))return y(t)||(t=function(e,t){if(\"function\"==typeof n&&(t=n.call(this,e,t)),!Y(t))return t}),r[1]=t,R.apply(P,r)}}),I.prototype[L]||n(22)(I.prototype,L,I.prototype.valueOf),p(I,\"Symbol\"),p(Math,\"Math\",!0),p(r.JSON,\"JSON\",!0)},function(e,t,n){var r=n(5),o=n(7),i=n(31),a=n(98),s=n(16).f;e.exports=function(e){var t=o.Symbol||(o.Symbol=i?{}:r.Symbol||{});\"_\"==e.charAt(0)||e in t||s(t,e,{value:a.f(e)})}},function(e,t,n){var r=n(34),o=n(71),i=n(45);e.exports=function(e){var t=r(e),n=o.f;if(n)for(var a,s=n(e),l=i.f,c=0;s.length>c;)l.call(e,a=s[c++])&&t.push(a);return t}},function(e,t,n){var r=n(28),o=n(99).f,i={}.toString,a=\"object\"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){return a&&\"[object Window]\"==i.call(e)?function(e){try{return o(e)}catch(e){return a.slice()}}(e):o(r(e))}},function(e,t,n){\"use strict\";\n/** @license React v16.6.1\n * react.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */var r=n(100),o=\"function\"==typeof Symbol&&Symbol.for,i=o?Symbol.for(\"react.element\"):60103,a=o?Symbol.for(\"react.portal\"):60106,s=o?Symbol.for(\"react.fragment\"):60107,l=o?Symbol.for(\"react.strict_mode\"):60108,c=o?Symbol.for(\"react.profiler\"):60114,u=o?Symbol.for(\"react.provider\"):60109,p=o?Symbol.for(\"react.context\"):60110,f=o?Symbol.for(\"react.concurrent_mode\"):60111,d=o?Symbol.for(\"react.forward_ref\"):60112,h=o?Symbol.for(\"react.suspense\"):60113,m=o?Symbol.for(\"react.memo\"):60115,g=o?Symbol.for(\"react.lazy\"):60116,y=\"function\"==typeof Symbol&&Symbol.iterator;function v(e){for(var t=arguments.length-1,n=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+e,r=0;r<t;r++)n+=\"&args[]=\"+encodeURIComponent(arguments[r+1]);!function(e,t,n,r,o,i,a,s){if(!e){if(e=void 0,void 0===t)e=Error(\"Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.\");else{var l=[n,r,o,i,a,s],c=0;(e=Error(t.replace(/%s/g,function(){return l[c++]}))).name=\"Invariant Violation\"}throw e.framesToPop=1,e}}(!1,\"Minified React error #\"+e+\"; visit %s for the full message or use the non-minified dev environment for full errors and additional helpful warnings. \",n)}var b={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w={};function x(e,t,n){this.props=e,this.context=t,this.refs=w,this.updater=n||b}function k(){}function E(e,t,n){this.props=e,this.context=t,this.refs=w,this.updater=n||b}x.prototype.isReactComponent={},x.prototype.setState=function(e,t){\"object\"!=typeof e&&\"function\"!=typeof e&&null!=e&&v(\"85\"),this.updater.enqueueSetState(this,e,t,\"setState\")},x.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,\"forceUpdate\")},k.prototype=x.prototype;var S=E.prototype=new k;S.constructor=E,r(S,x.prototype),S.isPureReactComponent=!0;var _={current:null,currentDispatcher:null},O=Object.prototype.hasOwnProperty,C={key:!0,ref:!0,__self:!0,__source:!0};function T(e,t,n){var r=void 0,o={},a=null,s=null;if(null!=t)for(r in void 0!==t.ref&&(s=t.ref),void 0!==t.key&&(a=\"\"+t.key),t)O.call(t,r)&&!C.hasOwnProperty(r)&&(o[r]=t[r]);var l=arguments.length-2;if(1===l)o.children=n;else if(1<l){for(var c=Array(l),u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}if(e&&e.defaultProps)for(r in l=e.defaultProps)void 0===o[r]&&(o[r]=l[r]);return{$$typeof:i,type:e,key:a,ref:s,props:o,_owner:_.current}}function j(e){return\"object\"==typeof e&&null!==e&&e.$$typeof===i}var A=/\\/+/g,I=[];function P(e,t,n,r){if(I.length){var o=I.pop();return o.result=e,o.keyPrefix=t,o.func=n,o.context=r,o.count=0,o}return{result:e,keyPrefix:t,func:n,context:r,count:0}}function R(e){e.result=null,e.keyPrefix=null,e.func=null,e.context=null,e.count=0,10>I.length&&I.push(e)}function N(e,t,n){return null==e?0:function e(t,n,r,o){var s=typeof t;\"undefined\"!==s&&\"boolean\"!==s||(t=null);var l=!1;if(null===t)l=!0;else switch(s){case\"string\":case\"number\":l=!0;break;case\"object\":switch(t.$$typeof){case i:case a:l=!0}}if(l)return r(o,t,\"\"===n?\".\"+L(t,0):n),1;if(l=0,n=\"\"===n?\".\":n+\":\",Array.isArray(t))for(var c=0;c<t.length;c++){var u=n+L(s=t[c],c);l+=e(s,u,r,o)}else if(u=null===t||\"object\"!=typeof t?null:\"function\"==typeof(u=y&&t[y]||t[\"@@iterator\"])?u:null,\"function\"==typeof u)for(t=u.call(t),c=0;!(s=t.next()).done;)l+=e(s=s.value,u=n+L(s,c++),r,o);else\"object\"===s&&v(\"31\",\"[object Object]\"==(r=\"\"+t)?\"object with keys {\"+Object.keys(t).join(\", \")+\"}\":r,\"\");return l}(e,\"\",t,n)}function L(e,t){return\"object\"==typeof e&&null!==e&&null!=e.key?function(e){var t={\"=\":\"=0\",\":\":\"=2\"};return\"$\"+(\"\"+e).replace(/[=:]/g,function(e){return t[e]})}(e.key):t.toString(36)}function M(e,t){e.func.call(e.context,t,e.count++)}function D(e,t,n){var r=e.result,o=e.keyPrefix;e=e.func.call(e.context,t,e.count++),Array.isArray(e)?F(e,r,n,function(e){return e}):null!=e&&(j(e)&&(e=function(e,t){return{$$typeof:i,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(e,o+(!e.key||t&&t.key===e.key?\"\":(\"\"+e.key).replace(A,\"$&/\")+\"/\")+n)),r.push(e))}function F(e,t,n,r,o){var i=\"\";null!=n&&(i=(\"\"+n).replace(A,\"$&/\")+\"/\"),N(e,D,t=P(t,i,r,o)),R(t)}var U={Children:{map:function(e,t,n){if(null==e)return e;var r=[];return F(e,r,null,t,n),r},forEach:function(e,t,n){if(null==e)return e;N(e,M,t=P(null,null,t,n)),R(t)},count:function(e){return N(e,function(){return null},null)},toArray:function(e){var t=[];return F(e,t,null,function(e){return e}),t},only:function(e){return j(e)||v(\"143\"),e}},createRef:function(){return{current:null}},Component:x,PureComponent:E,createContext:function(e,t){return void 0===t&&(t=null),(e={$$typeof:p,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:u,_context:e},e.Consumer=e},forwardRef:function(e){return{$$typeof:d,render:e}},lazy:function(e){return{$$typeof:g,_ctor:e,_status:-1,_result:null}},memo:function(e,t){return{$$typeof:m,type:e,compare:void 0===t?null:t}},Fragment:s,StrictMode:l,Suspense:h,createElement:T,cloneElement:function(e,t,n){null==e&&v(\"267\",e);var o=void 0,a=r({},e.props),s=e.key,l=e.ref,c=e._owner;if(null!=t){void 0!==t.ref&&(l=t.ref,c=_.current),void 0!==t.key&&(s=\"\"+t.key);var u=void 0;for(o in e.type&&e.type.defaultProps&&(u=e.type.defaultProps),t)O.call(t,o)&&!C.hasOwnProperty(o)&&(a[o]=void 0===t[o]&&void 0!==u?u[o]:t[o])}if(1===(o=arguments.length-2))a.children=n;else if(1<o){u=Array(o);for(var p=0;p<o;p++)u[p]=arguments[p+2];a.children=u}return{$$typeof:i,type:e.type,key:s,ref:l,props:a,_owner:c}},createFactory:function(e){var t=T.bind(null,e);return t.type=e,t},isValidElement:j,version:\"16.6.3\",__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{ReactCurrentOwner:_,assign:r}};U.unstable_ConcurrentMode=f,U.unstable_Profiler=c;var B={default:U},z=B&&U||B;e.exports=z.default||z},function(e,t,n){\"use strict\";\n/** @license React v16.6.1\n * react-dom.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */var r=n(0),o=n(100),i=n(180);function a(e){for(var t=arguments.length-1,n=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+e,r=0;r<t;r++)n+=\"&args[]=\"+encodeURIComponent(arguments[r+1]);!function(e,t,n,r,o,i,a,s){if(!e){if(e=void 0,void 0===t)e=Error(\"Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.\");else{var l=[n,r,o,i,a,s],c=0;(e=Error(t.replace(/%s/g,function(){return l[c++]}))).name=\"Invariant Violation\"}throw e.framesToPop=1,e}}(!1,\"Minified React error #\"+e+\"; visit %s for the full message or use the non-minified dev environment for full errors and additional helpful warnings. \",n)}r||a(\"227\");var s=!1,l=null,c=!1,u=null,p={onError:function(e){s=!0,l=e}};function f(e,t,n,r,o,i,a,c,u){s=!1,l=null,function(e,t,n,r,o,i,a,s,l){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(e){this.onError(e)}}.apply(p,arguments)}var d=null,h={};function m(){if(d)for(var e in h){var t=h[e],n=d.indexOf(e);if(-1<n||a(\"96\",e),!y[n])for(var r in t.extractEvents||a(\"97\",e),y[n]=t,n=t.eventTypes){var o=void 0,i=n[r],s=t,l=r;v.hasOwnProperty(l)&&a(\"99\",l),v[l]=i;var c=i.phasedRegistrationNames;if(c){for(o in c)c.hasOwnProperty(o)&&g(c[o],s,l);o=!0}else i.registrationName?(g(i.registrationName,s,l),o=!0):o=!1;o||a(\"98\",r,e)}}}function g(e,t,n){b[e]&&a(\"100\",e),b[e]=t,w[e]=t.eventTypes[n].dependencies}var y=[],v={},b={},w={},x=null,k=null,E=null;function S(e,t,n){var r=e.type||\"unknown-event\";e.currentTarget=E(n),function(e,t,n,r,o,i,p,d,h){if(f.apply(this,arguments),s){if(s){var m=l;s=!1,l=null}else a(\"198\"),m=void 0;c||(c=!0,u=m)}}(r,t,void 0,e),e.currentTarget=null}function _(e,t){return null==t&&a(\"30\"),null==e?t:Array.isArray(e)?Array.isArray(t)?(e.push.apply(e,t),e):(e.push(t),e):Array.isArray(t)?[e].concat(t):[e,t]}function O(e,t,n){Array.isArray(e)?e.forEach(t,n):e&&t.call(n,e)}var C=null;function T(e){if(e){var t=e._dispatchListeners,n=e._dispatchInstances;if(Array.isArray(t))for(var r=0;r<t.length&&!e.isPropagationStopped();r++)S(e,t[r],n[r]);else t&&S(e,t,n);e._dispatchListeners=null,e._dispatchInstances=null,e.isPersistent()||e.constructor.release(e)}}var j={injectEventPluginOrder:function(e){d&&a(\"101\"),d=Array.prototype.slice.call(e),m()},injectEventPluginsByName:function(e){var t,n=!1;for(t in e)if(e.hasOwnProperty(t)){var r=e[t];h.hasOwnProperty(t)&&h[t]===r||(h[t]&&a(\"102\",t),h[t]=r,n=!0)}n&&m()}};function A(e,t){var n=e.stateNode;if(!n)return null;var r=x(n);if(!r)return null;n=r[t];e:switch(t){case\"onClick\":case\"onClickCapture\":case\"onDoubleClick\":case\"onDoubleClickCapture\":case\"onMouseDown\":case\"onMouseDownCapture\":case\"onMouseMove\":case\"onMouseMoveCapture\":case\"onMouseUp\":case\"onMouseUpCapture\":(r=!r.disabled)||(r=!(\"button\"===(e=e.type)||\"input\"===e||\"select\"===e||\"textarea\"===e)),e=!r;break e;default:e=!1}return e?null:(n&&\"function\"!=typeof n&&a(\"231\",t,typeof n),n)}function I(e){if(null!==e&&(C=_(C,e)),e=C,C=null,e&&(O(e,T),C&&a(\"95\"),c))throw e=u,c=!1,u=null,e}var P=Math.random().toString(36).slice(2),R=\"__reactInternalInstance$\"+P,N=\"__reactEventHandlers$\"+P;function L(e){if(e[R])return e[R];for(;!e[R];){if(!e.parentNode)return null;e=e.parentNode}return 5===(e=e[R]).tag||6===e.tag?e:null}function M(e){return!(e=e[R])||5!==e.tag&&6!==e.tag?null:e}function D(e){if(5===e.tag||6===e.tag)return e.stateNode;a(\"33\")}function F(e){return e[N]||null}function U(e){do{e=e.return}while(e&&5!==e.tag);return e||null}function B(e,t,n){(t=A(e,n.dispatchConfig.phasedRegistrationNames[t]))&&(n._dispatchListeners=_(n._dispatchListeners,t),n._dispatchInstances=_(n._dispatchInstances,e))}function z(e){if(e&&e.dispatchConfig.phasedRegistrationNames){for(var t=e._targetInst,n=[];t;)n.push(t),t=U(t);for(t=n.length;0<t--;)B(n[t],\"captured\",e);for(t=0;t<n.length;t++)B(n[t],\"bubbled\",e)}}function $(e,t,n){e&&n&&n.dispatchConfig.registrationName&&(t=A(e,n.dispatchConfig.registrationName))&&(n._dispatchListeners=_(n._dispatchListeners,t),n._dispatchInstances=_(n._dispatchInstances,e))}function W(e){e&&e.dispatchConfig.registrationName&&$(e._targetInst,null,e)}function q(e){O(e,z)}var H=!(\"undefined\"==typeof window||!window.document||!window.document.createElement);function Y(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n[\"Webkit\"+e]=\"webkit\"+t,n[\"Moz\"+e]=\"moz\"+t,n}var V={animationend:Y(\"Animation\",\"AnimationEnd\"),animationiteration:Y(\"Animation\",\"AnimationIteration\"),animationstart:Y(\"Animation\",\"AnimationStart\"),transitionend:Y(\"Transition\",\"TransitionEnd\")},Q={},G={};function X(e){if(Q[e])return Q[e];if(!V[e])return e;var t,n=V[e];for(t in n)if(n.hasOwnProperty(t)&&t in G)return Q[e]=n[t];return e}H&&(G=document.createElement(\"div\").style,\"AnimationEvent\"in window||(delete V.animationend.animation,delete V.animationiteration.animation,delete V.animationstart.animation),\"TransitionEvent\"in window||delete V.transitionend.transition);var K=X(\"animationend\"),J=X(\"animationiteration\"),Z=X(\"animationstart\"),ee=X(\"transitionend\"),te=\"abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting\".split(\" \"),ne=null,re=null,oe=null;function ie(){if(oe)return oe;var e,t,n=re,r=n.length,o=\"value\"in ne?ne.value:ne.textContent,i=o.length;for(e=0;e<r&&n[e]===o[e];e++);var a=r-e;for(t=1;t<=a&&n[r-t]===o[i-t];t++);return oe=o.slice(e,1<t?1-t:void 0)}function ae(){return!0}function se(){return!1}function le(e,t,n,r){for(var o in this.dispatchConfig=e,this._targetInst=t,this.nativeEvent=n,e=this.constructor.Interface)e.hasOwnProperty(o)&&((t=e[o])?this[o]=t(n):\"target\"===o?this.target=r:this[o]=n[o]);return this.isDefaultPrevented=(null!=n.defaultPrevented?n.defaultPrevented:!1===n.returnValue)?ae:se,this.isPropagationStopped=se,this}function ce(e,t,n,r){if(this.eventPool.length){var o=this.eventPool.pop();return this.call(o,e,t,n,r),o}return new this(e,t,n,r)}function ue(e){e instanceof this||a(\"279\"),e.destructor(),10>this.eventPool.length&&this.eventPool.push(e)}function pe(e){e.eventPool=[],e.getPooled=ce,e.release=ue}o(le.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():\"unknown\"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=ae)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():\"unknown\"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=ae)},persist:function(){this.isPersistent=ae},isPersistent:se,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=se,this._dispatchInstances=this._dispatchListeners=null}}),le.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},le.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var i=new t;return o(i,n.prototype),n.prototype=i,n.prototype.constructor=n,n.Interface=o({},r.Interface,e),n.extend=r.extend,pe(n),n},pe(le);var fe=le.extend({data:null}),de=le.extend({data:null}),he=[9,13,27,32],me=H&&\"CompositionEvent\"in window,ge=null;H&&\"documentMode\"in document&&(ge=document.documentMode);var ye=H&&\"TextEvent\"in window&&!ge,ve=H&&(!me||ge&&8<ge&&11>=ge),be=String.fromCharCode(32),we={beforeInput:{phasedRegistrationNames:{bubbled:\"onBeforeInput\",captured:\"onBeforeInputCapture\"},dependencies:[\"compositionend\",\"keypress\",\"textInput\",\"paste\"]},compositionEnd:{phasedRegistrationNames:{bubbled:\"onCompositionEnd\",captured:\"onCompositionEndCapture\"},dependencies:\"blur compositionend keydown keypress keyup mousedown\".split(\" \")},compositionStart:{phasedRegistrationNames:{bubbled:\"onCompositionStart\",captured:\"onCompositionStartCapture\"},dependencies:\"blur compositionstart keydown keypress keyup mousedown\".split(\" \")},compositionUpdate:{phasedRegistrationNames:{bubbled:\"onCompositionUpdate\",captured:\"onCompositionUpdateCapture\"},dependencies:\"blur compositionupdate keydown keypress keyup mousedown\".split(\" \")}},xe=!1;function ke(e,t){switch(e){case\"keyup\":return-1!==he.indexOf(t.keyCode);case\"keydown\":return 229!==t.keyCode;case\"keypress\":case\"mousedown\":case\"blur\":return!0;default:return!1}}function Ee(e){return\"object\"==typeof(e=e.detail)&&\"data\"in e?e.data:null}var Se=!1;var _e={eventTypes:we,extractEvents:function(e,t,n,r){var o=void 0,i=void 0;if(me)e:{switch(e){case\"compositionstart\":o=we.compositionStart;break e;case\"compositionend\":o=we.compositionEnd;break e;case\"compositionupdate\":o=we.compositionUpdate;break e}o=void 0}else Se?ke(e,n)&&(o=we.compositionEnd):\"keydown\"===e&&229===n.keyCode&&(o=we.compositionStart);return o?(ve&&\"ko\"!==n.locale&&(Se||o!==we.compositionStart?o===we.compositionEnd&&Se&&(i=ie()):(re=\"value\"in(ne=r)?ne.value:ne.textContent,Se=!0)),o=fe.getPooled(o,t,n,r),i?o.data=i:null!==(i=Ee(n))&&(o.data=i),q(o),i=o):i=null,(e=ye?function(e,t){switch(e){case\"compositionend\":return Ee(t);case\"keypress\":return 32!==t.which?null:(xe=!0,be);case\"textInput\":return(e=t.data)===be&&xe?null:e;default:return null}}(e,n):function(e,t){if(Se)return\"compositionend\"===e||!me&&ke(e,t)?(e=ie(),oe=re=ne=null,Se=!1,e):null;switch(e){case\"paste\":return null;case\"keypress\":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case\"compositionend\":return ve&&\"ko\"!==t.locale?null:t.data;default:return null}}(e,n))?((t=de.getPooled(we.beforeInput,t,n,r)).data=e,q(t)):t=null,null===i?t:null===t?i:[i,t]}},Oe=null,Ce=null,Te=null;function je(e){if(e=k(e)){\"function\"!=typeof Oe&&a(\"280\");var t=x(e.stateNode);Oe(e.stateNode,e.type,t)}}function Ae(e){Ce?Te?Te.push(e):Te=[e]:Ce=e}function Ie(){if(Ce){var e=Ce,t=Te;if(Te=Ce=null,je(e),t)for(e=0;e<t.length;e++)je(t[e])}}function Pe(e,t){return e(t)}function Re(e,t,n){return e(t,n)}function Ne(){}var Le=!1;function Me(e,t){if(Le)return e(t);Le=!0;try{return Pe(e,t)}finally{Le=!1,(null!==Ce||null!==Te)&&(Ne(),Ie())}}var De={color:!0,date:!0,datetime:!0,\"datetime-local\":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Fe(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return\"input\"===t?!!De[e.type]:\"textarea\"===t}function Ue(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}function Be(e){if(!H)return!1;var t=(e=\"on\"+e)in document;return t||((t=document.createElement(\"div\")).setAttribute(e,\"return;\"),t=\"function\"==typeof t[e]),t}function ze(e){var t=e.type;return(e=e.nodeName)&&\"input\"===e.toLowerCase()&&(\"checkbox\"===t||\"radio\"===t)}function $e(e){e._valueTracker||(e._valueTracker=function(e){var t=ze(e)?\"checked\":\"value\",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=\"\"+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&\"function\"==typeof n.get&&\"function\"==typeof n.set){var o=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(e){r=\"\"+e,i.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=\"\"+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function We(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r=\"\";return e&&(r=ze(e)?e.checked?\"true\":\"false\":e.value),(e=r)!==n&&(t.setValue(e),!0)}var qe=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,He=/^(.*)[\\\\\\/]/,Ye=\"function\"==typeof Symbol&&Symbol.for,Ve=Ye?Symbol.for(\"react.element\"):60103,Qe=Ye?Symbol.for(\"react.portal\"):60106,Ge=Ye?Symbol.for(\"react.fragment\"):60107,Xe=Ye?Symbol.for(\"react.strict_mode\"):60108,Ke=Ye?Symbol.for(\"react.profiler\"):60114,Je=Ye?Symbol.for(\"react.provider\"):60109,Ze=Ye?Symbol.for(\"react.context\"):60110,et=Ye?Symbol.for(\"react.concurrent_mode\"):60111,tt=Ye?Symbol.for(\"react.forward_ref\"):60112,nt=Ye?Symbol.for(\"react.suspense\"):60113,rt=Ye?Symbol.for(\"react.memo\"):60115,ot=Ye?Symbol.for(\"react.lazy\"):60116,it=\"function\"==typeof Symbol&&Symbol.iterator;function at(e){return null===e||\"object\"!=typeof e?null:\"function\"==typeof(e=it&&e[it]||e[\"@@iterator\"])?e:null}function st(e){if(null==e)return null;if(\"function\"==typeof e)return e.displayName||e.name||null;if(\"string\"==typeof e)return e;switch(e){case et:return\"ConcurrentMode\";case Ge:return\"Fragment\";case Qe:return\"Portal\";case Ke:return\"Profiler\";case Xe:return\"StrictMode\";case nt:return\"Suspense\"}if(\"object\"==typeof e)switch(e.$$typeof){case Ze:return\"Context.Consumer\";case Je:return\"Context.Provider\";case tt:var t=e.render;return t=t.displayName||t.name||\"\",e.displayName||(\"\"!==t?\"ForwardRef(\"+t+\")\":\"ForwardRef\");case rt:return st(e.type);case ot:if(e=1===e._status?e._result:null)return st(e)}return null}function lt(e){var t=\"\";do{e:switch(e.tag){case 2:case 16:case 0:case 1:case 5:case 8:case 13:var n=e._debugOwner,r=e._debugSource,o=st(e.type),i=null;n&&(i=st(n.type)),n=o,o=\"\",r?o=\" (at \"+r.fileName.replace(He,\"\")+\":\"+r.lineNumber+\")\":i&&(o=\" (created by \"+i+\")\"),i=\"\\n    in \"+(n||\"Unknown\")+o;break e;default:i=\"\"}t+=i,e=e.return}while(e);return t}var ct=/^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$/,ut=Object.prototype.hasOwnProperty,pt={},ft={};function dt(e,t,n,r,o){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t}var ht={};\"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style\".split(\" \").forEach(function(e){ht[e]=new dt(e,0,!1,e,null)}),[[\"acceptCharset\",\"accept-charset\"],[\"className\",\"class\"],[\"htmlFor\",\"for\"],[\"httpEquiv\",\"http-equiv\"]].forEach(function(e){var t=e[0];ht[t]=new dt(t,1,!1,e[1],null)}),[\"contentEditable\",\"draggable\",\"spellCheck\",\"value\"].forEach(function(e){ht[e]=new dt(e,2,!1,e.toLowerCase(),null)}),[\"autoReverse\",\"externalResourcesRequired\",\"focusable\",\"preserveAlpha\"].forEach(function(e){ht[e]=new dt(e,2,!1,e,null)}),\"allowFullScreen async autoFocus autoPlay controls default defer disabled formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope\".split(\" \").forEach(function(e){ht[e]=new dt(e,3,!1,e.toLowerCase(),null)}),[\"checked\",\"multiple\",\"muted\",\"selected\"].forEach(function(e){ht[e]=new dt(e,3,!0,e,null)}),[\"capture\",\"download\"].forEach(function(e){ht[e]=new dt(e,4,!1,e,null)}),[\"cols\",\"rows\",\"size\",\"span\"].forEach(function(e){ht[e]=new dt(e,6,!1,e,null)}),[\"rowSpan\",\"start\"].forEach(function(e){ht[e]=new dt(e,5,!1,e.toLowerCase(),null)});var mt=/[\\-:]([a-z])/g;function gt(e){return e[1].toUpperCase()}function yt(e,t,n,r){var o=ht.hasOwnProperty(t)?ht[t]:null;(null!==o?0===o.type:!r&&(2<t.length&&(\"o\"===t[0]||\"O\"===t[0])&&(\"n\"===t[1]||\"N\"===t[1])))||(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case\"function\":case\"symbol\":return!0;case\"boolean\":return!r&&(null!==n?!n.acceptsBooleans:\"data-\"!==(e=e.toLowerCase().slice(0,5))&&\"aria-\"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,o,r)&&(n=null),r||null===o?function(e){return!!ut.call(ft,e)||!ut.call(pt,e)&&(ct.test(e)?ft[e]=!0:(pt[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,\"\"+n)):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&\"\":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?\"\":\"\"+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}function vt(e){switch(typeof e){case\"boolean\":case\"number\":case\"object\":case\"string\":case\"undefined\":return e;default:return\"\"}}function bt(e,t){var n=t.checked;return o({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function wt(e,t){var n=null==t.defaultValue?\"\":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=vt(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:\"checkbox\"===t.type||\"radio\"===t.type?null!=t.checked:null!=t.value}}function xt(e,t){null!=(t=t.checked)&&yt(e,\"checked\",t,!1)}function kt(e,t){xt(e,t);var n=vt(t.value),r=t.type;if(null!=n)\"number\"===r?(0===n&&\"\"===e.value||e.value!=n)&&(e.value=\"\"+n):e.value!==\"\"+n&&(e.value=\"\"+n);else if(\"submit\"===r||\"reset\"===r)return void e.removeAttribute(\"value\");t.hasOwnProperty(\"value\")?St(e,t.type,n):t.hasOwnProperty(\"defaultValue\")&&St(e,t.type,vt(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function Et(e,t,n){if(t.hasOwnProperty(\"value\")||t.hasOwnProperty(\"defaultValue\")){var r=t.type;if(!(\"submit\"!==r&&\"reset\"!==r||void 0!==t.value&&null!==t.value))return;t=\"\"+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}\"\"!==(n=e.name)&&(e.name=\"\"),e.defaultChecked=!e.defaultChecked,e.defaultChecked=!!e._wrapperState.initialChecked,\"\"!==n&&(e.name=n)}function St(e,t,n){\"number\"===t&&e.ownerDocument.activeElement===e||(null==n?e.defaultValue=\"\"+e._wrapperState.initialValue:e.defaultValue!==\"\"+n&&(e.defaultValue=\"\"+n))}\"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height\".split(\" \").forEach(function(e){var t=e.replace(mt,gt);ht[t]=new dt(t,1,!1,e,null)}),\"xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type\".split(\" \").forEach(function(e){var t=e.replace(mt,gt);ht[t]=new dt(t,1,!1,e,\"http://www.w3.org/1999/xlink\")}),[\"xml:base\",\"xml:lang\",\"xml:space\"].forEach(function(e){var t=e.replace(mt,gt);ht[t]=new dt(t,1,!1,e,\"http://www.w3.org/XML/1998/namespace\")}),ht.tabIndex=new dt(\"tabIndex\",1,!1,\"tabindex\",null);var _t={change:{phasedRegistrationNames:{bubbled:\"onChange\",captured:\"onChangeCapture\"},dependencies:\"blur change click focus input keydown keyup selectionchange\".split(\" \")}};function Ot(e,t,n){return(e=le.getPooled(_t.change,e,t,n)).type=\"change\",Ae(n),q(e),e}var Ct=null,Tt=null;function jt(e){I(e)}function At(e){if(We(D(e)))return e}function It(e,t){if(\"change\"===e)return t}var Pt=!1;function Rt(){Ct&&(Ct.detachEvent(\"onpropertychange\",Nt),Tt=Ct=null)}function Nt(e){\"value\"===e.propertyName&&At(Tt)&&Me(jt,e=Ot(Tt,e,Ue(e)))}function Lt(e,t,n){\"focus\"===e?(Rt(),Tt=n,(Ct=t).attachEvent(\"onpropertychange\",Nt)):\"blur\"===e&&Rt()}function Mt(e){if(\"selectionchange\"===e||\"keyup\"===e||\"keydown\"===e)return At(Tt)}function Dt(e,t){if(\"click\"===e)return At(t)}function Ft(e,t){if(\"input\"===e||\"change\"===e)return At(t)}H&&(Pt=Be(\"input\")&&(!document.documentMode||9<document.documentMode));var Ut={eventTypes:_t,_isInputEventSupported:Pt,extractEvents:function(e,t,n,r){var o=t?D(t):window,i=void 0,a=void 0,s=o.nodeName&&o.nodeName.toLowerCase();if(\"select\"===s||\"input\"===s&&\"file\"===o.type?i=It:Fe(o)?Pt?i=Ft:(i=Mt,a=Lt):(s=o.nodeName)&&\"input\"===s.toLowerCase()&&(\"checkbox\"===o.type||\"radio\"===o.type)&&(i=Dt),i&&(i=i(e,t)))return Ot(i,n,r);a&&a(e,o,t),\"blur\"===e&&(e=o._wrapperState)&&e.controlled&&\"number\"===o.type&&St(o,\"number\",o.value)}},Bt=le.extend({view:null,detail:null}),zt={Alt:\"altKey\",Control:\"ctrlKey\",Meta:\"metaKey\",Shift:\"shiftKey\"};function $t(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=zt[e])&&!!t[e]}function Wt(){return $t}var qt=0,Ht=0,Yt=!1,Vt=!1,Qt=Bt.extend({screenX:null,screenY:null,clientX:null,clientY:null,pageX:null,pageY:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,getModifierState:Wt,button:null,buttons:null,relatedTarget:function(e){return e.relatedTarget||(e.fromElement===e.srcElement?e.toElement:e.fromElement)},movementX:function(e){if(\"movementX\"in e)return e.movementX;var t=qt;return qt=e.screenX,Yt?\"mousemove\"===e.type?e.screenX-t:0:(Yt=!0,0)},movementY:function(e){if(\"movementY\"in e)return e.movementY;var t=Ht;return Ht=e.screenY,Vt?\"mousemove\"===e.type?e.screenY-t:0:(Vt=!0,0)}}),Gt=Qt.extend({pointerId:null,width:null,height:null,pressure:null,tangentialPressure:null,tiltX:null,tiltY:null,twist:null,pointerType:null,isPrimary:null}),Xt={mouseEnter:{registrationName:\"onMouseEnter\",dependencies:[\"mouseout\",\"mouseover\"]},mouseLeave:{registrationName:\"onMouseLeave\",dependencies:[\"mouseout\",\"mouseover\"]},pointerEnter:{registrationName:\"onPointerEnter\",dependencies:[\"pointerout\",\"pointerover\"]},pointerLeave:{registrationName:\"onPointerLeave\",dependencies:[\"pointerout\",\"pointerover\"]}},Kt={eventTypes:Xt,extractEvents:function(e,t,n,r){var o=\"mouseover\"===e||\"pointerover\"===e,i=\"mouseout\"===e||\"pointerout\"===e;if(o&&(n.relatedTarget||n.fromElement)||!i&&!o)return null;if(o=r.window===r?r:(o=r.ownerDocument)?o.defaultView||o.parentWindow:window,i?(i=t,t=(t=n.relatedTarget||n.toElement)?L(t):null):i=null,i===t)return null;var a=void 0,s=void 0,l=void 0,c=void 0;\"mouseout\"===e||\"mouseover\"===e?(a=Qt,s=Xt.mouseLeave,l=Xt.mouseEnter,c=\"mouse\"):\"pointerout\"!==e&&\"pointerover\"!==e||(a=Gt,s=Xt.pointerLeave,l=Xt.pointerEnter,c=\"pointer\");var u=null==i?o:D(i);if(o=null==t?o:D(t),(e=a.getPooled(s,i,n,r)).type=c+\"leave\",e.target=u,e.relatedTarget=o,(n=a.getPooled(l,t,n,r)).type=c+\"enter\",n.target=o,n.relatedTarget=u,r=t,i&&r)e:{for(o=r,c=0,a=t=i;a;a=U(a))c++;for(a=0,l=o;l;l=U(l))a++;for(;0<c-a;)t=U(t),c--;for(;0<a-c;)o=U(o),a--;for(;c--;){if(t===o||t===o.alternate)break e;t=U(t),o=U(o)}t=null}else t=null;for(o=t,t=[];i&&i!==o&&(null===(c=i.alternate)||c!==o);)t.push(i),i=U(i);for(i=[];r&&r!==o&&(null===(c=r.alternate)||c!==o);)i.push(r),r=U(r);for(r=0;r<t.length;r++)$(t[r],\"bubbled\",e);for(r=i.length;0<r--;)$(i[r],\"captured\",n);return[e,n]}},Jt=Object.prototype.hasOwnProperty;function Zt(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function en(e,t){if(Zt(e,t))return!0;if(\"object\"!=typeof e||null===e||\"object\"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++)if(!Jt.call(t,n[r])||!Zt(e[n[r]],t[n[r]]))return!1;return!0}function tn(e){var t=e;if(e.alternate)for(;t.return;)t=t.return;else{if(0!=(2&t.effectTag))return 1;for(;t.return;)if(0!=(2&(t=t.return).effectTag))return 1}return 3===t.tag?2:3}function nn(e){2!==tn(e)&&a(\"188\")}function rn(e){if(!(e=function(e){var t=e.alternate;if(!t)return 3===(t=tn(e))&&a(\"188\"),1===t?null:e;for(var n=e,r=t;;){var o=n.return,i=o?o.alternate:null;if(!o||!i)break;if(o.child===i.child){for(var s=o.child;s;){if(s===n)return nn(o),e;if(s===r)return nn(o),t;s=s.sibling}a(\"188\")}if(n.return!==r.return)n=o,r=i;else{s=!1;for(var l=o.child;l;){if(l===n){s=!0,n=o,r=i;break}if(l===r){s=!0,r=o,n=i;break}l=l.sibling}if(!s){for(l=i.child;l;){if(l===n){s=!0,n=i,r=o;break}if(l===r){s=!0,r=i,n=o;break}l=l.sibling}s||a(\"189\")}}n.alternate!==r&&a(\"190\")}return 3!==n.tag&&a(\"188\"),n.stateNode.current===n?e:t}(e)))return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}var on=le.extend({animationName:null,elapsedTime:null,pseudoElement:null}),an=le.extend({clipboardData:function(e){return\"clipboardData\"in e?e.clipboardData:window.clipboardData}}),sn=Bt.extend({relatedTarget:null});function ln(e){var t=e.keyCode;return\"charCode\"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}var cn={Esc:\"Escape\",Spacebar:\" \",Left:\"ArrowLeft\",Up:\"ArrowUp\",Right:\"ArrowRight\",Down:\"ArrowDown\",Del:\"Delete\",Win:\"OS\",Menu:\"ContextMenu\",Apps:\"ContextMenu\",Scroll:\"ScrollLock\",MozPrintableKey:\"Unidentified\"},un={8:\"Backspace\",9:\"Tab\",12:\"Clear\",13:\"Enter\",16:\"Shift\",17:\"Control\",18:\"Alt\",19:\"Pause\",20:\"CapsLock\",27:\"Escape\",32:\" \",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"ArrowLeft\",38:\"ArrowUp\",39:\"ArrowRight\",40:\"ArrowDown\",45:\"Insert\",46:\"Delete\",112:\"F1\",113:\"F2\",114:\"F3\",115:\"F4\",116:\"F5\",117:\"F6\",118:\"F7\",119:\"F8\",120:\"F9\",121:\"F10\",122:\"F11\",123:\"F12\",144:\"NumLock\",145:\"ScrollLock\",224:\"Meta\"},pn=Bt.extend({key:function(e){if(e.key){var t=cn[e.key]||e.key;if(\"Unidentified\"!==t)return t}return\"keypress\"===e.type?13===(e=ln(e))?\"Enter\":String.fromCharCode(e):\"keydown\"===e.type||\"keyup\"===e.type?un[e.keyCode]||\"Unidentified\":\"\"},location:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,repeat:null,locale:null,getModifierState:Wt,charCode:function(e){return\"keypress\"===e.type?ln(e):0},keyCode:function(e){return\"keydown\"===e.type||\"keyup\"===e.type?e.keyCode:0},which:function(e){return\"keypress\"===e.type?ln(e):\"keydown\"===e.type||\"keyup\"===e.type?e.keyCode:0}}),fn=Qt.extend({dataTransfer:null}),dn=Bt.extend({touches:null,targetTouches:null,changedTouches:null,altKey:null,metaKey:null,ctrlKey:null,shiftKey:null,getModifierState:Wt}),hn=le.extend({propertyName:null,elapsedTime:null,pseudoElement:null}),mn=Qt.extend({deltaX:function(e){return\"deltaX\"in e?e.deltaX:\"wheelDeltaX\"in e?-e.wheelDeltaX:0},deltaY:function(e){return\"deltaY\"in e?e.deltaY:\"wheelDeltaY\"in e?-e.wheelDeltaY:\"wheelDelta\"in e?-e.wheelDelta:0},deltaZ:null,deltaMode:null}),gn=[[\"abort\",\"abort\"],[K,\"animationEnd\"],[J,\"animationIteration\"],[Z,\"animationStart\"],[\"canplay\",\"canPlay\"],[\"canplaythrough\",\"canPlayThrough\"],[\"drag\",\"drag\"],[\"dragenter\",\"dragEnter\"],[\"dragexit\",\"dragExit\"],[\"dragleave\",\"dragLeave\"],[\"dragover\",\"dragOver\"],[\"durationchange\",\"durationChange\"],[\"emptied\",\"emptied\"],[\"encrypted\",\"encrypted\"],[\"ended\",\"ended\"],[\"error\",\"error\"],[\"gotpointercapture\",\"gotPointerCapture\"],[\"load\",\"load\"],[\"loadeddata\",\"loadedData\"],[\"loadedmetadata\",\"loadedMetadata\"],[\"loadstart\",\"loadStart\"],[\"lostpointercapture\",\"lostPointerCapture\"],[\"mousemove\",\"mouseMove\"],[\"mouseout\",\"mouseOut\"],[\"mouseover\",\"mouseOver\"],[\"playing\",\"playing\"],[\"pointermove\",\"pointerMove\"],[\"pointerout\",\"pointerOut\"],[\"pointerover\",\"pointerOver\"],[\"progress\",\"progress\"],[\"scroll\",\"scroll\"],[\"seeking\",\"seeking\"],[\"stalled\",\"stalled\"],[\"suspend\",\"suspend\"],[\"timeupdate\",\"timeUpdate\"],[\"toggle\",\"toggle\"],[\"touchmove\",\"touchMove\"],[ee,\"transitionEnd\"],[\"waiting\",\"waiting\"],[\"wheel\",\"wheel\"]],yn={},vn={};function bn(e,t){var n=e[0],r=\"on\"+((e=e[1])[0].toUpperCase()+e.slice(1));t={phasedRegistrationNames:{bubbled:r,captured:r+\"Capture\"},dependencies:[n],isInteractive:t},yn[e]=t,vn[n]=t}[[\"blur\",\"blur\"],[\"cancel\",\"cancel\"],[\"click\",\"click\"],[\"close\",\"close\"],[\"contextmenu\",\"contextMenu\"],[\"copy\",\"copy\"],[\"cut\",\"cut\"],[\"auxclick\",\"auxClick\"],[\"dblclick\",\"doubleClick\"],[\"dragend\",\"dragEnd\"],[\"dragstart\",\"dragStart\"],[\"drop\",\"drop\"],[\"focus\",\"focus\"],[\"input\",\"input\"],[\"invalid\",\"invalid\"],[\"keydown\",\"keyDown\"],[\"keypress\",\"keyPress\"],[\"keyup\",\"keyUp\"],[\"mousedown\",\"mouseDown\"],[\"mouseup\",\"mouseUp\"],[\"paste\",\"paste\"],[\"pause\",\"pause\"],[\"play\",\"play\"],[\"pointercancel\",\"pointerCancel\"],[\"pointerdown\",\"pointerDown\"],[\"pointerup\",\"pointerUp\"],[\"ratechange\",\"rateChange\"],[\"reset\",\"reset\"],[\"seeked\",\"seeked\"],[\"submit\",\"submit\"],[\"touchcancel\",\"touchCancel\"],[\"touchend\",\"touchEnd\"],[\"touchstart\",\"touchStart\"],[\"volumechange\",\"volumeChange\"]].forEach(function(e){bn(e,!0)}),gn.forEach(function(e){bn(e,!1)});var wn={eventTypes:yn,isInteractiveTopLevelEventType:function(e){return void 0!==(e=vn[e])&&!0===e.isInteractive},extractEvents:function(e,t,n,r){var o=vn[e];if(!o)return null;switch(e){case\"keypress\":if(0===ln(n))return null;case\"keydown\":case\"keyup\":e=pn;break;case\"blur\":case\"focus\":e=sn;break;case\"click\":if(2===n.button)return null;case\"auxclick\":case\"dblclick\":case\"mousedown\":case\"mousemove\":case\"mouseup\":case\"mouseout\":case\"mouseover\":case\"contextmenu\":e=Qt;break;case\"drag\":case\"dragend\":case\"dragenter\":case\"dragexit\":case\"dragleave\":case\"dragover\":case\"dragstart\":case\"drop\":e=fn;break;case\"touchcancel\":case\"touchend\":case\"touchmove\":case\"touchstart\":e=dn;break;case K:case J:case Z:e=on;break;case ee:e=hn;break;case\"scroll\":e=Bt;break;case\"wheel\":e=mn;break;case\"copy\":case\"cut\":case\"paste\":e=an;break;case\"gotpointercapture\":case\"lostpointercapture\":case\"pointercancel\":case\"pointerdown\":case\"pointermove\":case\"pointerout\":case\"pointerover\":case\"pointerup\":e=Gt;break;default:e=le}return q(t=e.getPooled(o,t,n,r)),t}},xn=wn.isInteractiveTopLevelEventType,kn=[];function En(e){var t=e.targetInst,n=t;do{if(!n){e.ancestors.push(n);break}var r;for(r=n;r.return;)r=r.return;if(!(r=3!==r.tag?null:r.stateNode.containerInfo))break;e.ancestors.push(n),n=L(r)}while(n);for(n=0;n<e.ancestors.length;n++){t=e.ancestors[n];var o=Ue(e.nativeEvent);r=e.topLevelType;for(var i=e.nativeEvent,a=null,s=0;s<y.length;s++){var l=y[s];l&&(l=l.extractEvents(r,t,i,o))&&(a=_(a,l))}I(a)}}var Sn=!0;function _n(e,t){if(!t)return null;var n=(xn(e)?Cn:Tn).bind(null,e);t.addEventListener(e,n,!1)}function On(e,t){if(!t)return null;var n=(xn(e)?Cn:Tn).bind(null,e);t.addEventListener(e,n,!0)}function Cn(e,t){Re(Tn,e,t)}function Tn(e,t){if(Sn){var n=Ue(t);if(null===(n=L(n))||\"number\"!=typeof n.tag||2===tn(n)||(n=null),kn.length){var r=kn.pop();r.topLevelType=e,r.nativeEvent=t,r.targetInst=n,e=r}else e={topLevelType:e,nativeEvent:t,targetInst:n,ancestors:[]};try{Me(En,e)}finally{e.topLevelType=null,e.nativeEvent=null,e.targetInst=null,e.ancestors.length=0,10>kn.length&&kn.push(e)}}}var jn={},An=0,In=\"_reactListenersID\"+(\"\"+Math.random()).slice(2);function Pn(e){return Object.prototype.hasOwnProperty.call(e,In)||(e[In]=An++,jn[e[In]]={}),jn[e[In]]}function Rn(e){if(void 0===(e=e||(\"undefined\"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Nn(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function Ln(e,t){var n,r=Nn(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=Nn(r)}}function Mn(){for(var e=window,t=Rn();t instanceof e.HTMLIFrameElement;){try{e=t.contentDocument.defaultView}catch(e){break}t=Rn(e.document)}return t}function Dn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(\"input\"===t&&(\"text\"===e.type||\"search\"===e.type||\"tel\"===e.type||\"url\"===e.type||\"password\"===e.type)||\"textarea\"===t||\"true\"===e.contentEditable)}var Fn=H&&\"documentMode\"in document&&11>=document.documentMode,Un={select:{phasedRegistrationNames:{bubbled:\"onSelect\",captured:\"onSelectCapture\"},dependencies:\"blur contextmenu dragend focus keydown keyup mousedown mouseup selectionchange\".split(\" \")}},Bn=null,zn=null,$n=null,Wn=!1;function qn(e,t){var n=t.window===t?t.document:9===t.nodeType?t:t.ownerDocument;return Wn||null==Bn||Bn!==Rn(n)?null:(\"selectionStart\"in(n=Bn)&&Dn(n)?n={start:n.selectionStart,end:n.selectionEnd}:n={anchorNode:(n=(n.ownerDocument&&n.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset},$n&&en($n,n)?null:($n=n,(e=le.getPooled(Un.select,zn,e,t)).type=\"select\",e.target=Bn,q(e),e))}var Hn={eventTypes:Un,extractEvents:function(e,t,n,r){var o,i=r.window===r?r.document:9===r.nodeType?r:r.ownerDocument;if(!(o=!i)){e:{i=Pn(i),o=w.onSelect;for(var a=0;a<o.length;a++){var s=o[a];if(!i.hasOwnProperty(s)||!i[s]){i=!1;break e}}i=!0}o=!i}if(o)return null;switch(i=t?D(t):window,e){case\"focus\":(Fe(i)||\"true\"===i.contentEditable)&&(Bn=i,zn=t,$n=null);break;case\"blur\":$n=zn=Bn=null;break;case\"mousedown\":Wn=!0;break;case\"contextmenu\":case\"mouseup\":case\"dragend\":return Wn=!1,qn(n,r);case\"selectionchange\":if(Fn)break;case\"keydown\":case\"keyup\":return qn(n,r)}return null}};function Yn(e,t){return e=o({children:void 0},t),(t=function(e){var t=\"\";return r.Children.forEach(e,function(e){null!=e&&(t+=e)}),t}(t.children))&&(e.children=t),e}function Vn(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o<n.length;o++)t[\"$\"+n[o]]=!0;for(n=0;n<e.length;n++)o=t.hasOwnProperty(\"$\"+e[n].value),e[n].selected!==o&&(e[n].selected=o),o&&r&&(e[n].defaultSelected=!0)}else{for(n=\"\"+vt(n),t=null,o=0;o<e.length;o++){if(e[o].value===n)return e[o].selected=!0,void(r&&(e[o].defaultSelected=!0));null!==t||e[o].disabled||(t=e[o])}null!==t&&(t.selected=!0)}}function Qn(e,t){return null!=t.dangerouslySetInnerHTML&&a(\"91\"),o({},t,{value:void 0,defaultValue:void 0,children:\"\"+e._wrapperState.initialValue})}function Gn(e,t){var n=t.value;null==n&&(n=t.defaultValue,null!=(t=t.children)&&(null!=n&&a(\"92\"),Array.isArray(t)&&(1>=t.length||a(\"93\"),t=t[0]),n=t),null==n&&(n=\"\")),e._wrapperState={initialValue:vt(n)}}function Xn(e,t){var n=vt(t.value),r=vt(t.defaultValue);null!=n&&((n=\"\"+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=\"\"+r)}function Kn(e){var t=e.textContent;t===e._wrapperState.initialValue&&(e.value=t)}j.injectEventPluginOrder(\"ResponderEventPlugin SimpleEventPlugin EnterLeaveEventPlugin ChangeEventPlugin SelectEventPlugin BeforeInputEventPlugin\".split(\" \")),x=F,k=M,E=D,j.injectEventPluginsByName({SimpleEventPlugin:wn,EnterLeaveEventPlugin:Kt,ChangeEventPlugin:Ut,SelectEventPlugin:Hn,BeforeInputEventPlugin:_e});var Jn={html:\"http://www.w3.org/1999/xhtml\",mathml:\"http://www.w3.org/1998/Math/MathML\",svg:\"http://www.w3.org/2000/svg\"};function Zn(e){switch(e){case\"svg\":return\"http://www.w3.org/2000/svg\";case\"math\":return\"http://www.w3.org/1998/Math/MathML\";default:return\"http://www.w3.org/1999/xhtml\"}}function er(e,t){return null==e||\"http://www.w3.org/1999/xhtml\"===e?Zn(t):\"http://www.w3.org/2000/svg\"===e&&\"foreignObject\"===t?\"http://www.w3.org/1999/xhtml\":e}var tr,nr=void 0,rr=(tr=function(e,t){if(e.namespaceURI!==Jn.svg||\"innerHTML\"in e)e.innerHTML=t;else{for((nr=nr||document.createElement(\"div\")).innerHTML=\"<svg>\"+t+\"</svg>\",t=nr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},\"undefined\"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction(function(){return tr(e,t)})}:tr);function or(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ir={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ar=[\"Webkit\",\"ms\",\"Moz\",\"O\"];function sr(e,t,n){return null==t||\"boolean\"==typeof t||\"\"===t?\"\":n||\"number\"!=typeof t||0===t||ir.hasOwnProperty(e)&&ir[e]?(\"\"+t).trim():t+\"px\"}function lr(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf(\"--\"),o=sr(n,t[n],r);\"float\"===n&&(n=\"cssFloat\"),r?e.setProperty(n,o):e[n]=o}}Object.keys(ir).forEach(function(e){ar.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ir[t]=ir[e]})});var cr=o({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ur(e,t){t&&(cr[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML)&&a(\"137\",e,\"\"),null!=t.dangerouslySetInnerHTML&&(null!=t.children&&a(\"60\"),\"object\"==typeof t.dangerouslySetInnerHTML&&\"__html\"in t.dangerouslySetInnerHTML||a(\"61\")),null!=t.style&&\"object\"!=typeof t.style&&a(\"62\",\"\"))}function pr(e,t){if(-1===e.indexOf(\"-\"))return\"string\"==typeof t.is;switch(e){case\"annotation-xml\":case\"color-profile\":case\"font-face\":case\"font-face-src\":case\"font-face-uri\":case\"font-face-format\":case\"font-face-name\":case\"missing-glyph\":return!1;default:return!0}}function fr(e,t){var n=Pn(e=9===e.nodeType||11===e.nodeType?e:e.ownerDocument);t=w[t];for(var r=0;r<t.length;r++){var o=t[r];if(!n.hasOwnProperty(o)||!n[o]){switch(o){case\"scroll\":On(\"scroll\",e);break;case\"focus\":case\"blur\":On(\"focus\",e),On(\"blur\",e),n.blur=!0,n.focus=!0;break;case\"cancel\":case\"close\":Be(o)&&On(o,e);break;case\"invalid\":case\"submit\":case\"reset\":break;default:-1===te.indexOf(o)&&_n(o,e)}n[o]=!0}}}function dr(){}var hr=null,mr=null;function gr(e,t){switch(e){case\"button\":case\"input\":case\"select\":case\"textarea\":return!!t.autoFocus}return!1}function yr(e,t){return\"textarea\"===e||\"option\"===e||\"noscript\"===e||\"string\"==typeof t.children||\"number\"==typeof t.children||\"object\"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var vr=\"function\"==typeof setTimeout?setTimeout:void 0,br=\"function\"==typeof clearTimeout?clearTimeout:void 0;function wr(e){for(e=e.nextSibling;e&&1!==e.nodeType&&3!==e.nodeType;)e=e.nextSibling;return e}function xr(e){for(e=e.firstChild;e&&1!==e.nodeType&&3!==e.nodeType;)e=e.nextSibling;return e}new Set;var kr=[],Er=-1;function Sr(e){0>Er||(e.current=kr[Er],kr[Er]=null,Er--)}function _r(e,t){kr[++Er]=e.current,e.current=t}var Or={},Cr={current:Or},Tr={current:!1},jr=Or;function Ar(e,t){var n=e.type.contextTypes;if(!n)return Or;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,i={};for(o in n)i[o]=t[o];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function Ir(e){return null!=(e=e.childContextTypes)}function Pr(e){Sr(Tr),Sr(Cr)}function Rr(e){Sr(Tr),Sr(Cr)}function Nr(e,t,n){Cr.current!==Or&&a(\"168\"),_r(Cr,t),_r(Tr,n)}function Lr(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,\"function\"!=typeof r.getChildContext)return n;for(var i in r=r.getChildContext())i in e||a(\"108\",st(t)||\"Unknown\",i);return o({},n,r)}function Mr(e){var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||Or,jr=Cr.current,_r(Cr,t),_r(Tr,Tr.current),!0}function Dr(e,t,n){var r=e.stateNode;r||a(\"169\"),n?(t=Lr(e,t,jr),r.__reactInternalMemoizedMergedChildContext=t,Sr(Tr),Sr(Cr),_r(Cr,t)):Sr(Tr),_r(Tr,n)}var Fr=null,Ur=null;function Br(e){return function(t){try{return e(t)}catch(e){}}}function zr(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.firstContextDependency=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childExpirationTime=this.expirationTime=0,this.alternate=null}function $r(e,t,n,r){return new zr(e,t,n,r)}function Wr(e){return!(!(e=e.prototype)||!e.isReactComponent)}function qr(e,t){var n=e.alternate;return null===n?((n=$r(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.effectTag=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childExpirationTime=e.childExpirationTime,n.expirationTime=e.expirationTime,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,n.firstContextDependency=e.firstContextDependency,n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Hr(e,t,n,r,o,i){var s=2;if(r=e,\"function\"==typeof e)Wr(e)&&(s=1);else if(\"string\"==typeof e)s=5;else e:switch(e){case Ge:return Yr(n.children,o,i,t);case et:return Vr(n,3|o,i,t);case Xe:return Vr(n,2|o,i,t);case Ke:return(e=$r(12,n,t,4|o)).elementType=Ke,e.type=Ke,e.expirationTime=i,e;case nt:return(e=$r(13,n,t,o)).elementType=nt,e.type=nt,e.expirationTime=i,e;default:if(\"object\"==typeof e&&null!==e)switch(e.$$typeof){case Je:s=10;break e;case Ze:s=9;break e;case tt:s=11;break e;case rt:s=14;break e;case ot:s=16,r=null;break e}a(\"130\",null==e?e:typeof e,\"\")}return(t=$r(s,n,t,o)).elementType=e,t.type=r,t.expirationTime=i,t}function Yr(e,t,n,r){return(e=$r(7,e,r,t)).expirationTime=n,e}function Vr(e,t,n,r){return e=$r(8,e,r,t),t=0==(1&t)?Xe:et,e.elementType=t,e.type=t,e.expirationTime=n,e}function Qr(e,t,n){return(e=$r(6,e,null,t)).expirationTime=n,e}function Gr(e,t,n){return(t=$r(4,null!==e.children?e.children:[],e.key,t)).expirationTime=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xr(e,t){e.didError=!1;var n=e.earliestPendingTime;0===n?e.earliestPendingTime=e.latestPendingTime=t:n<t?e.earliestPendingTime=t:e.latestPendingTime>t&&(e.latestPendingTime=t),Zr(t,e)}function Kr(e,t){e.didError=!1;var n=e.latestPingedTime;0!==n&&n>=t&&(e.latestPingedTime=0),n=e.earliestPendingTime;var r=e.latestPendingTime;n===t?e.earliestPendingTime=r===t?e.latestPendingTime=0:r:r===t&&(e.latestPendingTime=n),n=e.earliestSuspendedTime,r=e.latestSuspendedTime,0===n?e.earliestSuspendedTime=e.latestSuspendedTime=t:n<t?e.earliestSuspendedTime=t:r>t&&(e.latestSuspendedTime=t),Zr(t,e)}function Jr(e,t){var n=e.earliestPendingTime;return n>t&&(t=n),(e=e.earliestSuspendedTime)>t&&(t=e),t}function Zr(e,t){var n=t.earliestSuspendedTime,r=t.latestSuspendedTime,o=t.earliestPendingTime,i=t.latestPingedTime;0===(o=0!==o?o:i)&&(0===e||r<e)&&(o=r),0!==(e=o)&&n>e&&(e=n),t.nextExpirationTimeToWorkOn=o,t.expirationTime=e}var eo=!1;function to(e){return{baseState:e,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function no(e){return{baseState:e.baseState,firstUpdate:e.firstUpdate,lastUpdate:e.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function ro(e){return{expirationTime:e,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function oo(e,t){null===e.lastUpdate?e.firstUpdate=e.lastUpdate=t:(e.lastUpdate.next=t,e.lastUpdate=t)}function io(e,t){var n=e.alternate;if(null===n){var r=e.updateQueue,o=null;null===r&&(r=e.updateQueue=to(e.memoizedState))}else r=e.updateQueue,o=n.updateQueue,null===r?null===o?(r=e.updateQueue=to(e.memoizedState),o=n.updateQueue=to(n.memoizedState)):r=e.updateQueue=no(o):null===o&&(o=n.updateQueue=no(r));null===o||r===o?oo(r,t):null===r.lastUpdate||null===o.lastUpdate?(oo(r,t),oo(o,t)):(oo(r,t),o.lastUpdate=t)}function ao(e,t){var n=e.updateQueue;null===(n=null===n?e.updateQueue=to(e.memoizedState):so(e,n)).lastCapturedUpdate?n.firstCapturedUpdate=n.lastCapturedUpdate=t:(n.lastCapturedUpdate.next=t,n.lastCapturedUpdate=t)}function so(e,t){var n=e.alternate;return null!==n&&t===n.updateQueue&&(t=e.updateQueue=no(t)),t}function lo(e,t,n,r,i,a){switch(n.tag){case 1:return\"function\"==typeof(e=n.payload)?e.call(a,r,i):e;case 3:e.effectTag=-2049&e.effectTag|64;case 0:if(null==(i=\"function\"==typeof(e=n.payload)?e.call(a,r,i):e))break;return o({},r,i);case 2:eo=!0}return r}function co(e,t,n,r,o){eo=!1;for(var i=(t=so(e,t)).baseState,a=null,s=0,l=t.firstUpdate,c=i;null!==l;){var u=l.expirationTime;u<o?(null===a&&(a=l,i=c),s<u&&(s=u)):(c=lo(e,0,l,c,n,r),null!==l.callback&&(e.effectTag|=32,l.nextEffect=null,null===t.lastEffect?t.firstEffect=t.lastEffect=l:(t.lastEffect.nextEffect=l,t.lastEffect=l))),l=l.next}for(u=null,l=t.firstCapturedUpdate;null!==l;){var p=l.expirationTime;p<o?(null===u&&(u=l,null===a&&(i=c)),s<p&&(s=p)):(c=lo(e,0,l,c,n,r),null!==l.callback&&(e.effectTag|=32,l.nextEffect=null,null===t.lastCapturedEffect?t.firstCapturedEffect=t.lastCapturedEffect=l:(t.lastCapturedEffect.nextEffect=l,t.lastCapturedEffect=l))),l=l.next}null===a&&(t.lastUpdate=null),null===u?t.lastCapturedUpdate=null:e.effectTag|=32,null===a&&null===u&&(i=c),t.baseState=i,t.firstUpdate=a,t.firstCapturedUpdate=u,e.expirationTime=s,e.memoizedState=c}function uo(e,t,n){null!==t.firstCapturedUpdate&&(null!==t.lastUpdate&&(t.lastUpdate.next=t.firstCapturedUpdate,t.lastUpdate=t.lastCapturedUpdate),t.firstCapturedUpdate=t.lastCapturedUpdate=null),po(t.firstEffect,n),t.firstEffect=t.lastEffect=null,po(t.firstCapturedEffect,n),t.firstCapturedEffect=t.lastCapturedEffect=null}function po(e,t){for(;null!==e;){var n=e.callback;if(null!==n){e.callback=null;var r=t;\"function\"!=typeof n&&a(\"191\",n),n.call(r)}e=e.nextEffect}}function fo(e,t){return{value:e,source:t,stack:lt(t)}}var ho={current:null},mo=null,go=null,yo=null;function vo(e,t){var n=e.type._context;_r(ho,n._currentValue),n._currentValue=t}function bo(e){var t=ho.current;Sr(ho),e.type._context._currentValue=t}function wo(e){mo=e,yo=go=null,e.firstContextDependency=null}function xo(e,t){return yo!==e&&!1!==t&&0!==t&&(\"number\"==typeof t&&1073741823!==t||(yo=e,t=1073741823),t={context:e,observedBits:t,next:null},null===go?(null===mo&&a(\"293\"),mo.firstContextDependency=go=t):go=go.next=t),e._currentValue}var ko={},Eo={current:ko},So={current:ko},_o={current:ko};function Oo(e){return e===ko&&a(\"174\"),e}function Co(e,t){_r(_o,t),_r(So,e),_r(Eo,ko);var n=t.nodeType;switch(n){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:er(null,\"\");break;default:t=er(t=(n=8===n?t.parentNode:t).namespaceURI||null,n=n.tagName)}Sr(Eo),_r(Eo,t)}function To(e){Sr(Eo),Sr(So),Sr(_o)}function jo(e){Oo(_o.current);var t=Oo(Eo.current),n=er(t,e.type);t!==n&&(_r(So,e),_r(Eo,n))}function Ao(e){So.current===e&&(Sr(Eo),Sr(So))}function Io(e,t){if(e&&e.defaultProps)for(var n in t=o({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}var Po=qe.ReactCurrentOwner,Ro=(new r.Component).refs;function No(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:o({},t,n),e.memoizedState=n,null!==(r=e.updateQueue)&&0===e.expirationTime&&(r.baseState=n)}var Lo={isMounted:function(e){return!!(e=e._reactInternalFiber)&&2===tn(e)},enqueueSetState:function(e,t,n){e=e._reactInternalFiber;var r=Sa(),o=ro(r=Xi(r,e));o.payload=t,null!=n&&(o.callback=n),Hi(),io(e,o),Zi(e,r)},enqueueReplaceState:function(e,t,n){e=e._reactInternalFiber;var r=Sa(),o=ro(r=Xi(r,e));o.tag=1,o.payload=t,null!=n&&(o.callback=n),Hi(),io(e,o),Zi(e,r)},enqueueForceUpdate:function(e,t){e=e._reactInternalFiber;var n=Sa(),r=ro(n=Xi(n,e));r.tag=2,null!=t&&(r.callback=t),Hi(),io(e,r),Zi(e,n)}};function Mo(e,t,n,r,o,i,a){return\"function\"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,i,a):!t.prototype||!t.prototype.isPureReactComponent||(!en(n,r)||!en(o,i))}function Do(e,t,n){var r=!1,o=Or,i=t.contextType;return\"object\"==typeof i&&null!==i?i=Po.currentDispatcher.readContext(i):(o=Ir(t)?jr:Cr.current,i=(r=null!=(r=t.contextTypes))?Ar(e,o):Or),t=new t(n,i),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=Lo,e.stateNode=t,t._reactInternalFiber=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=o,e.__reactInternalMemoizedMaskedChildContext=i),t}function Fo(e,t,n,r){e=t.state,\"function\"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),\"function\"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&Lo.enqueueReplaceState(t,t.state,null)}function Uo(e,t,n,r){var o=e.stateNode;o.props=n,o.state=e.memoizedState,o.refs=Ro;var i=t.contextType;\"object\"==typeof i&&null!==i?o.context=Po.currentDispatcher.readContext(i):(i=Ir(t)?jr:Cr.current,o.context=Ar(e,i)),null!==(i=e.updateQueue)&&(co(e,i,n,o,r),o.state=e.memoizedState),\"function\"==typeof(i=t.getDerivedStateFromProps)&&(No(e,t,i,n),o.state=e.memoizedState),\"function\"==typeof t.getDerivedStateFromProps||\"function\"==typeof o.getSnapshotBeforeUpdate||\"function\"!=typeof o.UNSAFE_componentWillMount&&\"function\"!=typeof o.componentWillMount||(t=o.state,\"function\"==typeof o.componentWillMount&&o.componentWillMount(),\"function\"==typeof o.UNSAFE_componentWillMount&&o.UNSAFE_componentWillMount(),t!==o.state&&Lo.enqueueReplaceState(o,o.state,null),null!==(i=e.updateQueue)&&(co(e,i,n,o,r),o.state=e.memoizedState)),\"function\"==typeof o.componentDidMount&&(e.effectTag|=4)}var Bo=Array.isArray;function zo(e,t,n){if(null!==(e=n.ref)&&\"function\"!=typeof e&&\"object\"!=typeof e){if(n._owner){n=n._owner;var r=void 0;n&&(1!==n.tag&&a(\"289\"),r=n.stateNode),r||a(\"147\",e);var o=\"\"+e;return null!==t&&null!==t.ref&&\"function\"==typeof t.ref&&t.ref._stringRef===o?t.ref:((t=function(e){var t=r.refs;t===Ro&&(t=r.refs={}),null===e?delete t[o]:t[o]=e})._stringRef=o,t)}\"string\"!=typeof e&&a(\"284\"),n._owner||a(\"290\",e)}return e}function $o(e,t){\"textarea\"!==e.type&&a(\"31\",\"[object Object]\"===Object.prototype.toString.call(t)?\"object with keys {\"+Object.keys(t).join(\", \")+\"}\":t,\"\")}function Wo(e){function t(t,n){if(e){var r=t.lastEffect;null!==r?(r.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.effectTag=8}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function o(e,t,n){return(e=qr(e,t)).index=0,e.sibling=null,e}function i(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.effectTag=2,n):r:(t.effectTag=2,n):n}function s(t){return e&&null===t.alternate&&(t.effectTag=2),t}function l(e,t,n,r){return null===t||6!==t.tag?((t=Qr(n,e.mode,r)).return=e,t):((t=o(t,n)).return=e,t)}function c(e,t,n,r){return null!==t&&t.elementType===n.type?((r=o(t,n.props)).ref=zo(e,t,n),r.return=e,r):((r=Hr(n.type,n.key,n.props,null,e.mode,r)).ref=zo(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Gr(n,e.mode,r)).return=e,t):((t=o(t,n.children||[])).return=e,t)}function p(e,t,n,r,i){return null===t||7!==t.tag?((t=Yr(n,e.mode,r,i)).return=e,t):((t=o(t,n)).return=e,t)}function f(e,t,n){if(\"string\"==typeof t||\"number\"==typeof t)return(t=Qr(\"\"+t,e.mode,n)).return=e,t;if(\"object\"==typeof t&&null!==t){switch(t.$$typeof){case Ve:return(n=Hr(t.type,t.key,t.props,null,e.mode,n)).ref=zo(e,null,t),n.return=e,n;case Qe:return(t=Gr(t,e.mode,n)).return=e,t}if(Bo(t)||at(t))return(t=Yr(t,e.mode,n,null)).return=e,t;$o(e,t)}return null}function d(e,t,n,r){var o=null!==t?t.key:null;if(\"string\"==typeof n||\"number\"==typeof n)return null!==o?null:l(e,t,\"\"+n,r);if(\"object\"==typeof n&&null!==n){switch(n.$$typeof){case Ve:return n.key===o?n.type===Ge?p(e,t,n.props.children,r,o):c(e,t,n,r):null;case Qe:return n.key===o?u(e,t,n,r):null}if(Bo(n)||at(n))return null!==o?null:p(e,t,n,r,null);$o(e,n)}return null}function h(e,t,n,r,o){if(\"string\"==typeof r||\"number\"==typeof r)return l(t,e=e.get(n)||null,\"\"+r,o);if(\"object\"==typeof r&&null!==r){switch(r.$$typeof){case Ve:return e=e.get(null===r.key?n:r.key)||null,r.type===Ge?p(t,e,r.props.children,o,r.key):c(t,e,r,o);case Qe:return u(t,e=e.get(null===r.key?n:r.key)||null,r,o)}if(Bo(r)||at(r))return p(t,e=e.get(n)||null,r,o,null);$o(t,r)}return null}function m(o,a,s,l){for(var c=null,u=null,p=a,m=a=0,g=null;null!==p&&m<s.length;m++){p.index>m?(g=p,p=null):g=p.sibling;var y=d(o,p,s[m],l);if(null===y){null===p&&(p=g);break}e&&p&&null===y.alternate&&t(o,p),a=i(y,a,m),null===u?c=y:u.sibling=y,u=y,p=g}if(m===s.length)return n(o,p),c;if(null===p){for(;m<s.length;m++)(p=f(o,s[m],l))&&(a=i(p,a,m),null===u?c=p:u.sibling=p,u=p);return c}for(p=r(o,p);m<s.length;m++)(g=h(p,o,m,s[m],l))&&(e&&null!==g.alternate&&p.delete(null===g.key?m:g.key),a=i(g,a,m),null===u?c=g:u.sibling=g,u=g);return e&&p.forEach(function(e){return t(o,e)}),c}function g(o,s,l,c){var u=at(l);\"function\"!=typeof u&&a(\"150\"),null==(l=u.call(l))&&a(\"151\");for(var p=u=null,m=s,g=s=0,y=null,v=l.next();null!==m&&!v.done;g++,v=l.next()){m.index>g?(y=m,m=null):y=m.sibling;var b=d(o,m,v.value,c);if(null===b){m||(m=y);break}e&&m&&null===b.alternate&&t(o,m),s=i(b,s,g),null===p?u=b:p.sibling=b,p=b,m=y}if(v.done)return n(o,m),u;if(null===m){for(;!v.done;g++,v=l.next())null!==(v=f(o,v.value,c))&&(s=i(v,s,g),null===p?u=v:p.sibling=v,p=v);return u}for(m=r(o,m);!v.done;g++,v=l.next())null!==(v=h(m,o,g,v.value,c))&&(e&&null!==v.alternate&&m.delete(null===v.key?g:v.key),s=i(v,s,g),null===p?u=v:p.sibling=v,p=v);return e&&m.forEach(function(e){return t(o,e)}),u}return function(e,r,i,l){var c=\"object\"==typeof i&&null!==i&&i.type===Ge&&null===i.key;c&&(i=i.props.children);var u=\"object\"==typeof i&&null!==i;if(u)switch(i.$$typeof){case Ve:e:{for(u=i.key,c=r;null!==c;){if(c.key===u){if(7===c.tag?i.type===Ge:c.elementType===i.type){n(e,c.sibling),(r=o(c,i.type===Ge?i.props.children:i.props)).ref=zo(e,c,i),r.return=e,e=r;break e}n(e,c);break}t(e,c),c=c.sibling}i.type===Ge?((r=Yr(i.props.children,e.mode,l,i.key)).return=e,e=r):((l=Hr(i.type,i.key,i.props,null,e.mode,l)).ref=zo(e,r,i),l.return=e,e=l)}return s(e);case Qe:e:{for(c=i.key;null!==r;){if(r.key===c){if(4===r.tag&&r.stateNode.containerInfo===i.containerInfo&&r.stateNode.implementation===i.implementation){n(e,r.sibling),(r=o(r,i.children||[])).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=Gr(i,e.mode,l)).return=e,e=r}return s(e)}if(\"string\"==typeof i||\"number\"==typeof i)return i=\"\"+i,null!==r&&6===r.tag?(n(e,r.sibling),(r=o(r,i)).return=e,e=r):(n(e,r),(r=Qr(i,e.mode,l)).return=e,e=r),s(e);if(Bo(i))return m(e,r,i,l);if(at(i))return g(e,r,i,l);if(u&&$o(e,i),void 0===i&&!c)switch(e.tag){case 1:case 0:a(\"152\",(l=e.type).displayName||l.name||\"Component\")}return n(e,r)}}var qo=Wo(!0),Ho=Wo(!1),Yo=null,Vo=null,Qo=!1;function Go(e,t){var n=$r(5,null,null,0);n.elementType=\"DELETED\",n.type=\"DELETED\",n.stateNode=t,n.return=e,n.effectTag=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Xo(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=\"\"===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function Ko(e){if(Qo){var t=Vo;if(t){var n=t;if(!Xo(e,t)){if(!(t=wr(n))||!Xo(e,t))return e.effectTag|=2,Qo=!1,void(Yo=e);Go(Yo,n)}Yo=e,Vo=xr(t)}else e.effectTag|=2,Qo=!1,Yo=e}}function Jo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag;)e=e.return;Yo=e}function Zo(e){if(e!==Yo)return!1;if(!Qo)return Jo(e),Qo=!0,!1;var t=e.type;if(5!==e.tag||\"head\"!==t&&\"body\"!==t&&!yr(t,e.memoizedProps))for(t=Vo;t;)Go(e,t),t=wr(t);return Jo(e),Vo=Yo?wr(e.stateNode):null,!0}function ei(){Vo=Yo=null,Qo=!1}var ti=qe.ReactCurrentOwner;function ni(e,t,n,r){t.child=null===e?Ho(t,null,n,r):qo(t,e.child,n,r)}function ri(e,t,n,r,o){n=n.render;var i=t.ref;return wo(t),r=n(r,i),t.effectTag|=1,ni(e,t,r,o),t.child}function oi(e,t,n,r,o,i){if(null===e){var a=n.type;return\"function\"!=typeof a||Wr(a)||void 0!==a.defaultProps||null!==n.compare?((e=Hr(n.type,null,r,null,t.mode,i)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,ii(e,t,a,r,o,i))}return a=e.child,o<i&&(o=a.memoizedProps,(n=null!==(n=n.compare)?n:en)(o,r)&&e.ref===t.ref)?fi(e,t,i):(t.effectTag|=1,(e=qr(a,r)).ref=t.ref,e.return=t,t.child=e)}function ii(e,t,n,r,o,i){return null!==e&&o<i&&en(e.memoizedProps,r)&&e.ref===t.ref?fi(e,t,i):si(e,t,n,r,i)}function ai(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.effectTag|=128)}function si(e,t,n,r,o){var i=Ir(n)?jr:Cr.current;return i=Ar(t,i),wo(t),n=n(r,i),t.effectTag|=1,ni(e,t,n,o),t.child}function li(e,t,n,r,o){if(Ir(n)){var i=!0;Mr(t)}else i=!1;if(wo(t),null===t.stateNode)null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),Do(t,n,r),Uo(t,n,r,o),r=!0;else if(null===e){var a=t.stateNode,s=t.memoizedProps;a.props=s;var l=a.context,c=n.contextType;\"object\"==typeof c&&null!==c?c=Po.currentDispatcher.readContext(c):c=Ar(t,c=Ir(n)?jr:Cr.current);var u=n.getDerivedStateFromProps,p=\"function\"==typeof u||\"function\"==typeof a.getSnapshotBeforeUpdate;p||\"function\"!=typeof a.UNSAFE_componentWillReceiveProps&&\"function\"!=typeof a.componentWillReceiveProps||(s!==r||l!==c)&&Fo(t,a,r,c),eo=!1;var f=t.memoizedState;l=a.state=f;var d=t.updateQueue;null!==d&&(co(t,d,r,a,o),l=t.memoizedState),s!==r||f!==l||Tr.current||eo?(\"function\"==typeof u&&(No(t,n,u,r),l=t.memoizedState),(s=eo||Mo(t,n,s,r,f,l,c))?(p||\"function\"!=typeof a.UNSAFE_componentWillMount&&\"function\"!=typeof a.componentWillMount||(\"function\"==typeof a.componentWillMount&&a.componentWillMount(),\"function\"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount()),\"function\"==typeof a.componentDidMount&&(t.effectTag|=4)):(\"function\"==typeof a.componentDidMount&&(t.effectTag|=4),t.memoizedProps=r,t.memoizedState=l),a.props=r,a.state=l,a.context=c,r=s):(\"function\"==typeof a.componentDidMount&&(t.effectTag|=4),r=!1)}else a=t.stateNode,s=t.memoizedProps,a.props=t.type===t.elementType?s:Io(t.type,s),l=a.context,\"object\"==typeof(c=n.contextType)&&null!==c?c=Po.currentDispatcher.readContext(c):c=Ar(t,c=Ir(n)?jr:Cr.current),(p=\"function\"==typeof(u=n.getDerivedStateFromProps)||\"function\"==typeof a.getSnapshotBeforeUpdate)||\"function\"!=typeof a.UNSAFE_componentWillReceiveProps&&\"function\"!=typeof a.componentWillReceiveProps||(s!==r||l!==c)&&Fo(t,a,r,c),eo=!1,l=t.memoizedState,f=a.state=l,null!==(d=t.updateQueue)&&(co(t,d,r,a,o),f=t.memoizedState),s!==r||l!==f||Tr.current||eo?(\"function\"==typeof u&&(No(t,n,u,r),f=t.memoizedState),(u=eo||Mo(t,n,s,r,l,f,c))?(p||\"function\"!=typeof a.UNSAFE_componentWillUpdate&&\"function\"!=typeof a.componentWillUpdate||(\"function\"==typeof a.componentWillUpdate&&a.componentWillUpdate(r,f,c),\"function\"==typeof a.UNSAFE_componentWillUpdate&&a.UNSAFE_componentWillUpdate(r,f,c)),\"function\"==typeof a.componentDidUpdate&&(t.effectTag|=4),\"function\"==typeof a.getSnapshotBeforeUpdate&&(t.effectTag|=256)):(\"function\"!=typeof a.componentDidUpdate||s===e.memoizedProps&&l===e.memoizedState||(t.effectTag|=4),\"function\"!=typeof a.getSnapshotBeforeUpdate||s===e.memoizedProps&&l===e.memoizedState||(t.effectTag|=256),t.memoizedProps=r,t.memoizedState=f),a.props=r,a.state=f,a.context=c,r=u):(\"function\"!=typeof a.componentDidUpdate||s===e.memoizedProps&&l===e.memoizedState||(t.effectTag|=4),\"function\"!=typeof a.getSnapshotBeforeUpdate||s===e.memoizedProps&&l===e.memoizedState||(t.effectTag|=256),r=!1);return ci(e,t,n,r,i,o)}function ci(e,t,n,r,o,i){ai(e,t);var a=0!=(64&t.effectTag);if(!r&&!a)return o&&Dr(t,n,!1),fi(e,t,i);r=t.stateNode,ti.current=t;var s=a&&\"function\"!=typeof n.getDerivedStateFromError?null:r.render();return t.effectTag|=1,null!==e&&a?(t.child=qo(t,e.child,null,i),t.child=qo(t,null,s,i)):ni(e,t,s,i),t.memoizedState=r.state,o&&Dr(t,n,!0),t.child}function ui(e){var t=e.stateNode;t.pendingContext?Nr(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Nr(0,t.context,!1),Co(e,t.containerInfo)}function pi(e,t,n){var r=t.mode,o=t.pendingProps,i=t.memoizedState;if(0==(64&t.effectTag)){i=null;var a=!1}else i={timedOutAt:null!==i?i.timedOutAt:0},a=!0,t.effectTag&=-65;return null===e?a?(a=o.fallback,o=Yr(null,r,0,null),0==(1&t.mode)&&(o.child=null!==t.memoizedState?t.child.child:t.child),r=Yr(a,r,n,null),o.sibling=r,(n=o).return=r.return=t):n=r=Ho(t,null,o.children,n):null!==e.memoizedState?(e=(r=e.child).sibling,a?(n=o.fallback,o=qr(r,r.pendingProps),0==(1&t.mode)&&((a=null!==t.memoizedState?t.child.child:t.child)!==r.child&&(o.child=a)),r=o.sibling=qr(e,n,e.expirationTime),n=o,o.childExpirationTime=0,n.return=r.return=t):n=r=qo(t,r.child,o.children,n)):(e=e.child,a?(a=o.fallback,(o=Yr(null,r,0,null)).child=e,0==(1&t.mode)&&(o.child=null!==t.memoizedState?t.child.child:t.child),(r=o.sibling=Yr(a,r,n,null)).effectTag|=2,n=o,o.childExpirationTime=0,n.return=r.return=t):r=n=qo(t,e,o.children,n)),t.memoizedState=i,t.child=n,r}function fi(e,t,n){if(null!==e&&(t.firstContextDependency=e.firstContextDependency),t.childExpirationTime<n)return null;if(null!==e&&t.child!==e.child&&a(\"153\"),null!==t.child){for(n=qr(e=t.child,e.pendingProps,e.expirationTime),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=qr(e,e.pendingProps,e.expirationTime)).return=t;n.sibling=null}return t.child}function di(e,t,n){var r=t.expirationTime;if(null!==e&&e.memoizedProps===t.pendingProps&&!Tr.current&&r<n){switch(t.tag){case 3:ui(t),ei();break;case 5:jo(t);break;case 1:Ir(t.type)&&Mr(t);break;case 4:Co(t,t.stateNode.containerInfo);break;case 10:vo(t,t.memoizedProps.value);break;case 13:if(null!==t.memoizedState)return 0!==(r=t.child.childExpirationTime)&&r>=n?pi(e,t,n):null!==(t=fi(e,t,n))?t.sibling:null}return fi(e,t,n)}switch(t.expirationTime=0,t.tag){case 2:r=t.elementType,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),e=t.pendingProps;var o=Ar(t,Cr.current);if(wo(t),o=r(e,o),t.effectTag|=1,\"object\"==typeof o&&null!==o&&\"function\"==typeof o.render&&void 0===o.$$typeof){if(t.tag=1,Ir(r)){var i=!0;Mr(t)}else i=!1;t.memoizedState=null!==o.state&&void 0!==o.state?o.state:null;var s=r.getDerivedStateFromProps;\"function\"==typeof s&&No(t,r,s,e),o.updater=Lo,t.stateNode=o,o._reactInternalFiber=t,Uo(t,r,e,n),t=ci(null,t,r,!0,i,n)}else t.tag=0,ni(null,t,o,n),t=t.child;return t;case 16:switch(o=t.elementType,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),i=t.pendingProps,e=function(e){var t=e._result;switch(e._status){case 1:return t;case 2:case 0:throw t;default:throw e._status=0,(t=(t=e._ctor)()).then(function(t){0===e._status&&(t=t.default,e._status=1,e._result=t)},function(t){0===e._status&&(e._status=2,e._result=t)}),e._result=t,t}}(o),t.type=e,o=t.tag=function(e){if(\"function\"==typeof e)return Wr(e)?1:0;if(null!=e){if((e=e.$$typeof)===tt)return 11;if(e===rt)return 14}return 2}(e),i=Io(e,i),s=void 0,o){case 0:s=si(null,t,e,i,n);break;case 1:s=li(null,t,e,i,n);break;case 11:s=ri(null,t,e,i,n);break;case 14:s=oi(null,t,e,Io(e.type,i),r,n);break;default:a(\"283\",e)}return s;case 0:return r=t.type,o=t.pendingProps,si(e,t,r,o=t.elementType===r?o:Io(r,o),n);case 1:return r=t.type,o=t.pendingProps,li(e,t,r,o=t.elementType===r?o:Io(r,o),n);case 3:return ui(t),null===(r=t.updateQueue)&&a(\"282\"),o=null!==(o=t.memoizedState)?o.element:null,co(t,r,t.pendingProps,null,n),(r=t.memoizedState.element)===o?(ei(),t=fi(e,t,n)):(o=t.stateNode,(o=(null===e||null===e.child)&&o.hydrate)&&(Vo=xr(t.stateNode.containerInfo),Yo=t,o=Qo=!0),o?(t.effectTag|=2,t.child=Ho(t,null,r,n)):(ni(e,t,r,n),ei()),t=t.child),t;case 5:return jo(t),null===e&&Ko(t),r=t.type,o=t.pendingProps,i=null!==e?e.memoizedProps:null,s=o.children,yr(r,o)?s=null:null!==i&&yr(r,i)&&(t.effectTag|=16),ai(e,t),1!==n&&1&t.mode&&o.hidden?(t.expirationTime=1,t=null):(ni(e,t,s,n),t=t.child),t;case 6:return null===e&&Ko(t),null;case 13:return pi(e,t,n);case 4:return Co(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=qo(t,null,r,n):ni(e,t,r,n),t.child;case 11:return r=t.type,o=t.pendingProps,ri(e,t,r,o=t.elementType===r?o:Io(r,o),n);case 7:return ni(e,t,t.pendingProps,n),t.child;case 8:case 12:return ni(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,o=t.pendingProps,s=t.memoizedProps,vo(t,i=o.value),null!==s){var l=s.value;if(0===(i=l===i&&(0!==l||1/l==1/i)||l!=l&&i!=i?0:0|(\"function\"==typeof r._calculateChangedBits?r._calculateChangedBits(l,i):1073741823))){if(s.children===o.children&&!Tr.current){t=fi(e,t,n);break e}}else for(null!==(s=t.child)&&(s.return=t);null!==s;){if(null!==(l=s.firstContextDependency))do{if(l.context===r&&0!=(l.observedBits&i)){if(1===s.tag){var c=ro(n);c.tag=2,io(s,c)}s.expirationTime<n&&(s.expirationTime=n),null!==(c=s.alternate)&&c.expirationTime<n&&(c.expirationTime=n);for(var u=s.return;null!==u;){if(c=u.alternate,u.childExpirationTime<n)u.childExpirationTime=n,null!==c&&c.childExpirationTime<n&&(c.childExpirationTime=n);else{if(!(null!==c&&c.childExpirationTime<n))break;c.childExpirationTime=n}u=u.return}}c=s.child,l=l.next}while(null!==l);else c=10===s.tag&&s.type===t.type?null:s.child;if(null!==c)c.return=s;else for(c=s;null!==c;){if(c===t){c=null;break}if(null!==(s=c.sibling)){s.return=c.return,c=s;break}c=c.return}s=c}}ni(e,t,o.children,n),t=t.child}return t;case 9:return o=t.type,r=(i=t.pendingProps).children,wo(t),r=r(o=xo(o,i.unstable_observedBits)),t.effectTag|=1,ni(e,t,r,n),t.child;case 14:return oi(e,t,o=t.type,i=Io(o.type,t.pendingProps),r,n);case 15:return ii(e,t,t.type,t.pendingProps,r,n);case 17:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Io(r,o),null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),t.tag=1,Ir(r)?(e=!0,Mr(t)):e=!1,wo(t),Do(t,r,o),Uo(t,r,o,n),ci(null,t,r,!0,e,n);default:a(\"156\")}}function hi(e){e.effectTag|=4}var mi=void 0,gi=void 0,yi=void 0,vi=void 0;function bi(e,t){var n=t.source,r=t.stack;null===r&&null!==n&&(r=lt(n)),null!==n&&st(n.type),t=t.value,null!==e&&1===e.tag&&st(e.type);try{console.error(t)}catch(e){setTimeout(function(){throw e})}}function wi(e){var t=e.ref;if(null!==t)if(\"function\"==typeof t)try{t(null)}catch(t){Gi(e,t)}else t.current=null}function xi(e){switch(\"function\"==typeof Ur&&Ur(e),e.tag){case 0:case 11:case 14:case 15:var t=e.updateQueue;if(null!==t&&null!==(t=t.lastEffect)){var n=t=t.next;do{var r=n.destroy;if(null!==r){var o=e;try{r()}catch(e){Gi(o,e)}}n=n.next}while(n!==t)}break;case 1:if(wi(e),\"function\"==typeof(t=e.stateNode).componentWillUnmount)try{t.props=e.memoizedProps,t.state=e.memoizedState,t.componentWillUnmount()}catch(t){Gi(e,t)}break;case 5:wi(e);break;case 4:Si(e)}}function ki(e){return 5===e.tag||3===e.tag||4===e.tag}function Ei(e){e:{for(var t=e.return;null!==t;){if(ki(t)){var n=t;break e}t=t.return}a(\"160\"),n=void 0}var r=t=void 0;switch(n.tag){case 5:t=n.stateNode,r=!1;break;case 3:case 4:t=n.stateNode.containerInfo,r=!0;break;default:a(\"161\")}16&n.effectTag&&(or(t,\"\"),n.effectTag&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||ki(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag;){if(2&n.effectTag)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.effectTag)){n=n.stateNode;break e}}for(var o=e;;){if(5===o.tag||6===o.tag)if(n)if(r){var i=t,s=o.stateNode,l=n;8===i.nodeType?i.parentNode.insertBefore(s,l):i.insertBefore(s,l)}else t.insertBefore(o.stateNode,n);else r?(s=t,l=o.stateNode,8===s.nodeType?(i=s.parentNode).insertBefore(l,s):(i=s).appendChild(l),null!=(s=s._reactRootContainer)||null!==i.onclick||(i.onclick=dr)):t.appendChild(o.stateNode);else if(4!==o.tag&&null!==o.child){o.child.return=o,o=o.child;continue}if(o===e)break;for(;null===o.sibling;){if(null===o.return||o.return===e)return;o=o.return}o.sibling.return=o.return,o=o.sibling}}function Si(e){for(var t=e,n=!1,r=void 0,o=void 0;;){if(!n){n=t.return;e:for(;;){switch(null===n&&a(\"160\"),n.tag){case 5:r=n.stateNode,o=!1;break e;case 3:case 4:r=n.stateNode.containerInfo,o=!0;break e}n=n.return}n=!0}if(5===t.tag||6===t.tag){e:for(var i=t,s=i;;)if(xi(s),null!==s.child&&4!==s.tag)s.child.return=s,s=s.child;else{if(s===i)break;for(;null===s.sibling;){if(null===s.return||s.return===i)break e;s=s.return}s.sibling.return=s.return,s=s.sibling}o?(i=r,s=t.stateNode,8===i.nodeType?i.parentNode.removeChild(s):i.removeChild(s)):r.removeChild(t.stateNode)}else if(4===t.tag?(r=t.stateNode.containerInfo,o=!0):xi(t),null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;4===(t=t.return).tag&&(n=!1)}t.sibling.return=t.return,t=t.sibling}}function _i(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 1:break;case 5:var n=t.stateNode;if(null!=n){var r=t.memoizedProps,o=null!==e?e.memoizedProps:r;e=t.type;var i=t.updateQueue;if(t.updateQueue=null,null!==i){for(n[N]=r,\"input\"===e&&\"radio\"===r.type&&null!=r.name&&xt(n,r),pr(e,o),t=pr(e,r),o=0;o<i.length;o+=2){var s=i[o],l=i[o+1];\"style\"===s?lr(n,l):\"dangerouslySetInnerHTML\"===s?rr(n,l):\"children\"===s?or(n,l):yt(n,s,l,t)}switch(e){case\"input\":kt(n,r);break;case\"textarea\":Xn(n,r);break;case\"select\":t=n._wrapperState.wasMultiple,n._wrapperState.wasMultiple=!!r.multiple,null!=(e=r.value)?Vn(n,!!r.multiple,e,!1):t!==!!r.multiple&&(null!=r.defaultValue?Vn(n,!!r.multiple,r.defaultValue,!0):Vn(n,!!r.multiple,r.multiple?[]:\"\",!1))}}}break;case 6:null===t.stateNode&&a(\"162\"),t.stateNode.nodeValue=t.memoizedProps;break;case 3:case 12:break;case 13:if(e=t,null===(n=t.memoizedState)?r=!1:(r=!0,e=t.child,0===n.timedOutAt&&(n.timedOutAt=Sa())),null!==e)e:for(t=n=e;;){if(5===t.tag)e=t.stateNode,r?e.style.display=\"none\":(e=t.stateNode,i=null!=(i=t.memoizedProps.style)&&i.hasOwnProperty(\"display\")?i.display:null,e.style.display=sr(\"display\",i));else if(6===t.tag)t.stateNode.nodeValue=r?\"\":t.memoizedProps;else{if(13===t.tag&&null!==t.memoizedState){(e=t.child.sibling).return=t,t=e;continue}if(null!==t.child){t.child.return=t,t=t.child;continue}}if(t===n)break e;for(;null===t.sibling;){if(null===t.return||t.return===n)break e;t=t.return}t.sibling.return=t.return,t=t.sibling}break;case 17:break;default:a(\"163\")}}function Oi(e,t,n){(n=ro(n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Na(r),bi(e,t)},n}function Ci(e,t,n){(n=ro(n)).tag=3;var r=e.type.getDerivedStateFromError;if(\"function\"==typeof r){var o=t.value;n.payload=function(){return r(o)}}var i=e.stateNode;return null!==i&&\"function\"==typeof i.componentDidCatch&&(n.callback=function(){\"function\"!=typeof r&&(null===Wi?Wi=new Set([this]):Wi.add(this));var n=t.value,o=t.stack;bi(e,t),this.componentDidCatch(n,{componentStack:null!==o?o:\"\"})}),n}function Ti(e){switch(e.tag){case 1:Ir(e.type)&&Pr();var t=e.effectTag;return 2048&t?(e.effectTag=-2049&t|64,e):null;case 3:return To(),Rr(),0!=(64&(t=e.effectTag))&&a(\"285\"),e.effectTag=-2049&t|64,e;case 5:return Ao(e),null;case 13:return 2048&(t=e.effectTag)?(e.effectTag=-2049&t|64,e):null;case 4:return To(),null;case 10:return bo(e),null;default:return null}}mi=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},gi=function(){},yi=function(e,t,n,r,i){var a=e.memoizedProps;if(a!==r){var s=t.stateNode;switch(Oo(Eo.current),e=null,n){case\"input\":a=bt(s,a),r=bt(s,r),e=[];break;case\"option\":a=Yn(s,a),r=Yn(s,r),e=[];break;case\"select\":a=o({},a,{value:void 0}),r=o({},r,{value:void 0}),e=[];break;case\"textarea\":a=Qn(s,a),r=Qn(s,r),e=[];break;default:\"function\"!=typeof a.onClick&&\"function\"==typeof r.onClick&&(s.onclick=dr)}ur(n,r),s=n=void 0;var l=null;for(n in a)if(!r.hasOwnProperty(n)&&a.hasOwnProperty(n)&&null!=a[n])if(\"style\"===n){var c=a[n];for(s in c)c.hasOwnProperty(s)&&(l||(l={}),l[s]=\"\")}else\"dangerouslySetInnerHTML\"!==n&&\"children\"!==n&&\"suppressContentEditableWarning\"!==n&&\"suppressHydrationWarning\"!==n&&\"autoFocus\"!==n&&(b.hasOwnProperty(n)?e||(e=[]):(e=e||[]).push(n,null));for(n in r){var u=r[n];if(c=null!=a?a[n]:void 0,r.hasOwnProperty(n)&&u!==c&&(null!=u||null!=c))if(\"style\"===n)if(c){for(s in c)!c.hasOwnProperty(s)||u&&u.hasOwnProperty(s)||(l||(l={}),l[s]=\"\");for(s in u)u.hasOwnProperty(s)&&c[s]!==u[s]&&(l||(l={}),l[s]=u[s])}else l||(e||(e=[]),e.push(n,l)),l=u;else\"dangerouslySetInnerHTML\"===n?(u=u?u.__html:void 0,c=c?c.__html:void 0,null!=u&&c!==u&&(e=e||[]).push(n,\"\"+u)):\"children\"===n?c===u||\"string\"!=typeof u&&\"number\"!=typeof u||(e=e||[]).push(n,\"\"+u):\"suppressContentEditableWarning\"!==n&&\"suppressHydrationWarning\"!==n&&(b.hasOwnProperty(n)?(null!=u&&fr(i,n),e||c===u||(e=[])):(e=e||[]).push(n,u))}l&&(e=e||[]).push(\"style\",l),i=e,(t.updateQueue=i)&&hi(t)}},vi=function(e,t,n,r){n!==r&&hi(t)};var ji={readContext:xo},Ai=qe.ReactCurrentOwner,Ii=1073741822,Pi=0,Ri=!1,Ni=null,Li=null,Mi=0,Di=-1,Fi=!1,Ui=null,Bi=!1,zi=null,$i=null,Wi=null;function qi(){if(null!==Ni)for(var e=Ni.return;null!==e;){var t=e;switch(t.tag){case 1:var n=t.type.childContextTypes;null!=n&&Pr();break;case 3:To(),Rr();break;case 5:Ao(t);break;case 4:To();break;case 10:bo(t)}e=e.return}Li=null,Mi=0,Di=-1,Fi=!1,Ni=null}function Hi(){null!==$i&&(i.unstable_cancelCallback(zi),$i())}function Yi(e){for(;;){var t=e.alternate,n=e.return,r=e.sibling;if(0==(1024&e.effectTag)){Ni=e;e:{var i=t,s=Mi,l=(t=e).pendingProps;switch(t.tag){case 2:case 16:break;case 15:case 0:break;case 1:Ir(t.type)&&Pr();break;case 3:To(),Rr(),(l=t.stateNode).pendingContext&&(l.context=l.pendingContext,l.pendingContext=null),null!==i&&null!==i.child||(Zo(t),t.effectTag&=-3),gi(t);break;case 5:Ao(t);var c=Oo(_o.current);if(s=t.type,null!==i&&null!=t.stateNode)yi(i,t,s,l,c),i.ref!==t.ref&&(t.effectTag|=128);else if(l){var u=Oo(Eo.current);if(Zo(t)){i=(l=t).stateNode;var p=l.type,f=l.memoizedProps,d=c;switch(i[R]=l,i[N]=f,s=void 0,c=p){case\"iframe\":case\"object\":_n(\"load\",i);break;case\"video\":case\"audio\":for(p=0;p<te.length;p++)_n(te[p],i);break;case\"source\":_n(\"error\",i);break;case\"img\":case\"image\":case\"link\":_n(\"error\",i),_n(\"load\",i);break;case\"form\":_n(\"reset\",i),_n(\"submit\",i);break;case\"details\":_n(\"toggle\",i);break;case\"input\":wt(i,f),_n(\"invalid\",i),fr(d,\"onChange\");break;case\"select\":i._wrapperState={wasMultiple:!!f.multiple},_n(\"invalid\",i),fr(d,\"onChange\");break;case\"textarea\":Gn(i,f),_n(\"invalid\",i),fr(d,\"onChange\")}for(s in ur(c,f),p=null,f)f.hasOwnProperty(s)&&(u=f[s],\"children\"===s?\"string\"==typeof u?i.textContent!==u&&(p=[\"children\",u]):\"number\"==typeof u&&i.textContent!==\"\"+u&&(p=[\"children\",\"\"+u]):b.hasOwnProperty(s)&&null!=u&&fr(d,s));switch(c){case\"input\":$e(i),Et(i,f,!0);break;case\"textarea\":$e(i),Kn(i);break;case\"select\":case\"option\":break;default:\"function\"==typeof f.onClick&&(i.onclick=dr)}s=p,l.updateQueue=s,(l=null!==s)&&hi(t)}else{f=t,i=s,d=l,p=9===c.nodeType?c:c.ownerDocument,u===Jn.html&&(u=Zn(i)),u===Jn.html?\"script\"===i?((i=p.createElement(\"div\")).innerHTML=\"<script><\\/script>\",p=i.removeChild(i.firstChild)):\"string\"==typeof d.is?p=p.createElement(i,{is:d.is}):(p=p.createElement(i),\"select\"===i&&d.multiple&&(p.multiple=!0)):p=p.createElementNS(u,i),(i=p)[R]=f,i[N]=l,mi(i,t,!1,!1),d=i;var h=c,m=pr(p=s,f=l);switch(p){case\"iframe\":case\"object\":_n(\"load\",d),c=f;break;case\"video\":case\"audio\":for(c=0;c<te.length;c++)_n(te[c],d);c=f;break;case\"source\":_n(\"error\",d),c=f;break;case\"img\":case\"image\":case\"link\":_n(\"error\",d),_n(\"load\",d),c=f;break;case\"form\":_n(\"reset\",d),_n(\"submit\",d),c=f;break;case\"details\":_n(\"toggle\",d),c=f;break;case\"input\":wt(d,f),c=bt(d,f),_n(\"invalid\",d),fr(h,\"onChange\");break;case\"option\":c=Yn(d,f);break;case\"select\":d._wrapperState={wasMultiple:!!f.multiple},c=o({},f,{value:void 0}),_n(\"invalid\",d),fr(h,\"onChange\");break;case\"textarea\":Gn(d,f),c=Qn(d,f),_n(\"invalid\",d),fr(h,\"onChange\");break;default:c=f}ur(p,c),u=void 0;var g=p,y=d,v=c;for(u in v)if(v.hasOwnProperty(u)){var w=v[u];\"style\"===u?lr(y,w):\"dangerouslySetInnerHTML\"===u?null!=(w=w?w.__html:void 0)&&rr(y,w):\"children\"===u?\"string\"==typeof w?(\"textarea\"!==g||\"\"!==w)&&or(y,w):\"number\"==typeof w&&or(y,\"\"+w):\"suppressContentEditableWarning\"!==u&&\"suppressHydrationWarning\"!==u&&\"autoFocus\"!==u&&(b.hasOwnProperty(u)?null!=w&&fr(h,u):null!=w&&yt(y,u,w,m))}switch(p){case\"input\":$e(d),Et(d,f,!1);break;case\"textarea\":$e(d),Kn(d);break;case\"option\":null!=f.value&&d.setAttribute(\"value\",\"\"+vt(f.value));break;case\"select\":(c=d).multiple=!!f.multiple,null!=(d=f.value)?Vn(c,!!f.multiple,d,!1):null!=f.defaultValue&&Vn(c,!!f.multiple,f.defaultValue,!0);break;default:\"function\"==typeof c.onClick&&(d.onclick=dr)}(l=gr(s,l))&&hi(t),t.stateNode=i}null!==t.ref&&(t.effectTag|=128)}else null===t.stateNode&&a(\"166\");break;case 6:i&&null!=t.stateNode?vi(i,t,i.memoizedProps,l):(\"string\"!=typeof l&&(null===t.stateNode&&a(\"166\")),i=Oo(_o.current),Oo(Eo.current),Zo(t)?(s=(l=t).stateNode,i=l.memoizedProps,s[R]=l,(l=s.nodeValue!==i)&&hi(t)):(s=t,(l=(9===i.nodeType?i:i.ownerDocument).createTextNode(l))[R]=t,s.stateNode=l));break;case 11:break;case 13:if(l=t.memoizedState,0!=(64&t.effectTag)){t.expirationTime=s,Ni=t;break e}l=null!==l,s=null!==i&&null!==i.memoizedState,null!==i&&!l&&s&&(null!==(i=i.child.sibling)&&(null!==(c=t.firstEffect)?(t.firstEffect=i,i.nextEffect=c):(t.firstEffect=t.lastEffect=i,i.nextEffect=null),i.effectTag=8)),(l!==s||0==(1&t.effectTag)&&l)&&(t.effectTag|=4);break;case 7:case 8:case 12:break;case 4:To(),gi(t);break;case 10:bo(t);break;case 9:case 14:break;case 17:Ir(t.type)&&Pr();break;default:a(\"156\")}Ni=null}if(t=e,1===Mi||1!==t.childExpirationTime){for(l=0,s=t.child;null!==s;)(i=s.expirationTime)>l&&(l=i),(c=s.childExpirationTime)>l&&(l=c),s=s.sibling;t.childExpirationTime=l}if(null!==Ni)return Ni;null!==n&&0==(1024&n.effectTag)&&(null===n.firstEffect&&(n.firstEffect=e.firstEffect),null!==e.lastEffect&&(null!==n.lastEffect&&(n.lastEffect.nextEffect=e.firstEffect),n.lastEffect=e.lastEffect),1<e.effectTag&&(null!==n.lastEffect?n.lastEffect.nextEffect=e:n.firstEffect=e,n.lastEffect=e))}else{if(null!==(e=Ti(e)))return e.effectTag&=1023,e;null!==n&&(n.firstEffect=n.lastEffect=null,n.effectTag|=1024)}if(null!==r)return r;if(null===n)break;e=n}return null}function Vi(e){var t=di(e.alternate,e,Mi);return e.memoizedProps=e.pendingProps,null===t&&(t=Yi(e)),Ai.current=null,t}function Qi(e,t){Ri&&a(\"243\"),Hi(),Ri=!0,Ai.currentDispatcher=ji;var n=e.nextExpirationTimeToWorkOn;n===Mi&&e===Li&&null!==Ni||(qi(),Mi=n,Ni=qr((Li=e).current,null),e.pendingCommitExpirationTime=0);for(var r=!1;;){try{if(t)for(;null!==Ni&&!Ta();)Ni=Vi(Ni);else for(;null!==Ni;)Ni=Vi(Ni)}catch(t){if(yo=go=mo=null,null===Ni)r=!0,Na(t);else{null===Ni&&a(\"271\");var o=Ni,i=o.return;if(null!==i){e:{var s=e,l=i,c=o,u=t;if(i=Mi,c.effectTag|=1024,c.firstEffect=c.lastEffect=null,null!==u&&\"object\"==typeof u&&\"function\"==typeof u.then){var p=u;u=l;var f=-1,d=-1;do{if(13===u.tag){var h=u.alternate;if(null!==h&&null!==(h=h.memoizedState)){d=10*(1073741822-h.timedOutAt);break}\"number\"==typeof(h=u.pendingProps.maxDuration)&&(0>=h?f=0:(-1===f||h<f)&&(f=h))}u=u.return}while(null!==u);u=l;do{if((h=13===u.tag)&&(h=void 0!==u.memoizedProps.fallback&&null===u.memoizedState),h){if(l=Ki.bind(null,s,u,c,0==(1&u.mode)?1073741823:i),p.then(l,l),0==(1&u.mode)){u.effectTag|=64,c.effectTag&=-1957,1===c.tag&&null===c.alternate&&(c.tag=17),c.expirationTime=i;break e}-1===f?s=1073741823:(-1===d&&(d=10*(1073741822-Jr(s,i))-5e3),s=d+f),0<=s&&Di<s&&(Di=s),u.effectTag|=2048,u.expirationTime=i;break e}u=u.return}while(null!==u);u=Error((st(c.type)||\"A React component\")+\" suspended while rendering, but no fallback UI was specified.\\n\\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.\"+lt(c))}Fi=!0,u=fo(u,c),s=l;do{switch(s.tag){case 3:c=u,s.effectTag|=2048,s.expirationTime=i,ao(s,i=Oi(s,c,i));break e;case 1:if(c=u,l=s.type,p=s.stateNode,0==(64&s.effectTag)&&(\"function\"==typeof l.getDerivedStateFromError||null!==p&&\"function\"==typeof p.componentDidCatch&&(null===Wi||!Wi.has(p)))){s.effectTag|=2048,s.expirationTime=i,ao(s,i=Ci(s,c,i));break e}}s=s.return}while(null!==s)}Ni=Yi(o);continue}r=!0,Na(t)}}break}if(Ri=!1,yo=go=mo=Ai.currentDispatcher=null,r)Li=null,e.finishedWork=null;else if(null!==Ni)e.finishedWork=null;else{if(null===(r=e.current.alternate)&&a(\"281\"),Li=null,Fi){if(o=e.latestPendingTime,i=e.latestSuspendedTime,s=e.latestPingedTime,0!==o&&o<n||0!==i&&i<n||0!==s&&s<n)return Kr(e,n),void Ea(e,r,n,e.expirationTime,-1);if(!e.didError&&t)return e.didError=!0,n=e.nextExpirationTimeToWorkOn=n,t=e.expirationTime=1073741823,void Ea(e,r,n,t,-1)}t&&-1!==Di?(Kr(e,n),(t=10*(1073741822-Jr(e,n)))<Di&&(Di=t),t=10*(1073741822-Sa()),t=Di-t,Ea(e,r,n,e.expirationTime,0>t?0:t)):(e.pendingCommitExpirationTime=n,e.finishedWork=r)}}function Gi(e,t){for(var n=e.return;null!==n;){switch(n.tag){case 1:var r=n.stateNode;if(\"function\"==typeof n.type.getDerivedStateFromError||\"function\"==typeof r.componentDidCatch&&(null===Wi||!Wi.has(r)))return io(n,e=Ci(n,e=fo(t,e),1073741823)),void Zi(n,1073741823);break;case 3:return io(n,e=Oi(n,e=fo(t,e),1073741823)),void Zi(n,1073741823)}n=n.return}3===e.tag&&(io(e,n=Oi(e,n=fo(t,e),1073741823)),Zi(e,1073741823))}function Xi(e,t){return 0!==Pi?e=Pi:Ri?e=Bi?1073741823:Mi:1&t.mode?(e=da?1073741822-10*(1+((1073741822-e+15)/10|0)):1073741822-25*(1+((1073741822-e+500)/25|0)),null!==Li&&e===Mi&&--e):e=1073741823,da&&(0===la||e<la)&&(la=e),e}function Ki(e,t,n,r){var o=e.earliestSuspendedTime,i=e.latestSuspendedTime;if(0!==o&&r<=o&&r>=i){i=o=r,e.didError=!1;var a=e.latestPingedTime;(0===a||a>i)&&(e.latestPingedTime=i),Zr(i,e)}else Xr(e,o=Xi(o=Sa(),t));0!=(1&t.mode)&&e===Li&&Mi===r&&(Li=null),Ji(t,o),0==(1&t.mode)&&(Ji(n,o),1===n.tag&&null!==n.stateNode&&((t=ro(o)).tag=2,io(n,t))),0!==(n=e.expirationTime)&&_a(e,n)}function Ji(e,t){e.expirationTime<t&&(e.expirationTime=t);var n=e.alternate;null!==n&&n.expirationTime<t&&(n.expirationTime=t);var r=e.return,o=null;if(null===r&&3===e.tag)o=e.stateNode;else for(;null!==r;){if(n=r.alternate,r.childExpirationTime<t&&(r.childExpirationTime=t),null!==n&&n.childExpirationTime<t&&(n.childExpirationTime=t),null===r.return&&3===r.tag){o=r.stateNode;break}r=r.return}return o}function Zi(e,t){null!==(e=Ji(e,t))&&(!Ri&&0!==Mi&&t>Mi&&qi(),Xr(e,t),Ri&&!Bi&&Li===e||_a(e,e.expirationTime),ba>va&&(ba=0,a(\"185\")))}function ea(e,t,n,r,o){var i=Pi;Pi=1073741823;try{return e(t,n,r,o)}finally{Pi=i}}var ta=null,na=null,ra=0,oa=void 0,ia=!1,aa=null,sa=0,la=0,ca=!1,ua=null,pa=!1,fa=!1,da=!1,ha=null,ma=i.unstable_now(),ga=1073741822-(ma/10|0),ya=ga,va=50,ba=0,wa=null;function xa(){ga=1073741822-((i.unstable_now()-ma)/10|0)}function ka(e,t){if(0!==ra){if(t<ra)return;null!==oa&&i.unstable_cancelCallback(oa)}ra=t,e=i.unstable_now()-ma,oa=i.unstable_scheduleCallback(ja,{timeout:10*(1073741822-t)-e})}function Ea(e,t,n,r,o){e.expirationTime=r,0!==o||Ta()?0<o&&(e.timeoutHandle=vr(function(e,t,n){e.pendingCommitExpirationTime=n,e.finishedWork=t,xa(),ya=ga,Ia(e,n)}.bind(null,e,t,n),o)):(e.pendingCommitExpirationTime=n,e.finishedWork=t)}function Sa(){return ia?ya:(Oa(),0!==sa&&1!==sa||(xa(),ya=ga),ya)}function _a(e,t){null===e.nextScheduledRoot?(e.expirationTime=t,null===na?(ta=na=e,e.nextScheduledRoot=e):(na=na.nextScheduledRoot=e).nextScheduledRoot=ta):t>e.expirationTime&&(e.expirationTime=t),ia||(pa?fa&&(aa=e,sa=1073741823,Pa(e,1073741823,!1)):1073741823===t?Aa(1073741823,!1):ka(e,t))}function Oa(){var e=0,t=null;if(null!==na)for(var n=na,r=ta;null!==r;){var o=r.expirationTime;if(0===o){if((null===n||null===na)&&a(\"244\"),r===r.nextScheduledRoot){ta=na=r.nextScheduledRoot=null;break}if(r===ta)ta=o=r.nextScheduledRoot,na.nextScheduledRoot=o,r.nextScheduledRoot=null;else{if(r===na){(na=n).nextScheduledRoot=ta,r.nextScheduledRoot=null;break}n.nextScheduledRoot=r.nextScheduledRoot,r.nextScheduledRoot=null}r=n.nextScheduledRoot}else{if(o>e&&(e=o,t=r),r===na)break;if(1073741823===e)break;n=r,r=r.nextScheduledRoot}}aa=t,sa=e}var Ca=!1;function Ta(){return!!Ca||!!i.unstable_shouldYield()&&(Ca=!0)}function ja(){try{if(!Ta()&&null!==ta){xa();var e=ta;do{var t=e.expirationTime;0!==t&&ga<=t&&(e.nextExpirationTimeToWorkOn=ga),e=e.nextScheduledRoot}while(e!==ta)}Aa(0,!0)}finally{Ca=!1}}function Aa(e,t){if(Oa(),t)for(xa(),ya=ga;null!==aa&&0!==sa&&e<=sa&&!(Ca&&ga>sa);)Pa(aa,sa,ga>sa),Oa(),xa(),ya=ga;else for(;null!==aa&&0!==sa&&e<=sa;)Pa(aa,sa,!1),Oa();if(t&&(ra=0,oa=null),0!==sa&&ka(aa,sa),ba=0,wa=null,null!==ha)for(e=ha,ha=null,t=0;t<e.length;t++){var n=e[t];try{n._onComplete()}catch(e){ca||(ca=!0,ua=e)}}if(ca)throw e=ua,ua=null,ca=!1,e}function Ia(e,t){ia&&a(\"253\"),aa=e,sa=t,Pa(e,t,!1),Aa(1073741823,!1)}function Pa(e,t,n){if(ia&&a(\"245\"),ia=!0,n){var r=e.finishedWork;null!==r?Ra(e,r,t):(e.finishedWork=null,-1!==(r=e.timeoutHandle)&&(e.timeoutHandle=-1,br(r)),Qi(e,n),null!==(r=e.finishedWork)&&(Ta()?e.finishedWork=r:Ra(e,r,t)))}else null!==(r=e.finishedWork)?Ra(e,r,t):(e.finishedWork=null,-1!==(r=e.timeoutHandle)&&(e.timeoutHandle=-1,br(r)),Qi(e,n),null!==(r=e.finishedWork)&&Ra(e,r,t));ia=!1}function Ra(e,t,n){var r=e.firstBatch;if(null!==r&&r._expirationTime>=n&&(null===ha?ha=[r]:ha.push(r),r._defer))return e.finishedWork=t,void(e.expirationTime=0);e.finishedWork=null,e===wa?ba++:(wa=e,ba=0),Bi=Ri=!0,e.current===t&&a(\"177\"),0===(n=e.pendingCommitExpirationTime)&&a(\"261\"),e.pendingCommitExpirationTime=0,r=t.expirationTime;var o=t.childExpirationTime;if(r=o>r?o:r,e.didError=!1,0===r?(e.earliestPendingTime=0,e.latestPendingTime=0,e.earliestSuspendedTime=0,e.latestSuspendedTime=0,e.latestPingedTime=0):(0!==(o=e.latestPendingTime)&&(o>r?e.earliestPendingTime=e.latestPendingTime=0:e.earliestPendingTime>r&&(e.earliestPendingTime=e.latestPendingTime)),0===(o=e.earliestSuspendedTime)?Xr(e,r):r<e.latestSuspendedTime?(e.earliestSuspendedTime=0,e.latestSuspendedTime=0,e.latestPingedTime=0,Xr(e,r)):r>o&&Xr(e,r)),Zr(0,e),Ai.current=null,1<t.effectTag?null!==t.lastEffect?(t.lastEffect.nextEffect=t,r=t.firstEffect):r=t:r=t.firstEffect,hr=Sn,Dn(o=Mn())){if(\"selectionStart\"in o)var i={start:o.selectionStart,end:o.selectionEnd};else e:{var s=(i=(i=o.ownerDocument)&&i.defaultView||window).getSelection&&i.getSelection();if(s&&0!==s.rangeCount){i=s.anchorNode;var l=s.anchorOffset,c=s.focusNode;s=s.focusOffset;try{i.nodeType,c.nodeType}catch(e){i=null;break e}var u=0,p=-1,f=-1,d=0,h=0,m=o,g=null;t:for(;;){for(var y;m!==i||0!==l&&3!==m.nodeType||(p=u+l),m!==c||0!==s&&3!==m.nodeType||(f=u+s),3===m.nodeType&&(u+=m.nodeValue.length),null!==(y=m.firstChild);)g=m,m=y;for(;;){if(m===o)break t;if(g===i&&++d===l&&(p=u),g===c&&++h===s&&(f=u),null!==(y=m.nextSibling))break;g=(m=g).parentNode}m=y}i=-1===p||-1===f?null:{start:p,end:f}}else i=null}i=i||{start:0,end:0}}else i=null;for(mr={focusedElem:o,selectionRange:i},Sn=!1,Ui=r;null!==Ui;){o=!1,i=void 0;try{for(;null!==Ui;){if(256&Ui.effectTag)e:{var v=Ui.alternate;switch((l=Ui).tag){case 0:case 11:case 15:break e;case 1:if(256&l.effectTag&&null!==v){var b=v.memoizedProps,w=v.memoizedState,x=l.stateNode,k=x.getSnapshotBeforeUpdate(l.elementType===l.type?b:Io(l.type,b),w);x.__reactInternalSnapshotBeforeUpdate=k}break e;case 3:case 5:case 6:case 4:case 17:break e;default:a(\"163\")}}Ui=Ui.nextEffect}}catch(e){o=!0,i=e}o&&(null===Ui&&a(\"178\"),Gi(Ui,i),null!==Ui&&(Ui=Ui.nextEffect))}for(Ui=r;null!==Ui;){v=!1,b=void 0;try{for(;null!==Ui;){var E=Ui.effectTag;if(16&E&&or(Ui.stateNode,\"\"),128&E){var S=Ui.alternate;if(null!==S){var _=S.ref;null!==_&&(\"function\"==typeof _?_(null):_.current=null)}}switch(14&E){case 2:Ei(Ui),Ui.effectTag&=-3;break;case 6:Ei(Ui),Ui.effectTag&=-3,_i(Ui.alternate,Ui);break;case 4:_i(Ui.alternate,Ui);break;case 8:Si(w=Ui),w.return=null,w.child=null,w.alternate&&(w.alternate.child=null,w.alternate.return=null)}Ui=Ui.nextEffect}}catch(e){v=!0,b=e}v&&(null===Ui&&a(\"178\"),Gi(Ui,b),null!==Ui&&(Ui=Ui.nextEffect))}if(_=mr,S=Mn(),E=_.focusedElem,b=_.selectionRange,S!==E&&E&&E.ownerDocument&&function e(t,n){return!(!t||!n)&&(t===n||(!t||3!==t.nodeType)&&(n&&3===n.nodeType?e(t,n.parentNode):\"contains\"in t?t.contains(n):!!t.compareDocumentPosition&&!!(16&t.compareDocumentPosition(n))))}(E.ownerDocument.documentElement,E)){null!==b&&Dn(E)&&(S=b.start,void 0===(_=b.end)&&(_=S),\"selectionStart\"in E?(E.selectionStart=S,E.selectionEnd=Math.min(_,E.value.length)):(_=(S=E.ownerDocument||document)&&S.defaultView||window).getSelection&&(_=_.getSelection(),w=E.textContent.length,v=Math.min(b.start,w),b=void 0===b.end?v:Math.min(b.end,w),!_.extend&&v>b&&(w=b,b=v,v=w),w=Ln(E,v),x=Ln(E,b),w&&x&&(1!==_.rangeCount||_.anchorNode!==w.node||_.anchorOffset!==w.offset||_.focusNode!==x.node||_.focusOffset!==x.offset)&&((S=S.createRange()).setStart(w.node,w.offset),_.removeAllRanges(),v>b?(_.addRange(S),_.extend(x.node,x.offset)):(S.setEnd(x.node,x.offset),_.addRange(S))))),S=[];for(_=E;_=_.parentNode;)1===_.nodeType&&S.push({element:_,left:_.scrollLeft,top:_.scrollTop});for(\"function\"==typeof E.focus&&E.focus(),E=0;E<S.length;E++)(_=S[E]).element.scrollLeft=_.left,_.element.scrollTop=_.top}for(mr=null,Sn=!!hr,hr=null,e.current=t,Ui=r;null!==Ui;){r=!1,E=void 0;try{for(S=n;null!==Ui;){var O=Ui.effectTag;if(36&O){var C=Ui.alternate;switch(v=S,(_=Ui).tag){case 0:case 11:case 15:break;case 1:var T=_.stateNode;if(4&_.effectTag)if(null===C)T.componentDidMount();else{var j=_.elementType===_.type?C.memoizedProps:Io(_.type,C.memoizedProps);T.componentDidUpdate(j,C.memoizedState,T.__reactInternalSnapshotBeforeUpdate)}var A=_.updateQueue;null!==A&&uo(0,A,T);break;case 3:var I=_.updateQueue;if(null!==I){if(b=null,null!==_.child)switch(_.child.tag){case 5:b=_.child.stateNode;break;case 1:b=_.child.stateNode}uo(0,I,b)}break;case 5:var P=_.stateNode;null===C&&4&_.effectTag&&gr(_.type,_.memoizedProps)&&P.focus();break;case 6:case 4:case 12:case 13:case 17:break;default:a(\"163\")}}if(128&O){var R=Ui.ref;if(null!==R){var N=Ui.stateNode;switch(Ui.tag){case 5:var L=N;break;default:L=N}\"function\"==typeof R?R(L):R.current=L}}Ui=Ui.nextEffect}}catch(e){r=!0,E=e}r&&(null===Ui&&a(\"178\"),Gi(Ui,E),null!==Ui&&(Ui=Ui.nextEffect))}Ri=Bi=!1,\"function\"==typeof Fr&&Fr(t.stateNode),O=t.expirationTime,0===(t=(t=t.childExpirationTime)>O?t:O)&&(Wi=null),e.expirationTime=t,e.finishedWork=null}function Na(e){null===aa&&a(\"246\"),aa.expirationTime=0,ca||(ca=!0,ua=e)}function La(e,t){var n=pa;pa=!0;try{return e(t)}finally{(pa=n)||ia||Aa(1073741823,!1)}}function Ma(e,t){if(pa&&!fa){fa=!0;try{return e(t)}finally{fa=!1}}return e(t)}function Da(e,t,n){if(da)return e(t,n);pa||ia||0===la||(Aa(la,!1),la=0);var r=da,o=pa;pa=da=!0;try{return e(t,n)}finally{da=r,(pa=o)||ia||Aa(1073741823,!1)}}function Fa(e,t,n,r,o){var i=t.current;e:if(n){t:{2===tn(n=n._reactInternalFiber)&&1===n.tag||a(\"170\");var s=n;do{switch(s.tag){case 3:s=s.stateNode.context;break t;case 1:if(Ir(s.type)){s=s.stateNode.__reactInternalMemoizedMergedChildContext;break t}}s=s.return}while(null!==s);a(\"171\"),s=void 0}if(1===n.tag){var l=n.type;if(Ir(l)){n=Lr(n,l,s);break e}}n=s}else n=Or;return null===t.context?t.context=n:t.pendingContext=n,t=o,(o=ro(r)).payload={element:e},null!==(t=void 0===t?null:t)&&(o.callback=t),Hi(),io(i,o),Zi(i,r),r}function Ua(e,t,n,r){var o=t.current;return Fa(e,t,n,o=Xi(Sa(),o),r)}function Ba(e){if(!(e=e.current).child)return null;switch(e.child.tag){case 5:default:return e.child.stateNode}}function za(e){var t=1073741822-25*(1+((1073741822-Sa()+500)/25|0));t>=Ii&&(t=Ii-1),this._expirationTime=Ii=t,this._root=e,this._callbacks=this._next=null,this._hasChildren=this._didComplete=!1,this._children=null,this._defer=!0}function $a(){this._callbacks=null,this._didCommit=!1,this._onCommit=this._onCommit.bind(this)}function Wa(e,t,n){e={current:t=$r(3,null,null,t?3:0),containerInfo:e,pendingChildren:null,earliestPendingTime:0,latestPendingTime:0,earliestSuspendedTime:0,latestSuspendedTime:0,latestPingedTime:0,didError:!1,pendingCommitExpirationTime:0,finishedWork:null,timeoutHandle:-1,context:null,pendingContext:null,hydrate:n,nextExpirationTimeToWorkOn:0,expirationTime:0,firstBatch:null,nextScheduledRoot:null},this._internalRoot=t.stateNode=e}function qa(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||\" react-mount-point-unstable \"!==e.nodeValue))}function Ha(e,t,n,r,o){qa(n)||a(\"200\");var i=n._reactRootContainer;if(i){if(\"function\"==typeof o){var s=o;o=function(){var e=Ba(i._internalRoot);s.call(e)}}null!=e?i.legacy_renderSubtreeIntoContainer(e,t,o):i.render(t,o)}else{if(i=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute(\"data-reactroot\"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new Wa(e,!1,t)}(n,r),\"function\"==typeof o){var l=o;o=function(){var e=Ba(i._internalRoot);l.call(e)}}Ma(function(){null!=e?i.legacy_renderSubtreeIntoContainer(e,t,o):i.render(t,o)})}return Ba(i._internalRoot)}function Ya(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;return qa(t)||a(\"200\"),function(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:Qe,key:null==r?null:\"\"+r,children:e,containerInfo:t,implementation:n}}(e,t,null,n)}Oe=function(e,t,n){switch(t){case\"input\":if(kt(e,n),t=n.name,\"radio\"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll(\"input[name=\"+JSON.stringify(\"\"+t)+'][type=\"radio\"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var o=F(r);o||a(\"90\"),We(r),kt(r,o)}}}break;case\"textarea\":Xn(e,n);break;case\"select\":null!=(t=n.value)&&Vn(e,!!n.multiple,t,!1)}},za.prototype.render=function(e){this._defer||a(\"250\"),this._hasChildren=!0,this._children=e;var t=this._root._internalRoot,n=this._expirationTime,r=new $a;return Fa(e,t,null,n,r._onCommit),r},za.prototype.then=function(e){if(this._didComplete)e();else{var t=this._callbacks;null===t&&(t=this._callbacks=[]),t.push(e)}},za.prototype.commit=function(){var e=this._root._internalRoot,t=e.firstBatch;if(this._defer&&null!==t||a(\"251\"),this._hasChildren){var n=this._expirationTime;if(t!==this){this._hasChildren&&(n=this._expirationTime=t._expirationTime,this.render(this._children));for(var r=null,o=t;o!==this;)r=o,o=o._next;null===r&&a(\"251\"),r._next=o._next,this._next=t,e.firstBatch=this}this._defer=!1,Ia(e,n),t=this._next,this._next=null,null!==(t=e.firstBatch=t)&&t._hasChildren&&t.render(t._children)}else this._next=null,this._defer=!1},za.prototype._onComplete=function(){if(!this._didComplete){this._didComplete=!0;var e=this._callbacks;if(null!==e)for(var t=0;t<e.length;t++)(0,e[t])()}},$a.prototype.then=function(e){if(this._didCommit)e();else{var t=this._callbacks;null===t&&(t=this._callbacks=[]),t.push(e)}},$a.prototype._onCommit=function(){if(!this._didCommit){this._didCommit=!0;var e=this._callbacks;if(null!==e)for(var t=0;t<e.length;t++){var n=e[t];\"function\"!=typeof n&&a(\"191\",n),n()}}},Wa.prototype.render=function(e,t){var n=this._internalRoot,r=new $a;return null!==(t=void 0===t?null:t)&&r.then(t),Ua(e,n,null,r._onCommit),r},Wa.prototype.unmount=function(e){var t=this._internalRoot,n=new $a;return null!==(e=void 0===e?null:e)&&n.then(e),Ua(null,t,null,n._onCommit),n},Wa.prototype.legacy_renderSubtreeIntoContainer=function(e,t,n){var r=this._internalRoot,o=new $a;return null!==(n=void 0===n?null:n)&&o.then(n),Ua(t,r,e,o._onCommit),o},Wa.prototype.createBatch=function(){var e=new za(this),t=e._expirationTime,n=this._internalRoot,r=n.firstBatch;if(null===r)n.firstBatch=e,e._next=null;else{for(n=null;null!==r&&r._expirationTime>=t;)n=r,r=r._next;e._next=r,null!==n&&(n._next=e)}return e},Pe=La,Re=Da,Ne=function(){ia||0===la||(Aa(la,!1),la=0)};var Va={createPortal:Ya,findDOMNode:function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=e._reactInternalFiber;return void 0===t&&(\"function\"==typeof e.render?a(\"188\"):a(\"268\",Object.keys(e))),e=null===(e=rn(t))?null:e.stateNode},hydrate:function(e,t,n){return Ha(null,e,t,!0,n)},render:function(e,t,n){return Ha(null,e,t,!1,n)},unstable_renderSubtreeIntoContainer:function(e,t,n,r){return(null==e||void 0===e._reactInternalFiber)&&a(\"38\"),Ha(e,t,n,!1,r)},unmountComponentAtNode:function(e){return qa(e)||a(\"40\"),!!e._reactRootContainer&&(Ma(function(){Ha(null,null,e,!1,function(){e._reactRootContainer=null})}),!0)},unstable_createPortal:function(){return Ya.apply(void 0,arguments)},unstable_batchedUpdates:La,unstable_interactiveUpdates:Da,flushSync:function(e,t){ia&&a(\"187\");var n=pa;pa=!0;try{return ea(e,t)}finally{pa=n,Aa(1073741823,!1)}},unstable_flushControlled:function(e){var t=pa;pa=!0;try{ea(e)}finally{(pa=t)||ia||Aa(1073741823,!1)}},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{Events:[M,D,F,j.injectEventPluginsByName,v,q,function(e){O(e,W)},Ae,Ie,Tn,I]},unstable_createRoot:function(e,t){return qa(e)||a(\"299\",\"unstable_createRoot\"),new Wa(e,!0,null!=t&&!0===t.hydrate)}};!function(e){var t=e.findFiberByHostInstance;(function(e){if(\"undefined\"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)return!1;var t=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(t.isDisabled||!t.supportsFiber)return!0;try{var n=t.inject(e);Fr=Br(function(e){return t.onCommitFiberRoot(n,e)}),Ur=Br(function(e){return t.onCommitFiberUnmount(n,e)})}catch(e){}})(o({},e,{findHostInstanceByFiber:function(e){return null===(e=rn(e))?null:e.stateNode},findFiberByHostInstance:function(e){return t?t(e):null}}))}({findFiberByHostInstance:L,bundleType:0,version:\"16.6.3\",rendererPackageName:\"react-dom\"});var Qa={default:Va},Ga=Qa&&Va||Qa;e.exports=Ga.default||Ga},function(e,t,n){\"use strict\";e.exports=n(181)},function(e,t,n){\"use strict\";\n/** @license React v16.6.1\n * scheduler.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */Object.defineProperty(t,\"__esModule\",{value:!0});var r=null,o=!1,i=3,a=-1,s=-1,l=!1,c=!1;function u(){if(!l){var e=r.expirationTime;c?y():c=!0,g(d,e)}}function p(){var e=r,t=r.next;if(r===t)r=null;else{var n=r.previous;r=n.next=t,t.previous=n}e.next=e.previous=null,n=e.callback,t=e.expirationTime,e=e.priorityLevel;var o=i,a=s;i=e,s=t;try{var l=n()}finally{i=o,s=a}if(\"function\"==typeof l)if(l={callback:l,priorityLevel:e,expirationTime:t,next:null,previous:null},null===r)r=l.next=l.previous=l;else{n=null,e=r;do{if(e.expirationTime>=t){n=e;break}e=e.next}while(e!==r);null===n?n=r:n===r&&(r=l,u()),(t=n.previous).next=n.previous=l,l.next=n,l.previous=t}}function f(){if(-1===a&&null!==r&&1===r.priorityLevel){l=!0;try{do{p()}while(null!==r&&1===r.priorityLevel)}finally{l=!1,null!==r?u():c=!1}}}function d(e){l=!0;var n=o;o=e;try{if(e)for(;null!==r;){var i=t.unstable_now();if(!(r.expirationTime<=i))break;do{p()}while(null!==r&&r.expirationTime<=i)}else if(null!==r)do{p()}while(null!==r&&!v())}finally{l=!1,o=n,null!==r?u():c=!1,f()}}var h,m,g,y,v,b=Date,w=\"function\"==typeof setTimeout?setTimeout:void 0,x=\"function\"==typeof clearTimeout?clearTimeout:void 0,k=\"function\"==typeof requestAnimationFrame?requestAnimationFrame:void 0,E=\"function\"==typeof cancelAnimationFrame?cancelAnimationFrame:void 0;function S(e){h=k(function(t){x(m),e(t)}),m=w(function(){E(h),e(t.unstable_now())},100)}if(\"object\"==typeof performance&&\"function\"==typeof performance.now){var _=performance;t.unstable_now=function(){return _.now()}}else t.unstable_now=function(){return b.now()};if(\"undefined\"!=typeof window&&window._schedMock){var O=window._schedMock;g=O[0],y=O[1],v=O[2]}else if(\"undefined\"==typeof window||\"function\"!=typeof window.addEventListener){var C=null,T=-1,j=function(e,t){if(null!==C){var n=C;C=null;try{T=t,n(e)}finally{T=-1}}};g=function(e,t){-1!==T?setTimeout(g,0,e,t):(C=e,setTimeout(j,t,!0,t),setTimeout(j,1073741823,!1,1073741823))},y=function(){C=null},v=function(){return!1},t.unstable_now=function(){return-1===T?0:T}}else{\"undefined\"!=typeof console&&(\"function\"!=typeof k&&console.error(\"This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills\"),\"function\"!=typeof E&&console.error(\"This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills\"));var A=null,I=!1,P=-1,R=!1,N=!1,L=0,M=33,D=33;v=function(){return L<=t.unstable_now()};var F=\"__reactIdleCallback$\"+Math.random().toString(36).slice(2);window.addEventListener(\"message\",function(e){if(e.source===window&&e.data===F){I=!1,e=A;var n=P;A=null,P=-1;var r=t.unstable_now(),o=!1;if(0>=L-r){if(!(-1!==n&&n<=r))return R||(R=!0,S(U)),A=e,void(P=n);o=!0}if(null!==e){N=!0;try{e(o)}finally{N=!1}}}},!1);var U=function(e){if(null!==A){S(U);var t=e-L+D;t<D&&M<D?(8>t&&(t=8),D=t<M?M:t):M=t,L=e+D,I||(I=!0,window.postMessage(F,\"*\"))}else R=!1};g=function(e,t){A=e,P=t,N||0>t?window.postMessage(F,\"*\"):R||(R=!0,S(U))},y=function(){A=null,I=!1,P=-1}}t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,n){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var r=i,o=a;i=e,a=t.unstable_now();try{return n()}finally{i=r,a=o,f()}},t.unstable_scheduleCallback=function(e,n){var o=-1!==a?a:t.unstable_now();if(\"object\"==typeof n&&null!==n&&\"number\"==typeof n.timeout)n=o+n.timeout;else switch(i){case 1:n=o+-1;break;case 2:n=o+250;break;case 5:n=o+1073741823;break;case 4:n=o+1e4;break;default:n=o+5e3}if(e={callback:e,priorityLevel:i,expirationTime:n,next:null,previous:null},null===r)r=e.next=e.previous=e,u();else{o=null;var s=r;do{if(s.expirationTime>n){o=s;break}s=s.next}while(s!==r);null===o?o=r:o===r&&(r=e,u()),(n=o.previous).next=o.previous=e,e.next=o,e.previous=n}return e},t.unstable_cancelCallback=function(e){var t=e.next;if(null!==t){if(t===e)r=null;else{e===r&&(r=t);var n=e.previous;n.next=t,t.previous=n}e.next=e.previous=null}},t.unstable_wrapCallback=function(e){var n=i;return function(){var r=i,o=a;i=n,a=t.unstable_now();try{return e.apply(this,arguments)}finally{i=r,a=o,f()}}},t.unstable_getCurrentPriorityLevel=function(){return i},t.unstable_shouldYield=function(){return!o&&(null!==r&&r.expirationTime<s||v())}},function(e,t,n){\"use strict\";var r=n(183);function o(){}e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var s=new Error(\"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types\");throw s.name=\"Invariant Violation\",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return n.checkPropTypes=o,n.PropTypes=n,n}},function(e,t,n){\"use strict\";e.exports=\"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED\"},function(e,t,n){(function(e,r){var o;/*! https://mths.be/punycode v1.4.1 by @mathias */!function(i){t&&t.nodeType,e&&e.nodeType;var a=\"object\"==typeof r&&r;a.global!==a&&a.window!==a&&a.self;var s,l=2147483647,c=36,u=1,p=26,f=38,d=700,h=72,m=128,g=\"-\",y=/^xn--/,v=/[^\\x20-\\x7E]/,b=/[\\x2E\\u3002\\uFF0E\\uFF61]/g,w={overflow:\"Overflow: input needs wider integers to process\",\"not-basic\":\"Illegal input >= 0x80 (not a basic code point)\",\"invalid-input\":\"Invalid input\"},x=c-u,k=Math.floor,E=String.fromCharCode;function S(e){throw new RangeError(w[e])}function _(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function O(e,t){var n=e.split(\"@\"),r=\"\";return n.length>1&&(r=n[0]+\"@\",e=n[1]),r+_((e=e.replace(b,\".\")).split(\".\"),t).join(\".\")}function C(e){for(var t,n,r=[],o=0,i=e.length;o<i;)(t=e.charCodeAt(o++))>=55296&&t<=56319&&o<i?56320==(64512&(n=e.charCodeAt(o++)))?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),o--):r.push(t);return r}function T(e){return _(e,function(e){var t=\"\";return e>65535&&(t+=E((e-=65536)>>>10&1023|55296),e=56320|1023&e),t+=E(e)}).join(\"\")}function j(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function A(e,t,n){var r=0;for(e=n?k(e/d):e>>1,e+=k(e/t);e>x*p>>1;r+=c)e=k(e/x);return k(r+(x+1)*e/(e+f))}function I(e){var t,n,r,o,i,a,s,f,d,y,v,b=[],w=e.length,x=0,E=m,_=h;for((n=e.lastIndexOf(g))<0&&(n=0),r=0;r<n;++r)e.charCodeAt(r)>=128&&S(\"not-basic\"),b.push(e.charCodeAt(r));for(o=n>0?n+1:0;o<w;){for(i=x,a=1,s=c;o>=w&&S(\"invalid-input\"),((f=(v=e.charCodeAt(o++))-48<10?v-22:v-65<26?v-65:v-97<26?v-97:c)>=c||f>k((l-x)/a))&&S(\"overflow\"),x+=f*a,!(f<(d=s<=_?u:s>=_+p?p:s-_));s+=c)a>k(l/(y=c-d))&&S(\"overflow\"),a*=y;_=A(x-i,t=b.length+1,0==i),k(x/t)>l-E&&S(\"overflow\"),E+=k(x/t),x%=t,b.splice(x++,0,E)}return T(b)}function P(e){var t,n,r,o,i,a,s,f,d,y,v,b,w,x,_,O=[];for(b=(e=C(e)).length,t=m,n=0,i=h,a=0;a<b;++a)(v=e[a])<128&&O.push(E(v));for(r=o=O.length,o&&O.push(g);r<b;){for(s=l,a=0;a<b;++a)(v=e[a])>=t&&v<s&&(s=v);for(s-t>k((l-n)/(w=r+1))&&S(\"overflow\"),n+=(s-t)*w,t=s,a=0;a<b;++a)if((v=e[a])<t&&++n>l&&S(\"overflow\"),v==t){for(f=n,d=c;!(f<(y=d<=i?u:d>=i+p?p:d-i));d+=c)_=f-y,x=c-y,O.push(E(j(y+_%x,0))),f=k(_/x);O.push(E(j(f,0))),i=A(n,w,r==o),n=0,++r}++n,++t}return O.join(\"\")}s={version:\"1.4.1\",ucs2:{decode:C,encode:T},decode:I,encode:P,toASCII:function(e){return O(e,function(e){return v.test(e)?\"xn--\"+P(e):e})},toUnicode:function(e){return O(e,function(e){return y.test(e)?I(e.slice(4).toLowerCase()):e})}},void 0===(o=function(){return s}.call(t,n,t,e))||(e.exports=o)}()}).call(this,n(185)(e),n(4))},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,\"loaded\",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,\"id\",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,n){\"use strict\";e.exports={isString:function(e){return\"string\"==typeof e},isObject:function(e){return\"object\"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},function(e,t,n){\"use strict\";t.decode=t.parse=n(188),t.encode=t.stringify=n(189)},function(e,t,n){\"use strict\";function r(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,n,i){t=t||\"&\",n=n||\"=\";var a={};if(\"string\"!=typeof e||0===e.length)return a;var s=/\\+/g;e=e.split(t);var l=1e3;i&&\"number\"==typeof i.maxKeys&&(l=i.maxKeys);var c=e.length;l>0&&c>l&&(c=l);for(var u=0;u<c;++u){var p,f,d,h,m=e[u].replace(s,\"%20\"),g=m.indexOf(n);g>=0?(p=m.substr(0,g),f=m.substr(g+1)):(p=m,f=\"\"),d=decodeURIComponent(p),h=decodeURIComponent(f),r(a,d)?o(a[d])?a[d].push(h):a[d]=[a[d],h]:a[d]=h}return a};var o=Array.isArray||function(e){return\"[object Array]\"===Object.prototype.toString.call(e)}},function(e,t,n){\"use strict\";var r=function(e){switch(typeof e){case\"string\":return e;case\"boolean\":return e?\"true\":\"false\";case\"number\":return isFinite(e)?e:\"\";default:return\"\"}};e.exports=function(e,t,n,s){return t=t||\"&\",n=n||\"=\",null===e&&(e=void 0),\"object\"==typeof e?i(a(e),function(a){var s=encodeURIComponent(r(a))+n;return o(e[a])?i(e[a],function(e){return s+encodeURIComponent(r(e))}).join(t):s+encodeURIComponent(r(e[a]))}).join(t):s?encodeURIComponent(r(s))+n+encodeURIComponent(r(e)):\"\"};var o=Array.isArray||function(e){return\"[object Array]\"===Object.prototype.toString.call(e)};function i(e,t){if(e.map)return e.map(t);for(var n=[],r=0;r<e.length;r++)n.push(t(e[r],r));return n}var a=Object.keys||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t}},function(e,t,n){\"use strict\";\n/** @license React v16.6.1\n * react-is.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */Object.defineProperty(t,\"__esModule\",{value:!0});var r=\"function\"==typeof Symbol&&Symbol.for,o=r?Symbol.for(\"react.element\"):60103,i=r?Symbol.for(\"react.portal\"):60106,a=r?Symbol.for(\"react.fragment\"):60107,s=r?Symbol.for(\"react.strict_mode\"):60108,l=r?Symbol.for(\"react.profiler\"):60114,c=r?Symbol.for(\"react.provider\"):60109,u=r?Symbol.for(\"react.context\"):60110,p=r?Symbol.for(\"react.async_mode\"):60111,f=r?Symbol.for(\"react.concurrent_mode\"):60111,d=r?Symbol.for(\"react.forward_ref\"):60112,h=r?Symbol.for(\"react.suspense\"):60113,m=r?Symbol.for(\"react.memo\"):60115,g=r?Symbol.for(\"react.lazy\"):60116;function y(e){if(\"object\"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case o:switch(e=e.type){case p:case f:case a:case l:case s:return e;default:switch(e=e&&e.$$typeof){case u:case d:case c:return e;default:return t}}case i:return t}}}function v(e){return y(e)===f}t.typeOf=y,t.AsyncMode=p,t.ConcurrentMode=f,t.ContextConsumer=u,t.ContextProvider=c,t.Element=o,t.ForwardRef=d,t.Fragment=a,t.Profiler=l,t.Portal=i,t.StrictMode=s,t.isValidElementType=function(e){return\"string\"==typeof e||\"function\"==typeof e||e===a||e===f||e===l||e===s||e===h||\"object\"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===m||e.$$typeof===c||e.$$typeof===u||e.$$typeof===d)},t.isAsyncMode=function(e){return v(e)||y(e)===p},t.isConcurrentMode=v,t.isContextConsumer=function(e){return y(e)===u},t.isContextProvider=function(e){return y(e)===c},t.isElement=function(e){return\"object\"==typeof e&&null!==e&&e.$$typeof===o},t.isForwardRef=function(e){return y(e)===d},t.isFragment=function(e){return y(e)===a},t.isProfiler=function(e){return y(e)===l},t.isPortal=function(e){return y(e)===i},t.isStrictMode=function(e){return y(e)===s}},function(e,t,n){\"use strict\";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=c(e),r=n[0],a=n[1],s=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,a)),l=0,u=a>0?r-4:r,p=0;p<u;p+=4)t=o[e.charCodeAt(p)]<<18|o[e.charCodeAt(p+1)]<<12|o[e.charCodeAt(p+2)]<<6|o[e.charCodeAt(p+3)],s[l++]=t>>16&255,s[l++]=t>>8&255,s[l++]=255&t;2===a&&(t=o[e.charCodeAt(p)]<<2|o[e.charCodeAt(p+1)]>>4,s[l++]=255&t);1===a&&(t=o[e.charCodeAt(p)]<<10|o[e.charCodeAt(p+1)]<<4|o[e.charCodeAt(p+2)]>>2,s[l++]=t>>8&255,s[l++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;a<s;a+=16383)i.push(u(e,a,a+16383>s?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+\"==\")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+\"=\"));return i.join(\"\")};for(var r=[],o=[],i=\"undefined\"!=typeof Uint8Array?Uint8Array:Array,a=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",s=0,l=a.length;s<l;++s)r[s]=a[s],o[a.charCodeAt(s)]=s;function c(e){var t=e.length;if(t%4>0)throw new Error(\"Invalid string. Length must be a multiple of 4\");var n=e.indexOf(\"=\");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function u(e,t,n){for(var o,i,a=[],s=t;s<n;s+=3)o=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(255&e[s+2]),a.push(r[(i=o)>>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join(\"\")}o[\"-\".charCodeAt(0)]=62,o[\"_\".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,l=(1<<s)-1,c=l>>1,u=-7,p=n?o-1:0,f=n?-1:1,d=e[t+p];for(p+=f,i=d&(1<<-u)-1,d>>=-u,u+=s;u>0;i=256*i+e[t+p],p+=f,u-=8);for(a=i&(1<<-u)-1,i>>=-u,u+=r;u>0;a=256*a+e[t+p],p+=f,u-=8);if(0===i)i=1-c;else{if(i===l)return a?NaN:1/0*(d?-1:1);a+=Math.pow(2,r),i-=c}return(d?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,l,c=8*i-o-1,u=(1<<c)-1,p=u>>1,f=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,d=r?0:i-1,h=r?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=u):(a=Math.floor(Math.log(t)/Math.LN2),t*(l=Math.pow(2,-a))<1&&(a--,l*=2),(t+=a+p>=1?f/l:f*Math.pow(2,1-p))*l>=2&&(a++,l/=2),a+p>=u?(s=0,a=u):a+p>=1?(s=(t*l-1)*Math.pow(2,o),a+=p):(s=t*Math.pow(2,p-1)*Math.pow(2,o),a=0));o>=8;e[n+d]=255&s,d+=h,s/=256,o-=8);for(a=a<<o|s,c+=o;c>0;e[n+d]=255&a,d+=h,a/=256,c-=8);e[n+d-h]|=128*m}},function(e,t,n){\"use strict\";(function(t){e.exports={order:100,allowEmpty:!0,canParse:\".json\",parse:function(e){return new Promise(function(n,r){var o=e.data;t.isBuffer(o)&&(o=o.toString()),\"string\"==typeof o?0===o.trim().length?n(void 0):n(JSON.parse(o)):n(o)})}}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";(function(t){var r=n(103);e.exports={order:200,allowEmpty:!0,canParse:[\".yaml\",\".yml\",\".json\"],parse:function(e){return new Promise(function(n,o){var i=e.data;t.isBuffer(i)&&(i=i.toString()),n(\"string\"==typeof i?r.parse(i):i)})}}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";var r=n(196),o=n(215);function i(e){return function(){throw new Error(\"Function \"+e+\" is deprecated and cannot be used.\")}}e.exports.Type=n(3),e.exports.Schema=n(29),e.exports.FAILSAFE_SCHEMA=n(73),e.exports.JSON_SCHEMA=n(105),e.exports.CORE_SCHEMA=n(104),e.exports.DEFAULT_SAFE_SCHEMA=n(48),e.exports.DEFAULT_FULL_SCHEMA=n(74),e.exports.load=r.load,e.exports.loadAll=r.loadAll,e.exports.safeLoad=r.safeLoad,e.exports.safeLoadAll=r.safeLoadAll,e.exports.dump=o.dump,e.exports.safeDump=o.safeDump,e.exports.YAMLException=n(47),e.exports.MINIMAL_SCHEMA=n(73),e.exports.SAFE_SCHEMA=n(48),e.exports.DEFAULT_SCHEMA=n(74),e.exports.scan=i(\"scan\"),e.exports.parse=i(\"parse\"),e.exports.compose=i(\"compose\"),e.exports.addConstructor=i(\"addConstructor\")},function(e,t,n){\"use strict\";var r=n(37),o=n(47),i=n(197),a=n(48),s=n(74),l=Object.prototype.hasOwnProperty,c=1,u=2,p=3,f=4,d=1,h=2,m=3,g=/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/,y=/[\\x85\\u2028\\u2029]/,v=/[,\\[\\]\\{\\}]/,b=/^(?:!|!!|![a-z\\-]+!)$/i,w=/^(?:!|[^,\\[\\]\\{\\}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;\\/\\?:@&=\\+\\$,_\\.!~\\*'\\(\\)\\[\\]])*$/i;function x(e){return 10===e||13===e}function k(e){return 9===e||32===e}function E(e){return 9===e||32===e||10===e||13===e}function S(e){return 44===e||91===e||93===e||123===e||125===e}function _(e){var t;return 48<=e&&e<=57?e-48:97<=(t=32|e)&&t<=102?t-97+10:-1}function O(e){return 48===e?\"\\0\":97===e?\"\u0007\":98===e?\"\\b\":116===e?\"\\t\":9===e?\"\\t\":110===e?\"\\n\":118===e?\"\\v\":102===e?\"\\f\":114===e?\"\\r\":101===e?\"\u001b\":32===e?\" \":34===e?'\"':47===e?\"/\":92===e?\"\\\\\":78===e?\"\":95===e?\" \":76===e?\"\\u2028\":80===e?\"\\u2029\":\"\"}function C(e){return e<=65535?String.fromCharCode(e):String.fromCharCode(55296+(e-65536>>10),56320+(e-65536&1023))}for(var T=new Array(256),j=new Array(256),A=0;A<256;A++)T[A]=O(A)?1:0,j[A]=O(A);function I(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||s,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function P(e,t){return new o(t,new i(e.filename,e.input,e.position,e.line,e.position-e.lineStart))}function R(e,t){throw P(e,t)}function N(e,t){e.onWarning&&e.onWarning.call(null,P(e,t))}var L={YAML:function(e,t,n){var r,o,i;null!==e.version&&R(e,\"duplication of %YAML directive\"),1!==n.length&&R(e,\"YAML directive accepts exactly one argument\"),null===(r=/^([0-9]+)\\.([0-9]+)$/.exec(n[0]))&&R(e,\"ill-formed argument of the YAML directive\"),o=parseInt(r[1],10),i=parseInt(r[2],10),1!==o&&R(e,\"unacceptable YAML version of the document\"),e.version=n[0],e.checkLineBreaks=i<2,1!==i&&2!==i&&N(e,\"unsupported YAML version of the document\")},TAG:function(e,t,n){var r,o;2!==n.length&&R(e,\"TAG directive accepts exactly two arguments\"),r=n[0],o=n[1],b.test(r)||R(e,\"ill-formed tag handle (first argument) of the TAG directive\"),l.call(e.tagMap,r)&&R(e,'there is a previously declared suffix for \"'+r+'\" tag handle'),w.test(o)||R(e,\"ill-formed tag prefix (second argument) of the TAG directive\"),e.tagMap[r]=o}};function M(e,t,n,r){var o,i,a,s;if(t<n){if(s=e.input.slice(t,n),r)for(o=0,i=s.length;o<i;o+=1)9===(a=s.charCodeAt(o))||32<=a&&a<=1114111||R(e,\"expected valid JSON character\");else g.test(s)&&R(e,\"the stream contains non-printable characters\");e.result+=s}}function D(e,t,n,o){var i,a,s,c;for(r.isObject(n)||R(e,\"cannot merge mappings; the provided source object is unacceptable\"),s=0,c=(i=Object.keys(n)).length;s<c;s+=1)a=i[s],l.call(t,a)||(t[a]=n[a],o[a]=!0)}function F(e,t,n,r,o,i,a,s){var c,u;if(o=String(o),null===t&&(t={}),\"tag:yaml.org,2002:merge\"===r)if(Array.isArray(i))for(c=0,u=i.length;c<u;c+=1)D(e,t,i[c],n);else D(e,t,i,n);else e.json||l.call(n,o)||!l.call(t,o)||(e.line=a||e.line,e.position=s||e.position,R(e,\"duplicated mapping key\")),t[o]=i,delete n[o];return t}function U(e){var t;10===(t=e.input.charCodeAt(e.position))?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):R(e,\"a line break is expected\"),e.line+=1,e.lineStart=e.position}function B(e,t,n){for(var r=0,o=e.input.charCodeAt(e.position);0!==o;){for(;k(o);)o=e.input.charCodeAt(++e.position);if(t&&35===o)do{o=e.input.charCodeAt(++e.position)}while(10!==o&&13!==o&&0!==o);if(!x(o))break;for(U(e),o=e.input.charCodeAt(e.position),r++,e.lineIndent=0;32===o;)e.lineIndent++,o=e.input.charCodeAt(++e.position)}return-1!==n&&0!==r&&e.lineIndent<n&&N(e,\"deficient indentation\"),r}function z(e){var t,n=e.position;return!(45!==(t=e.input.charCodeAt(n))&&46!==t||t!==e.input.charCodeAt(n+1)||t!==e.input.charCodeAt(n+2)||(n+=3,0!==(t=e.input.charCodeAt(n))&&!E(t)))}function $(e,t){1===t?e.result+=\" \":t>1&&(e.result+=r.repeat(\"\\n\",t-1))}function W(e,t){var n,r,o=e.tag,i=e.anchor,a=[],s=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),r=e.input.charCodeAt(e.position);0!==r&&45===r&&E(e.input.charCodeAt(e.position+1));)if(s=!0,e.position++,B(e,!0,-1)&&e.lineIndent<=t)a.push(null),r=e.input.charCodeAt(e.position);else if(n=e.line,Y(e,t,p,!1,!0),a.push(e.result),B(e,!0,-1),r=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==r)R(e,\"bad indentation of a sequence entry\");else if(e.lineIndent<t)break;return!!s&&(e.tag=o,e.anchor=i,e.kind=\"sequence\",e.result=a,!0)}function q(e){var t,n,r,o,i=!1,a=!1;if(33!==(o=e.input.charCodeAt(e.position)))return!1;if(null!==e.tag&&R(e,\"duplication of a tag property\"),60===(o=e.input.charCodeAt(++e.position))?(i=!0,o=e.input.charCodeAt(++e.position)):33===o?(a=!0,n=\"!!\",o=e.input.charCodeAt(++e.position)):n=\"!\",t=e.position,i){do{o=e.input.charCodeAt(++e.position)}while(0!==o&&62!==o);e.position<e.length?(r=e.input.slice(t,e.position),o=e.input.charCodeAt(++e.position)):R(e,\"unexpected end of the stream within a verbatim tag\")}else{for(;0!==o&&!E(o);)33===o&&(a?R(e,\"tag suffix cannot contain exclamation marks\"):(n=e.input.slice(t-1,e.position+1),b.test(n)||R(e,\"named tag handle cannot contain such characters\"),a=!0,t=e.position+1)),o=e.input.charCodeAt(++e.position);r=e.input.slice(t,e.position),v.test(r)&&R(e,\"tag suffix cannot contain flow indicator characters\")}return r&&!w.test(r)&&R(e,\"tag name cannot contain such characters: \"+r),i?e.tag=r:l.call(e.tagMap,n)?e.tag=e.tagMap[n]+r:\"!\"===n?e.tag=\"!\"+r:\"!!\"===n?e.tag=\"tag:yaml.org,2002:\"+r:R(e,'undeclared tag handle \"'+n+'\"'),!0}function H(e){var t,n;if(38!==(n=e.input.charCodeAt(e.position)))return!1;for(null!==e.anchor&&R(e,\"duplication of an anchor property\"),n=e.input.charCodeAt(++e.position),t=e.position;0!==n&&!E(n)&&!S(n);)n=e.input.charCodeAt(++e.position);return e.position===t&&R(e,\"name of an anchor node must contain at least one character\"),e.anchor=e.input.slice(t,e.position),!0}function Y(e,t,n,o,i){var a,s,g,y,v,b,w,O,A=1,I=!1,P=!1;if(null!==e.listener&&e.listener(\"open\",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,a=s=g=f===n||p===n,o&&B(e,!0,-1)&&(I=!0,e.lineIndent>t?A=1:e.lineIndent===t?A=0:e.lineIndent<t&&(A=-1)),1===A)for(;q(e)||H(e);)B(e,!0,-1)?(I=!0,g=a,e.lineIndent>t?A=1:e.lineIndent===t?A=0:e.lineIndent<t&&(A=-1)):g=!1;if(g&&(g=I||i),1!==A&&f!==n||(w=c===n||u===n?t:t+1,O=e.position-e.lineStart,1===A?g&&(W(e,O)||function(e,t,n){var r,o,i,a,s,l=e.tag,c=e.anchor,p={},d={},h=null,m=null,g=null,y=!1,v=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=p),s=e.input.charCodeAt(e.position);0!==s;){if(r=e.input.charCodeAt(e.position+1),i=e.line,a=e.position,63!==s&&58!==s||!E(r)){if(!Y(e,n,u,!1,!0))break;if(e.line===i){for(s=e.input.charCodeAt(e.position);k(s);)s=e.input.charCodeAt(++e.position);if(58===s)E(s=e.input.charCodeAt(++e.position))||R(e,\"a whitespace character is expected after the key-value separator within a block mapping\"),y&&(F(e,p,d,h,m,null),h=m=g=null),v=!0,y=!1,o=!1,h=e.tag,m=e.result;else{if(!v)return e.tag=l,e.anchor=c,!0;R(e,\"can not read an implicit mapping pair; a colon is missed\")}}else{if(!v)return e.tag=l,e.anchor=c,!0;R(e,\"can not read a block mapping entry; a multiline key may not be an implicit key\")}}else 63===s?(y&&(F(e,p,d,h,m,null),h=m=g=null),v=!0,y=!0,o=!0):y?(y=!1,o=!0):R(e,\"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line\"),e.position+=1,s=r;if((e.line===i||e.lineIndent>t)&&(Y(e,t,f,!0,o)&&(y?m=e.result:g=e.result),y||(F(e,p,d,h,m,g,i,a),h=m=g=null),B(e,!0,-1),s=e.input.charCodeAt(e.position)),e.lineIndent>t&&0!==s)R(e,\"bad indentation of a mapping entry\");else if(e.lineIndent<t)break}return y&&F(e,p,d,h,m,null),v&&(e.tag=l,e.anchor=c,e.kind=\"mapping\",e.result=p),v}(e,O,w))||function(e,t){var n,r,o,i,a,s,l,u,p,f,d=!0,h=e.tag,m=e.anchor,g={};if(91===(f=e.input.charCodeAt(e.position)))o=93,s=!1,r=[];else{if(123!==f)return!1;o=125,s=!0,r={}}for(null!==e.anchor&&(e.anchorMap[e.anchor]=r),f=e.input.charCodeAt(++e.position);0!==f;){if(B(e,!0,t),(f=e.input.charCodeAt(e.position))===o)return e.position++,e.tag=h,e.anchor=m,e.kind=s?\"mapping\":\"sequence\",e.result=r,!0;d||R(e,\"missed comma between flow collection entries\"),p=null,i=a=!1,63===f&&E(e.input.charCodeAt(e.position+1))&&(i=a=!0,e.position++,B(e,!0,t)),n=e.line,Y(e,t,c,!1,!0),u=e.tag,l=e.result,B(e,!0,t),f=e.input.charCodeAt(e.position),!a&&e.line!==n||58!==f||(i=!0,f=e.input.charCodeAt(++e.position),B(e,!0,t),Y(e,t,c,!1,!0),p=e.result),s?F(e,r,g,u,l,p):i?r.push(F(e,null,g,u,l,p)):r.push(l),B(e,!0,t),44===(f=e.input.charCodeAt(e.position))?(d=!0,f=e.input.charCodeAt(++e.position)):d=!1}R(e,\"unexpected end of the stream within a flow collection\")}(e,w)?P=!0:(s&&function(e,t){var n,o,i,a,s,l=d,c=!1,u=!1,p=t,f=0,g=!1;if(124===(a=e.input.charCodeAt(e.position)))o=!1;else{if(62!==a)return!1;o=!0}for(e.kind=\"scalar\",e.result=\"\";0!==a;)if(43===(a=e.input.charCodeAt(++e.position))||45===a)d===l?l=43===a?m:h:R(e,\"repeat of a chomping mode identifier\");else{if(!((i=48<=(s=a)&&s<=57?s-48:-1)>=0))break;0===i?R(e,\"bad explicit indentation width of a block scalar; it cannot be less than one\"):u?R(e,\"repeat of an indentation width identifier\"):(p=t+i-1,u=!0)}if(k(a)){do{a=e.input.charCodeAt(++e.position)}while(k(a));if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!x(a)&&0!==a)}for(;0!==a;){for(U(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!u||e.lineIndent<p)&&32===a;)e.lineIndent++,a=e.input.charCodeAt(++e.position);if(!u&&e.lineIndent>p&&(p=e.lineIndent),x(a))f++;else{if(e.lineIndent<p){l===m?e.result+=r.repeat(\"\\n\",c?1+f:f):l===d&&c&&(e.result+=\"\\n\");break}for(o?k(a)?(g=!0,e.result+=r.repeat(\"\\n\",c?1+f:f)):g?(g=!1,e.result+=r.repeat(\"\\n\",f+1)):0===f?c&&(e.result+=\" \"):e.result+=r.repeat(\"\\n\",f):e.result+=r.repeat(\"\\n\",c?1+f:f),c=!0,u=!0,f=0,n=e.position;!x(a)&&0!==a;)a=e.input.charCodeAt(++e.position);M(e,n,e.position,!1)}}return!0}(e,w)||function(e,t){var n,r,o;if(39!==(n=e.input.charCodeAt(e.position)))return!1;for(e.kind=\"scalar\",e.result=\"\",e.position++,r=o=e.position;0!==(n=e.input.charCodeAt(e.position));)if(39===n){if(M(e,r,e.position,!0),39!==(n=e.input.charCodeAt(++e.position)))return!0;r=e.position,e.position++,o=e.position}else x(n)?(M(e,r,o,!0),$(e,B(e,!1,t)),r=o=e.position):e.position===e.lineStart&&z(e)?R(e,\"unexpected end of the document within a single quoted scalar\"):(e.position++,o=e.position);R(e,\"unexpected end of the stream within a single quoted scalar\")}(e,w)||function(e,t){var n,r,o,i,a,s,l;if(34!==(s=e.input.charCodeAt(e.position)))return!1;for(e.kind=\"scalar\",e.result=\"\",e.position++,n=r=e.position;0!==(s=e.input.charCodeAt(e.position));){if(34===s)return M(e,n,e.position,!0),e.position++,!0;if(92===s){if(M(e,n,e.position,!0),x(s=e.input.charCodeAt(++e.position)))B(e,!1,t);else if(s<256&&T[s])e.result+=j[s],e.position++;else if((a=120===(l=s)?2:117===l?4:85===l?8:0)>0){for(o=a,i=0;o>0;o--)(a=_(s=e.input.charCodeAt(++e.position)))>=0?i=(i<<4)+a:R(e,\"expected hexadecimal character\");e.result+=C(i),e.position++}else R(e,\"unknown escape sequence\");n=r=e.position}else x(s)?(M(e,n,r,!0),$(e,B(e,!1,t)),n=r=e.position):e.position===e.lineStart&&z(e)?R(e,\"unexpected end of the document within a double quoted scalar\"):(e.position++,r=e.position)}R(e,\"unexpected end of the stream within a double quoted scalar\")}(e,w)?P=!0:!function(e){var t,n,r;if(42!==(r=e.input.charCodeAt(e.position)))return!1;for(r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!E(r)&&!S(r);)r=e.input.charCodeAt(++e.position);return e.position===t&&R(e,\"name of an alias node must contain at least one character\"),n=e.input.slice(t,e.position),e.anchorMap.hasOwnProperty(n)||R(e,'unidentified alias \"'+n+'\"'),e.result=e.anchorMap[n],B(e,!0,-1),!0}(e)?function(e,t,n){var r,o,i,a,s,l,c,u,p=e.kind,f=e.result;if(E(u=e.input.charCodeAt(e.position))||S(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(E(r=e.input.charCodeAt(e.position+1))||n&&S(r)))return!1;for(e.kind=\"scalar\",e.result=\"\",o=i=e.position,a=!1;0!==u;){if(58===u){if(E(r=e.input.charCodeAt(e.position+1))||n&&S(r))break}else if(35===u){if(E(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&z(e)||n&&S(u))break;if(x(u)){if(s=e.line,l=e.lineStart,c=e.lineIndent,B(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position);continue}e.position=i,e.line=s,e.lineStart=l,e.lineIndent=c;break}}a&&(M(e,o,i,!1),$(e,e.line-s),o=i=e.position,a=!1),k(u)||(i=e.position+1),u=e.input.charCodeAt(++e.position)}return M(e,o,i,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,w,c===n)&&(P=!0,null===e.tag&&(e.tag=\"?\")):(P=!0,null===e.tag&&null===e.anchor||R(e,\"alias node should not have any properties\")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===A&&(P=g&&W(e,O))),null!==e.tag&&\"!\"!==e.tag)if(\"?\"===e.tag){for(y=0,v=e.implicitTypes.length;y<v;y+=1)if((b=e.implicitTypes[y]).resolve(e.result)){e.result=b.construct(e.result),e.tag=b.tag,null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);break}}else l.call(e.typeMap[e.kind||\"fallback\"],e.tag)?(b=e.typeMap[e.kind||\"fallback\"][e.tag],null!==e.result&&b.kind!==e.kind&&R(e,\"unacceptable node kind for !<\"+e.tag+'> tag; it should be \"'+b.kind+'\", not \"'+e.kind+'\"'),b.resolve(e.result)?(e.result=b.construct(e.result),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):R(e,\"cannot resolve a node with !<\"+e.tag+\"> explicit tag\")):R(e,\"unknown tag !<\"+e.tag+\">\");return null!==e.listener&&e.listener(\"close\",e),null!==e.tag||null!==e.anchor||P}function V(e){var t,n,r,o,i=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};0!==(o=e.input.charCodeAt(e.position))&&(B(e,!0,-1),o=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==o));){for(a=!0,o=e.input.charCodeAt(++e.position),t=e.position;0!==o&&!E(o);)o=e.input.charCodeAt(++e.position);for(r=[],(n=e.input.slice(t,e.position)).length<1&&R(e,\"directive name must not be less than one character in length\");0!==o;){for(;k(o);)o=e.input.charCodeAt(++e.position);if(35===o){do{o=e.input.charCodeAt(++e.position)}while(0!==o&&!x(o));break}if(x(o))break;for(t=e.position;0!==o&&!E(o);)o=e.input.charCodeAt(++e.position);r.push(e.input.slice(t,e.position))}0!==o&&U(e),l.call(L,n)?L[n](e,n,r):N(e,'unknown document directive \"'+n+'\"')}B(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,B(e,!0,-1)):a&&R(e,\"directives end mark is expected\"),Y(e,e.lineIndent-1,f,!1,!0),B(e,!0,-1),e.checkLineBreaks&&y.test(e.input.slice(i,e.position))&&N(e,\"non-ASCII line breaks are interpreted as content\"),e.documents.push(e.result),e.position===e.lineStart&&z(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,B(e,!0,-1)):e.position<e.length-1&&R(e,\"end of the stream or a document separator is expected\")}function Q(e,t){t=t||{},0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+=\"\\n\"),65279===e.charCodeAt(0)&&(e=e.slice(1)));var n=new I(e,t);for(n.input+=\"\\0\";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)V(n);return n.documents}function G(e,t,n){var r,o,i=Q(e,n);if(\"function\"!=typeof t)return i;for(r=0,o=i.length;r<o;r+=1)t(i[r])}function X(e,t){var n=Q(e,t);if(0!==n.length){if(1===n.length)return n[0];throw new o(\"expected a single document in the stream, but found more\")}}e.exports.loadAll=G,e.exports.load=X,e.exports.safeLoadAll=function(e,t,n){if(\"function\"!=typeof t)return G(e,r.extend({schema:a},n));G(e,t,r.extend({schema:a},n))},e.exports.safeLoad=function(e,t){return X(e,r.extend({schema:a},t))}},function(e,t,n){\"use strict\";var r=n(37);function o(e,t,n,r,o){this.name=e,this.buffer=t,this.position=n,this.line=r,this.column=o}o.prototype.getSnippet=function(e,t){var n,o,i,a,s;if(!this.buffer)return null;for(e=e||4,t=t||75,n=\"\",o=this.position;o>0&&-1===\"\\0\\r\\n\\u2028\\u2029\".indexOf(this.buffer.charAt(o-1));)if(o-=1,this.position-o>t/2-1){n=\" ... \",o+=5;break}for(i=\"\",a=this.position;a<this.buffer.length&&-1===\"\\0\\r\\n\\u2028\\u2029\".indexOf(this.buffer.charAt(a));)if((a+=1)-this.position>t/2-1){i=\" ... \",a-=5;break}return s=this.buffer.slice(o,a),r.repeat(\" \",e)+n+s+i+\"\\n\"+r.repeat(\" \",e+this.position-o+n.length)+\"^\"},o.prototype.toString=function(e){var t,n=\"\";return this.name&&(n+='in \"'+this.name+'\" '),n+=\"at line \"+(this.line+1)+\", column \"+(this.column+1),e||(t=this.getSnippet())&&(n+=\":\\n\"+t),n},e.exports=o},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:str\",{kind:\"scalar\",construct:function(e){return null!==e?e:\"\"}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:seq\",{kind:\"sequence\",construct:function(e){return null!==e?e:[]}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:map\",{kind:\"mapping\",construct:function(e){return null!==e?e:{}}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:null\",{kind:\"scalar\",resolve:function(e){if(null===e)return!0;var t=e.length;return 1===t&&\"~\"===e||4===t&&(\"null\"===e||\"Null\"===e||\"NULL\"===e)},construct:function(){return null},predicate:function(e){return null===e},represent:{canonical:function(){return\"~\"},lowercase:function(){return\"null\"},uppercase:function(){return\"NULL\"},camelcase:function(){return\"Null\"}},defaultStyle:\"lowercase\"})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:bool\",{kind:\"scalar\",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&(\"true\"===e||\"True\"===e||\"TRUE\"===e)||5===t&&(\"false\"===e||\"False\"===e||\"FALSE\"===e)},construct:function(e){return\"true\"===e||\"True\"===e||\"TRUE\"===e},predicate:function(e){return\"[object Boolean]\"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?\"true\":\"false\"},uppercase:function(e){return e?\"TRUE\":\"FALSE\"},camelcase:function(e){return e?\"True\":\"False\"}},defaultStyle:\"lowercase\"})},function(e,t,n){\"use strict\";var r=n(37),o=n(3);function i(e){return 48<=e&&e<=55}function a(e){return 48<=e&&e<=57}e.exports=new o(\"tag:yaml.org,2002:int\",{kind:\"scalar\",resolve:function(e){if(null===e)return!1;var t,n,r=e.length,o=0,s=!1;if(!r)return!1;if(\"-\"!==(t=e[o])&&\"+\"!==t||(t=e[++o]),\"0\"===t){if(o+1===r)return!0;if(\"b\"===(t=e[++o])){for(o++;o<r;o++)if(\"_\"!==(t=e[o])){if(\"0\"!==t&&\"1\"!==t)return!1;s=!0}return s&&\"_\"!==t}if(\"x\"===t){for(o++;o<r;o++)if(\"_\"!==(t=e[o])){if(!(48<=(n=e.charCodeAt(o))&&n<=57||65<=n&&n<=70||97<=n&&n<=102))return!1;s=!0}return s&&\"_\"!==t}for(;o<r;o++)if(\"_\"!==(t=e[o])){if(!i(e.charCodeAt(o)))return!1;s=!0}return s&&\"_\"!==t}if(\"_\"===t)return!1;for(;o<r;o++)if(\"_\"!==(t=e[o])){if(\":\"===t)break;if(!a(e.charCodeAt(o)))return!1;s=!0}return!(!s||\"_\"===t)&&(\":\"!==t||/^(:[0-5]?[0-9])+$/.test(e.slice(o)))},construct:function(e){var t,n,r=e,o=1,i=[];return-1!==r.indexOf(\"_\")&&(r=r.replace(/_/g,\"\")),\"-\"!==(t=r[0])&&\"+\"!==t||(\"-\"===t&&(o=-1),t=(r=r.slice(1))[0]),\"0\"===r?0:\"0\"===t?\"b\"===r[1]?o*parseInt(r.slice(2),2):\"x\"===r[1]?o*parseInt(r,16):o*parseInt(r,8):-1!==r.indexOf(\":\")?(r.split(\":\").forEach(function(e){i.unshift(parseInt(e,10))}),r=0,n=1,i.forEach(function(e){r+=e*n,n*=60}),o*r):o*parseInt(r,10)},predicate:function(e){return\"[object Number]\"===Object.prototype.toString.call(e)&&e%1==0&&!r.isNegativeZero(e)},represent:{binary:function(e){return e>=0?\"0b\"+e.toString(2):\"-0b\"+e.toString(2).slice(1)},octal:function(e){return e>=0?\"0\"+e.toString(8):\"-0\"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?\"0x\"+e.toString(16).toUpperCase():\"-0x\"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:\"decimal\",styleAliases:{binary:[2,\"bin\"],octal:[8,\"oct\"],decimal:[10,\"dec\"],hexadecimal:[16,\"hex\"]}})},function(e,t,n){\"use strict\";var r=n(37),o=n(3),i=new RegExp(\"^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*|[-+]?\\\\.(?:inf|Inf|INF)|\\\\.(?:nan|NaN|NAN))$\");var a=/^[-+]?[0-9]+e/;e.exports=new o(\"tag:yaml.org,2002:float\",{kind:\"scalar\",resolve:function(e){return null!==e&&!(!i.test(e)||\"_\"===e[e.length-1])},construct:function(e){var t,n,r,o;return n=\"-\"===(t=e.replace(/_/g,\"\").toLowerCase())[0]?-1:1,o=[],\"+-\".indexOf(t[0])>=0&&(t=t.slice(1)),\".inf\"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:\".nan\"===t?NaN:t.indexOf(\":\")>=0?(t.split(\":\").forEach(function(e){o.unshift(parseFloat(e,10))}),t=0,r=1,o.forEach(function(e){t+=e*r,r*=60}),n*t):n*parseFloat(t,10)},predicate:function(e){return\"[object Number]\"===Object.prototype.toString.call(e)&&(e%1!=0||r.isNegativeZero(e))},represent:function(e,t){var n;if(isNaN(e))switch(t){case\"lowercase\":return\".nan\";case\"uppercase\":return\".NAN\";case\"camelcase\":return\".NaN\"}else if(Number.POSITIVE_INFINITY===e)switch(t){case\"lowercase\":return\".inf\";case\"uppercase\":return\".INF\";case\"camelcase\":return\".Inf\"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case\"lowercase\":return\"-.inf\";case\"uppercase\":return\"-.INF\";case\"camelcase\":return\"-.Inf\"}else if(r.isNegativeZero(e))return\"-0.0\";return n=e.toString(10),a.test(n)?n.replace(\"e\",\".e\"):n},defaultStyle:\"lowercase\"})},function(e,t,n){\"use strict\";var r=n(3),o=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$\"),i=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\\\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\\\.([0-9]*))?(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$\");e.exports=new r(\"tag:yaml.org,2002:timestamp\",{kind:\"scalar\",resolve:function(e){return null!==e&&(null!==o.exec(e)||null!==i.exec(e))},construct:function(e){var t,n,r,a,s,l,c,u,p=0,f=null;if(null===(t=o.exec(e))&&(t=i.exec(e)),null===t)throw new Error(\"Date resolve error\");if(n=+t[1],r=+t[2]-1,a=+t[3],!t[4])return new Date(Date.UTC(n,r,a));if(s=+t[4],l=+t[5],c=+t[6],t[7]){for(p=t[7].slice(0,3);p.length<3;)p+=\"0\";p=+p}return t[9]&&(f=6e4*(60*+t[10]+ +(t[11]||0)),\"-\"===t[9]&&(f=-f)),u=new Date(Date.UTC(n,r,a,s,l,c,p)),f&&u.setTime(u.getTime()-f),u},instanceOf:Date,represent:function(e){return e.toISOString()}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:merge\",{kind:\"scalar\",resolve:function(e){return\"<<\"===e||null===e}})},function(e,t,n){\"use strict\";var r;try{r=n(9).Buffer}catch(e){}var o=n(3),i=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r\";e.exports=new o(\"tag:yaml.org,2002:binary\",{kind:\"scalar\",resolve:function(e){if(null===e)return!1;var t,n,r=0,o=e.length,a=i;for(n=0;n<o;n++)if(!((t=a.indexOf(e.charAt(n)))>64)){if(t<0)return!1;r+=6}return r%8==0},construct:function(e){var t,n,o=e.replace(/[\\r\\n=]/g,\"\"),a=o.length,s=i,l=0,c=[];for(t=0;t<a;t++)t%4==0&&t&&(c.push(l>>16&255),c.push(l>>8&255),c.push(255&l)),l=l<<6|s.indexOf(o.charAt(t));return 0==(n=a%4*6)?(c.push(l>>16&255),c.push(l>>8&255),c.push(255&l)):18===n?(c.push(l>>10&255),c.push(l>>2&255)):12===n&&c.push(l>>4&255),r?r.from?r.from(c):new r(c):c},predicate:function(e){return r&&r.isBuffer(e)},represent:function(e){var t,n,r=\"\",o=0,a=e.length,s=i;for(t=0;t<a;t++)t%3==0&&t&&(r+=s[o>>18&63],r+=s[o>>12&63],r+=s[o>>6&63],r+=s[63&o]),o=(o<<8)+e[t];return 0==(n=a%3)?(r+=s[o>>18&63],r+=s[o>>12&63],r+=s[o>>6&63],r+=s[63&o]):2===n?(r+=s[o>>10&63],r+=s[o>>4&63],r+=s[o<<2&63],r+=s[64]):1===n&&(r+=s[o>>2&63],r+=s[o<<4&63],r+=s[64],r+=s[64]),r}})},function(e,t,n){\"use strict\";var r=n(3),o=Object.prototype.hasOwnProperty,i=Object.prototype.toString;e.exports=new r(\"tag:yaml.org,2002:omap\",{kind:\"sequence\",resolve:function(e){if(null===e)return!0;var t,n,r,a,s,l=[],c=e;for(t=0,n=c.length;t<n;t+=1){if(r=c[t],s=!1,\"[object Object]\"!==i.call(r))return!1;for(a in r)if(o.call(r,a)){if(s)return!1;s=!0}if(!s)return!1;if(-1!==l.indexOf(a))return!1;l.push(a)}return!0},construct:function(e){return null!==e?e:[]}})},function(e,t,n){\"use strict\";var r=n(3),o=Object.prototype.toString;e.exports=new r(\"tag:yaml.org,2002:pairs\",{kind:\"sequence\",resolve:function(e){if(null===e)return!0;var t,n,r,i,a,s=e;for(a=new Array(s.length),t=0,n=s.length;t<n;t+=1){if(r=s[t],\"[object Object]\"!==o.call(r))return!1;if(1!==(i=Object.keys(r)).length)return!1;a[t]=[i[0],r[i[0]]]}return!0},construct:function(e){if(null===e)return[];var t,n,r,o,i,a=e;for(i=new Array(a.length),t=0,n=a.length;t<n;t+=1)r=a[t],o=Object.keys(r),i[t]=[o[0],r[o[0]]];return i}})},function(e,t,n){\"use strict\";var r=n(3),o=Object.prototype.hasOwnProperty;e.exports=new r(\"tag:yaml.org,2002:set\",{kind:\"mapping\",resolve:function(e){if(null===e)return!0;var t,n=e;for(t in n)if(o.call(n,t)&&null!==n[t])return!1;return!0},construct:function(e){return null!==e?e:{}}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:js/undefined\",{kind:\"scalar\",resolve:function(){return!0},construct:function(){},predicate:function(e){return void 0===e},represent:function(){return\"\"}})},function(e,t,n){\"use strict\";var r=n(3);e.exports=new r(\"tag:yaml.org,2002:js/regexp\",{kind:\"scalar\",resolve:function(e){if(null===e)return!1;if(0===e.length)return!1;var t=e,n=/\\/([gim]*)$/.exec(e),r=\"\";if(\"/\"===t[0]){if(n&&(r=n[1]),r.length>3)return!1;if(\"/\"!==t[t.length-r.length-1])return!1}return!0},construct:function(e){var t=e,n=/\\/([gim]*)$/.exec(e),r=\"\";return\"/\"===t[0]&&(n&&(r=n[1]),t=t.slice(1,t.length-r.length-1)),new RegExp(t,r)},predicate:function(e){return\"[object RegExp]\"===Object.prototype.toString.call(e)},represent:function(e){var t=\"/\"+e.source+\"/\";return e.global&&(t+=\"g\"),e.multiline&&(t+=\"m\"),e.ignoreCase&&(t+=\"i\"),t}})},function(e,t,n){\"use strict\";var r;try{r=n(214)}catch(e){\"undefined\"!=typeof window&&(r=window.esprima)}var o=n(3);e.exports=new o(\"tag:yaml.org,2002:js/function\",{kind:\"scalar\",resolve:function(e){if(null===e)return!1;try{var t=\"(\"+e+\")\",n=r.parse(t,{range:!0});return\"Program\"===n.type&&1===n.body.length&&\"ExpressionStatement\"===n.body[0].type&&(\"ArrowFunctionExpression\"===n.body[0].expression.type||\"FunctionExpression\"===n.body[0].expression.type)}catch(e){return!1}},construct:function(e){var t,n=\"(\"+e+\")\",o=r.parse(n,{range:!0}),i=[];if(\"Program\"!==o.type||1!==o.body.length||\"ExpressionStatement\"!==o.body[0].type||\"ArrowFunctionExpression\"!==o.body[0].expression.type&&\"FunctionExpression\"!==o.body[0].expression.type)throw new Error(\"Failed to resolve function\");return o.body[0].expression.params.forEach(function(e){i.push(e.name)}),t=o.body[0].expression.body.range,\"BlockStatement\"===o.body[0].expression.body.type?new Function(i,n.slice(t[0]+1,t[1]-1)):new Function(i,\"return \"+n.slice(t[0],t[1]))},predicate:function(e){return\"[object Function]\"===Object.prototype.toString.call(e)},represent:function(e){return e.toString()}})},function(e,n){if(void 0===t){var r=new Error(\"Cannot find module 'esprima'\");throw r.code=\"MODULE_NOT_FOUND\",r}e.exports=t},function(e,t){e.exports=function(){}},function(e,t){e.exports=function(e){var t=Array.prototype.slice.call(arguments,1);return t.length&&(e=e.replace(/(%?)(%([jds]))/g,function(e,n,r,o){var i=t.shift();switch(o){case\"s\":i=\"\"+i;break;case\"d\":i=Number(i);break;case\"j\":i=JSON.stringify(i)}return n?(t.unshift(i),e):i})),t.length&&(e+=\" \"+t.join(\" \")),\"\"+(e=e.replace(/%{2,2}/g,\"%\"))}},function(e,t,n){\"use strict\";(function(t){var n=/\\.(txt|htm|html|md|xml|js|min|map|css|scss|less|svg)$/i;e.exports={order:300,allowEmpty:!0,encoding:\"utf8\",canParse:function(e){return(\"string\"==typeof e.data||t.isBuffer(e.data))&&n.test(e.url)},parse:function(e){if(\"string\"==typeof e.data)return e.data;if(t.isBuffer(e.data))return e.data.toString(this.encoding);throw new Error(\"data is not text\")}}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";(function(t){var n=/\\.(jpeg|jpg|gif|png|bmp|ico)$/i;e.exports={order:400,allowEmpty:!0,canParse:function(e){return t.isBuffer(e.data)&&n.test(e.url)},parse:function(e){return t.isBuffer(e.data)?e.data:new t(e.data)}}}).call(this,n(9).Buffer)},function(e,t,n){\"use strict\";var r=n(220),o=n(25),i=n(19);e.exports={order:100,canRead:function(e){return i.isFileSystemPath(e.url)},read:function(e){return new Promise(function(t,n){var a;try{a=i.toFileSystemPath(e.url)}catch(t){n(o.uri(t,\"Malformed URI: %s\",e.url))}try{r.readFile(a,function(e,r){e?n(o(e,'Error opening file \"%s\"',a)):t(r)})}catch(e){n(o(e,'Error opening file \"%s\"',a))}})}}},function(e,t){},function(e,t,n){\"use strict\";(function(t,r){var o=n(106),i=n(233),a=n(25),s=n(19);e.exports={order:200,headers:null,timeout:5e3,redirects:5,withCredentials:!1,canRead:function(e){return s.isHttp(e.url)},read:function(e){var n=s.parse(e.url);return t.browser&&!n.protocol&&(n.protocol=s.parse(location.href).protocol),function e(t,n,l){return new Promise(function(c,u){t=s.parse(t),(l=l||[]).push(t.href),function(e,t){return new Promise(function(n,a){var s=\"https:\"===e.protocol?i:o,l=s.get({hostname:e.hostname,port:e.port,path:e.path,auth:e.auth,protocol:e.protocol,headers:t.headers||{},withCredentials:t.withCredentials});\"function\"==typeof l.setTimeout&&l.setTimeout(t.timeout),l.on(\"timeout\",function(){l.abort()}),l.on(\"error\",a),l.once(\"response\",function(e){e.body=new r(0),e.on(\"data\",function(t){e.body=r.concat([e.body,new r(t)])}),e.on(\"error\",a),e.on(\"end\",function(){n(e)})})})}(t,n).then(function(o){if(o.statusCode>=400)throw a({status:o.statusCode},\"HTTP ERROR %d\",o.statusCode);if(o.statusCode>=300)if(l.length>n.redirects)u(a({status:o.statusCode},\"Error downloading %s. \\nToo many redirects: \\n  %s\",l[0],l.join(\" \\n  \")));else{if(!o.headers.location)throw a({status:o.statusCode},\"HTTP %d redirect with no location header\",o.statusCode);var i=s.resolve(t,o.headers.location);e(i,n,l).then(c,u)}else c(o.body||new r(0))}).catch(function(e){u(a(e,\"Error downloading\",t.href))})})}(n,this)}}}).call(this,n(6),n(9).Buffer)},function(e,t,n){(function(t,r,o){var i=n(107),a=n(20),s=n(108),l=n(109),c=n(230),u=s.IncomingMessage,p=s.readyStates;var f=e.exports=function(e){var n,r=this;l.Writable.call(r),r._opts=e,r._body=[],r._headers={},e.auth&&r.setHeader(\"Authorization\",\"Basic \"+new t(e.auth).toString(\"base64\")),Object.keys(e.headers).forEach(function(t){r.setHeader(t,e.headers[t])});var o=!0;if(\"disable-fetch\"===e.mode||\"requestTimeout\"in e&&!i.abortController)o=!1,n=!0;else if(\"prefer-streaming\"===e.mode)n=!1;else if(\"allow-wrong-content-type\"===e.mode)n=!i.overrideMimeType;else{if(e.mode&&\"default\"!==e.mode&&\"prefer-fast\"!==e.mode)throw new Error(\"Invalid value for opts.mode\");n=!0}r._mode=function(e,t){return i.fetch&&t?\"fetch\":i.mozchunkedarraybuffer?\"moz-chunked-arraybuffer\":i.msstream?\"ms-stream\":i.arraybuffer&&e?\"arraybuffer\":i.vbArray&&e?\"text:vbarray\":\"text\"}(n,o),r._fetchTimer=null,r.on(\"finish\",function(){r._onFinish()})};a(f,l.Writable),f.prototype.setHeader=function(e,t){var n=e.toLowerCase();-1===d.indexOf(n)&&(this._headers[n]={name:e,value:t})},f.prototype.getHeader=function(e){var t=this._headers[e.toLowerCase()];return t?t.value:null},f.prototype.removeHeader=function(e){delete this._headers[e.toLowerCase()]},f.prototype._onFinish=function(){var e=this;if(!e._destroyed){var n=e._opts,a=e._headers,s=null;\"GET\"!==n.method&&\"HEAD\"!==n.method&&(s=i.arraybuffer?c(t.concat(e._body)):i.blobConstructor?new r.Blob(e._body.map(function(e){return c(e)}),{type:(a[\"content-type\"]||{}).value||\"\"}):t.concat(e._body).toString());var l=[];if(Object.keys(a).forEach(function(e){var t=a[e].name,n=a[e].value;Array.isArray(n)?n.forEach(function(e){l.push([t,e])}):l.push([t,n])}),\"fetch\"===e._mode){var u=null;if(i.abortController){var f=new AbortController;u=f.signal,e._fetchAbortController=f,\"requestTimeout\"in n&&0!==n.requestTimeout&&(e._fetchTimer=r.setTimeout(function(){e.emit(\"requestTimeout\"),e._fetchAbortController&&e._fetchAbortController.abort()},n.requestTimeout))}r.fetch(e._opts.url,{method:e._opts.method,headers:l,body:s||void 0,mode:\"cors\",credentials:n.withCredentials?\"include\":\"same-origin\",signal:u}).then(function(t){e._fetchResponse=t,e._connect()},function(t){r.clearTimeout(e._fetchTimer),e._destroyed||e.emit(\"error\",t)})}else{var d=e._xhr=new r.XMLHttpRequest;try{d.open(e._opts.method,e._opts.url,!0)}catch(t){return void o.nextTick(function(){e.emit(\"error\",t)})}\"responseType\"in d&&(d.responseType=e._mode.split(\":\")[0]),\"withCredentials\"in d&&(d.withCredentials=!!n.withCredentials),\"text\"===e._mode&&\"overrideMimeType\"in d&&d.overrideMimeType(\"text/plain; charset=x-user-defined\"),\"requestTimeout\"in n&&(d.timeout=n.requestTimeout,d.ontimeout=function(){e.emit(\"requestTimeout\")}),l.forEach(function(e){d.setRequestHeader(e[0],e[1])}),e._response=null,d.onreadystatechange=function(){switch(d.readyState){case p.LOADING:case p.DONE:e._onXHRProgress()}},\"moz-chunked-arraybuffer\"===e._mode&&(d.onprogress=function(){e._onXHRProgress()}),d.onerror=function(){e._destroyed||e.emit(\"error\",new Error(\"XHR error\"))};try{d.send(s)}catch(t){return void o.nextTick(function(){e.emit(\"error\",t)})}}}},f.prototype._onXHRProgress=function(){(function(e){try{var t=e.status;return null!==t&&0!==t}catch(e){return!1}})(this._xhr)&&!this._destroyed&&(this._response||this._connect(),this._response._onXHRProgress())},f.prototype._connect=function(){var e=this;e._destroyed||(e._response=new u(e._xhr,e._fetchResponse,e._mode,e._fetchTimer),e._response.on(\"error\",function(t){e.emit(\"error\",t)}),e.emit(\"response\",e._response))},f.prototype._write=function(e,t,n){this._body.push(e),n()},f.prototype.abort=f.prototype.destroy=function(){this._destroyed=!0,r.clearTimeout(this._fetchTimer),this._response&&(this._response._destroyed=!0),this._xhr?this._xhr.abort():this._fetchAbortController&&this._fetchAbortController.abort()},f.prototype.end=function(e,t,n){\"function\"==typeof e&&(n=e,e=void 0),l.Writable.prototype.end.call(this,e,t,n)},f.prototype.flushHeaders=function(){},f.prototype.setTimeout=function(){},f.prototype.setNoDelay=function(){},f.prototype.setSocketKeepAlive=function(){};var d=[\"accept-charset\",\"accept-encoding\",\"access-control-request-headers\",\"access-control-request-method\",\"connection\",\"content-length\",\"cookie\",\"cookie2\",\"date\",\"dnt\",\"expect\",\"host\",\"keep-alive\",\"origin\",\"referer\",\"te\",\"trailer\",\"transfer-encoding\",\"upgrade\",\"via\"]}).call(this,n(9).Buffer,n(4),n(6))},function(e,t){},function(e,t,n){\"use strict\";var r=n(50).Buffer,o=n(225);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return\"\";for(var t=this.head,n=\"\"+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+\" \"+e})},function(e,t){},function(e,t,n){(function(e){var r=void 0!==e&&e||\"undefined\"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(227),t.setImmediate=\"undefined\"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate=\"undefined\"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(4))},function(e,t,n){(function(e,t){!function(e,n){\"use strict\";if(!e.setImmediate){var r,o,i,a,s,l=1,c={},u=!1,p=e.document,f=Object.getPrototypeOf&&Object.getPrototypeOf(e);f=f&&f.setTimeout?f:e,\"[object process]\"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){h(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage(\"\",\"*\"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){h(e.data)},r=function(e){i.port2.postMessage(e)}):p&&\"onreadystatechange\"in p.createElement(\"script\")?(o=p.documentElement,r=function(e){var t=p.createElement(\"script\");t.onreadystatechange=function(){h(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(h,0,e)}:(a=\"setImmediate$\"+Math.random()+\"$\",s=function(t){t.source===e&&\"string\"==typeof t.data&&0===t.data.indexOf(a)&&h(+t.data.slice(a.length))},e.addEventListener?e.addEventListener(\"message\",s,!1):e.attachEvent(\"onmessage\",s),r=function(t){e.postMessage(a+t,\"*\")}),f.setImmediate=function(e){\"function\"!=typeof e&&(e=new Function(\"\"+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return c[l]=o,r(l),l++},f.clearImmediate=d}function d(e){delete c[e]}function h(e){if(u)setTimeout(h,0,e);else{var t=c[e];if(t){u=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{d(e),u=!1}}}}}(\"undefined\"==typeof self?void 0===e?this:e:self)}).call(this,n(4),n(6))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&\"true\"===String(n).toLowerCase()}e.exports=function(e,t){if(n(\"noDeprecation\"))return e;var r=!1;return function(){if(!r){if(n(\"throwDeprecation\"))throw new Error(t);n(\"traceDeprecation\")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(4))},function(e,t,n){\"use strict\";e.exports=i;var r=n(116),o=n(38);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(20),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){var r=n(9).Buffer;e.exports=function(e){if(e instanceof Uint8Array){if(0===e.byteOffset&&e.byteLength===e.buffer.byteLength)return e.buffer;if(\"function\"==typeof e.buffer.slice)return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}if(r.isBuffer(e)){for(var t=new Uint8Array(e.length),n=e.length,o=0;o<n;o++)t[o]=e[o];return t.buffer}throw new Error(\"Argument must be a Buffer\")}},function(e,t){e.exports=function(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];for(var o in r)n.call(r,o)&&(e[o]=r[o])}return e};var n=Object.prototype.hasOwnProperty},function(e,t){e.exports={100:\"Continue\",101:\"Switching Protocols\",102:\"Processing\",200:\"OK\",201:\"Created\",202:\"Accepted\",203:\"Non-Authoritative Information\",204:\"No Content\",205:\"Reset Content\",206:\"Partial Content\",207:\"Multi-Status\",208:\"Already Reported\",226:\"IM Used\",300:\"Multiple Choices\",301:\"Moved Permanently\",302:\"Found\",303:\"See Other\",304:\"Not Modified\",305:\"Use Proxy\",307:\"Temporary Redirect\",308:\"Permanent Redirect\",400:\"Bad Request\",401:\"Unauthorized\",402:\"Payment Required\",403:\"Forbidden\",404:\"Not Found\",405:\"Method Not Allowed\",406:\"Not Acceptable\",407:\"Proxy Authentication Required\",408:\"Request Timeout\",409:\"Conflict\",410:\"Gone\",411:\"Length Required\",412:\"Precondition Failed\",413:\"Payload Too Large\",414:\"URI Too Long\",415:\"Unsupported Media Type\",416:\"Range Not Satisfiable\",417:\"Expectation Failed\",418:\"I'm a teapot\",421:\"Misdirected Request\",422:\"Unprocessable Entity\",423:\"Locked\",424:\"Failed Dependency\",425:\"Unordered Collection\",426:\"Upgrade Required\",428:\"Precondition Required\",429:\"Too Many Requests\",431:\"Request Header Fields Too Large\",451:\"Unavailable For Legal Reasons\",500:\"Internal Server Error\",501:\"Not Implemented\",502:\"Bad Gateway\",503:\"Service Unavailable\",504:\"Gateway Timeout\",505:\"HTTP Version Not Supported\",506:\"Variant Also Negotiates\",507:\"Insufficient Storage\",508:\"Loop Detected\",509:\"Bandwidth Limit Exceeded\",510:\"Not Extended\",511:\"Network Authentication Required\"}},function(e,t,n){var r=n(106),o=n(10),i=e.exports;for(var a in r)r.hasOwnProperty(a)&&(i[a]=r[a]);function s(e){if(\"string\"==typeof e&&(e=o.parse(e)),e.protocol||(e.protocol=\"https:\"),\"https:\"!==e.protocol)throw new Error('Protocol \"'+e.protocol+'\" not supported. Expected \"https:\"');return e}i.request=function(e,t){return e=s(e),r.request.call(this,e,t)},i.get=function(e,t){return e=s(e),r.get.call(this,e,t)}},function(e,t,n){\"use strict\";var r=n(25),o=n(51),i=n(19);function a(){this.circular=!1,this._$refs={},this._root$Ref=null}function s(e,t){var n=Object.keys(e);return(t=Array.isArray(t[0])?t[0]:Array.prototype.slice.call(t)).length>0&&t[0]&&(n=n.filter(function(n){return-1!==t.indexOf(e[n].pathType)})),n.map(function(t){return{encoded:t,decoded:\"file\"===e[t].pathType?i.toFileSystemPath(t,!0):t}})}e.exports=a,a.prototype.paths=function(e){return s(this._$refs,arguments).map(function(e){return e.decoded})},a.prototype.values=function(e){var t=this._$refs;return s(t,arguments).reduce(function(e,n){return e[n.decoded]=t[n.encoded].value,e},{})},a.prototype.toJSON=a.prototype.values,a.prototype.exists=function(e,t){try{return this._resolve(e,t),!0}catch(e){return!1}},a.prototype.get=function(e,t){return this._resolve(e,t).value},a.prototype.set=function(e,t){var n=i.resolve(this._root$Ref.path,e),o=i.stripHash(n),a=this._$refs[o];if(!a)throw r('Error resolving $ref pointer \"%s\". \\n\"%s\" not found.',e,o);a.set(n,t)},a.prototype._add=function(e){var t=i.stripHash(e),n=new o;return n.path=t,n.$refs=this,this._$refs[t]=n,this._root$Ref=this._root$Ref||n,n},a.prototype._resolve=function(e,t){var n=i.resolve(this._root$Ref.path,e),o=i.stripHash(n),a=this._$refs[o];if(!a)throw r('Error resolving $ref pointer \"%s\". \\n\"%s\" not found.',e,o);return a.resolve(n,t,e)},a.prototype._get$Ref=function(e){e=i.resolve(this._root$Ref.path,e);var t=i.stripHash(e);return this._$refs[t]}},function(e,t,n){\"use strict\";function r(e,t,n,r){var o=e[t];if(\"function\"==typeof o)return o.apply(e,[n,r]);if(!r){if(o instanceof RegExp)return o.test(n.url);if(\"string\"==typeof o)return o===n.extension;if(Array.isArray(o))return-1!==o.indexOf(n.extension)}return o}t.all=function(e){return Object.keys(e).filter(function(t){return\"object\"==typeof e[t]}).map(function(t){return e[t].name=t,e[t]})},t.filter=function(e,t,n){return e.filter(function(e){return!!r(e,t,n)})},t.sort=function(e){return e.forEach(function(e){e.order=e.order||Number.MAX_SAFE_INTEGER}),e.sort(function(e,t){return e.order-t.order})},t.run=function(e,t,n){var o,i,a=0;return new Promise(function(s,l){function c(){if(!(o=e[a++]))return l(i);try{var s=r(o,t,n,u);s&&\"function\"==typeof s.then?s.then(p,f):void 0!==s&&p(s)}catch(e){f(e)}}function u(e,t){e?f(e):p(t)}function p(e){s({plugin:o,result:e})}function f(e){i=e,c()}c()})}},function(e,t,n){\"use strict\";var r=n(102);e.exports=function(e){var t,n,o,i;\"function\"==typeof(e=Array.prototype.slice.call(e))[e.length-1]&&(i=e.pop());\"string\"==typeof e[0]?(t=e[0],\"object\"==typeof e[2]?(n=e[1],o=e[2]):(n=void 0,o=e[1])):(t=\"\",n=e[0],o=e[1]);o instanceof r||(o=new r(o));return{path:t,schema:n,options:o,callback:i}}},function(e,t,n){\"use strict\";var r=n(51),o=n(75),i=n(117),a=n(19);function s(e,t,n,i){var a=[];return e&&\"object\"==typeof e&&(r.isExternal$Ref(e)?a.push(l(e,t,n,i)):Object.keys(e).forEach(function(c){var u=o.join(t,c),p=e[c];r.isExternal$Ref(p)?a.push(l(p,u,n,i)):a=a.concat(s(p,u,n,i))})),a}function l(e,t,n,r){var o=a.resolve(t,e.$ref),l=a.stripHash(o);return(e=n._$refs[l])?Promise.resolve(e.value):i(o,n,r).then(function(e){var t=s(e,l+\"#\",n,r);return Promise.all(t)})}e.exports=function(e,t){if(!t.resolve.external)return Promise.resolve();try{var n=s(e.schema,e.$refs._root$Ref.path+\"#\",e.$refs,t);return Promise.all(n)}catch(e){return Promise.reject(e)}}},function(e,t,n){\"use strict\";var r=n(51),o=n(75),i=n(19);function a(e,t,n,i,l,c,u,p){var f=null===t?e:e[t];f&&\"object\"==typeof f&&(r.isAllowed$Ref(f)?s(e,t,n,i,l,c,u,p):Object.keys(f).sort(function(e,t){return\"definitions\"===e?-1:\"definitions\"===t?1:e.length-t.length}).forEach(function(e){var t=o.join(n,e),d=o.join(i,e),h=f[e];r.isAllowed$Ref(h)?s(f,e,n,d,l,c,u,p):a(f,e,t,d,l,c,u,p)}))}function s(e,t,n,s,l,c,u,p){var f=null===t?e:e[t],d=i.resolve(n,f.$ref),h=u._resolve(d,p),m=o.parse(s).length,g=i.stripHash(h.path),y=i.getHash(h.path),v=g!==u._root$Ref.path,b=r.isExtended$Ref(f);l+=h.indirections;var w=function(e,t,n){for(var r=0;r<e.length;r++){var o=e[r];if(o.parent===t&&o.key===n)return o}}(c,e,t);if(w){if(!(m<w.depth||l<w.indirections))return;!function(e,t){var n=e.indexOf(t);e.splice(n,1)}(c,w)}c.push({$ref:f,parent:e,key:t,pathFromRoot:s,depth:m,file:g,hash:y,value:h.value,circular:h.circular,extended:b,external:v,indirections:l}),a(h.value,null,h.path,s,l+1,c,u,p)}e.exports=function(e,t){var n=[];a(e,\"schema\",e.$refs._root$Ref.path+\"#\",\"#\",0,n,e.$refs,t),function(e){var t,n,i;e.sort(function(e,t){if(e.file!==t.file)return e.file<t.file?-1:1;if(e.hash!==t.hash)return e.hash<t.hash?-1:1;if(e.circular!==t.circular)return e.circular?-1:1;if(e.extended!==t.extended)return e.extended?1:-1;if(e.indirections!==t.indirections)return e.indirections-t.indirections;if(e.depth!==t.depth)return e.depth-t.depth;var n=e.pathFromRoot.lastIndexOf(\"/definitions\"),r=t.pathFromRoot.lastIndexOf(\"/definitions\");return n!==r?r-n:e.pathFromRoot.length-t.pathFromRoot.length}),e.forEach(function(e){e.external?e.file===t&&e.hash===n?e.$ref.$ref=i:e.file===t&&0===e.hash.indexOf(n+\"/\")?e.$ref.$ref=o.join(i,o.parse(e.hash.replace(n,\"#\"))):(t=e.file,n=e.hash,i=e.pathFromRoot,e.$ref=e.parent[e.key]=r.dereference(e.$ref,e.value),e.circular&&(e.$ref.$ref=e.pathFromRoot)):e.$ref.$ref=e.hash})}(n)}},function(e,t){e.exports=function(){}},function(e,t,n){\"use strict\";var r=n(119),o=n(52),i=n(10),a=(n(241),n(120)),s=n(46),l=n(76).jptr,c=n(122).recurse,u=n(77).clone,p=n(121).isRef,f=n(123);function d(e,t,n,r,o,a){for(var s=a.externalRefs[n+r].paths[0],d=i.parse(o),h={},m=1;m;)m=0,c(e,{identityDetection:!0},function(e,n,r){if(p(e,n))if(e[n].startsWith(\"#\"))if(h[e[n]]||e.$fixed){if(!e.$fixed){var c=(s+\"/\"+h[e[n]]).split(\"/#/\").join(\"/\");r.parent[r.pkey]={$ref:c,\"x-miro\":e[n],$fixed:!0},a.verbose>1&&console.log(\"Replacing with\",c),m++}}else{var g=u(l(t,e[n]));if(a.verbose>1&&console.log((!1===g?f.colour.red:f.colour.green)+\"Internal resolution\",e[n],f.colour.normal),!1===g){if(r.parent[r.pkey]={},a.fatal){var y=new Error(\"Internal $ref resolution failed \"+e[n]);if(!a.promise)throw y;a.promise.reject(y)}}else m++,r.parent[r.pkey]=g,h[e[n]]=r.path.replace(\"/%24ref\",\"\")}else if(d.protocol){c=i.resolve(o,e[n]).toString();a.verbose>1&&console.log(f.colour.yellow+\"Rewriting external url ref\",e[n],\"as\",c,f.colour.normal),e[\"x-miro\"]=e[n],e[n]=c}else if(!e[\"x-miro\"]){c=i.resolve(o,e[n]).toString();a.verbose>1&&console.log(f.colour.yellow+\"Rewriting external ref\",e[n],\"as\",c,f.colour.normal),e[\"x-miro\"]=e[n],e[n]=c}});return c(e,{},function(e,t,n){p(e,t)&&(void 0!==e.$fixed&&delete e.$fixed,a.preserveMiro||delete e[\"x-miro\"])}),a.verbose>1&&console.log(\"Finished internal resolution\"),e}function h(e,t){if(!t.filters||!t.filters.length)return e;for(var n=0,r=t.filters;n<r.length;n++){e=(0,r[n])(e,t)}return e}function m(e,t,n,c){var p=i.parse(n.source),f=n.source.split(\"\\\\\").join(\"/\").split(\"/\");f.pop()||f.pop();var m=\"\",g=t.split(\"#\");g.length>1&&(m=\"#\"+g[1],t=g[0]),f=f.join(\"/\");var y,v,b,w=i.parse(t),x=w.protocol?w.protocol:p.protocol?p.protocol:\"file:\";if(y=\"file:\"===x?o.resolve(f?f+\"/\":\"\",t):i.resolve(f?f+\"/\":\"\",t),n.cache[y]){n.verbose&&console.log(\"CACHED\",y,m);var k=u(n.cache[y]),E=k;if(m&&!1===(E=l(E,m))&&(E={},n.fatal)){var S=new Error(\"Cached $ref resolution failed \"+y+m);if(!n.promise)throw S;n.promise.reject(S)}return E=h(E=d(E,k,t,m,y,n),n),c(u(E),y,n),Promise.resolve(E)}return n.verbose&&console.log(\"GET\",y,m),n.handlers&&n.handlers[x]?n.handlers[x](f,t,m,n).then(function(e){return e=h(e,n),n.cache[y]=e,c(e,y,n),e}).catch(function(e){throw n.verbose&&console.warn(e),e}):x&&x.startsWith(\"http\")?a(y,{agent:n.agent}).then(function(e){if(200!==e.status)throw new Error(\"Received status code \"+e.status);return e.text()}).then(function(e){try{var r=s.safeLoad(e,{json:!0});if(e=r,n.cache[y]=u(e),m&&!1===(e=l(e,m))&&(e={},n.fatal)){var o=new Error(\"Remote $ref resolution failed \"+y+m);if(!n.promise)throw o;n.promise.reject(o)}e=h(e=d(e,r,t,m,y,n),n)}catch(o){if(n.verbose&&console.warn(o),!n.promise||!n.fatal)throw o;n.promise.reject(o)}return c(e,y,n),e}).catch(function(e){if(n.verbose&&console.warn(e),n.cache[y]={},!n.promise||!n.fatal)throw e;n.promise.reject(e)}):(v=y,b=n.encoding||\"utf8\",new Promise(function(e,t){r.readFile(v,b,function(n,r){n?t(n):e(r)})})).then(function(e){try{var r=s.safeLoad(e,{json:!0});if(e=r,n.cache[y]=u(e),m&&!1===(e=l(e,m))&&(e={},n.fatal)){var o=new Error(\"File $ref resolution failed \"+y+m);if(!n.promise)throw o;n.promise.reject(o)}e=h(e=d(e,r,t,m,y,n),n)}catch(o){if(n.verbose&&console.warn(o),!n.promise||!n.fatal)throw o;n.promise.reject(o)}return c(e,y,n),e}).catch(function(e){if(n.verbose&&console.warn(e),!n.promise||!n.fatal)throw e;n.promise.reject(e)})}function g(e){return new Promise(function(t,n){(function(e){return new Promise(function(t,n){var r=e.externalRefs;if(e.resolver.depth>0&&e.source===e.resolver.base)return t(r);c(e.openapi,{identityDetection:!0},function(t,n,o){if(t[n]&&p(t[n],\"$ref\")){var i=t[n].$ref;if(!i.startsWith(\"#\"))if(r[i]||(r[i]={resolved:!1,paths:[],description:t[n].description}),r[i].resolved)if(e.rewriteRefs){var a=r[i].resolvedAt;e.verbose>1&&console.log(\"Rewriting ref\",i,a),t[n][\"x-miro\"]=i,t[n].$ref=a}else t[n]=u(r[i].data);else r[i].paths.push(o.path)}}),t(r)})})(e).then(function(t){var n=function(n){if(!t[n].resolved){var r=e.resolver.depth;r>0&&r++,e.resolver.actions[r].push(function(){return m(e.openapi,n,e,function(e,r,o){if(!t[n].resolved){var i={};i.context=t[n],i.$ref=n,i.original=u(e),i.updated=e,i.source=r,o.externals.push(i),t[n].resolved=!0}var a=Object.assign({},o,{source:\"\",resolver:{actions:o.resolver.actions,depth:o.resolver.actions.length-1,base:o.resolver.base}});o.patch&&t[n].description&&!e.description&&\"object\"==typeof e&&(e.description=t[n].description),t[n].data=e;for(var s,c=0,p=(s=t[n].paths,new Set(s).slice());c<p.length;c++){var f=p[c];if(t[n].resolvedAt&&f!==t[n].resolvedAt&&f.indexOf(\"x-ms-examples/\")<0)o.verbose>1&&console.log(\"Creating pointer to data at\",f),l(o.openapi,f,{$ref:t[n].resolvedAt,\"x-miro\":n});else{t[n].resolvedAt?o.verbose>1&&console.log(\"Avoiding circular reference\"):(t[n].resolvedAt=f,o.verbose>1&&console.log(\"Creating initial clone of data at\",f));var d=u(e);l(o.openapi,f,d)}}0===o.resolver.actions[a.resolver.depth].length&&o.resolver.actions[a.resolver.depth].push(function(){return g(a)})})})}};for(var r in t)n(r)}).catch(function(t){e.verbose&&console.warn(t),n(t)});var r={options:e};r.actions=e.resolver.actions[e.resolver.depth],t(r)})}var y=function(e){return e.reduce(function(e,t){return e.then(function(e){return t().then(Array.prototype.concat.bind(e))})},Promise.resolve([]))};function v(e,t,n){e.resolver.actions.push([]),g(e).then(function(r){y(r.actions).then(function(){if(e.resolver.depth>=e.resolver.actions.length)return console.warn(\"Ran off the end of resolver actions\"),t(!0);e.resolver.depth++,e.resolver.actions[e.resolver.depth].length?setTimeout(function(){v(r.options,t,n)},0):(e.verbose>1&&console.log(f.colour.yellow+\"Finished resolution!\",f.colour.normal),t(e))}).catch(function(t){e.verbose&&console.warn(t),n(t)})}).catch(function(t){e.verbose&&console.warn(t),n(t)})}function b(e){(e.cache||(e.cache={}),e.source)&&(i.parse(e.source).protocol||(e.source=o.resolve(e.source)));e.externals||(e.externals=[]),e.externalRefs||(e.externalRefs=[]),e.rewriteRefs=!0,e.resolver={},e.resolver.depth=0,e.resolver.base=e.source,e.resolver.actions=[[]]}e.exports={optionalResolve:function(e){return b(e),new Promise(function(t,n){e.resolve?v(e,t,n):t(e)})},resolve:function(e,t,n){return n||(n={}),n.openapi=e,n.source=t,n.resolve=!0,b(n),new Promise(function(e,t){v(n,e,t)})}}},function(e,t,n){(function(e,r){var o=/%[sdj%]/g;t.format=function(e){if(!y(e)){for(var t=[],n=0;n<arguments.length;n++)t.push(s(arguments[n]));return t.join(\" \")}n=1;for(var r=arguments,i=r.length,a=String(e).replace(o,function(e){if(\"%%\"===e)return\"%\";if(n>=i)return e;switch(e){case\"%s\":return String(r[n++]);case\"%d\":return Number(r[n++]);case\"%j\":try{return JSON.stringify(r[n++])}catch(e){return\"[Circular]\"}default:return e}}),l=r[n];n<i;l=r[++n])m(l)||!w(l)?a+=\" \"+l:a+=\" \"+s(l);return a},t.deprecate=function(n,o){if(v(e.process))return function(){return t.deprecate(n,o).apply(this,arguments)};if(!0===r.noDeprecation)return n;var i=!1;return function(){if(!i){if(r.throwDeprecation)throw new Error(o);r.traceDeprecation?console.trace(o):console.error(o),i=!0}return n.apply(this,arguments)}};var i,a={};function s(e,n){var r={seen:[],stylize:c};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),h(n)?r.showHidden=n:n&&t._extend(r,n),v(r.showHidden)&&(r.showHidden=!1),v(r.depth)&&(r.depth=2),v(r.colors)&&(r.colors=!1),v(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=l),u(r,e,r.depth)}function l(e,t){var n=s.styles[t];return n?\"\u001b[\"+s.colors[n][0]+\"m\"+e+\"\u001b[\"+s.colors[n][1]+\"m\":e}function c(e,t){return e}function u(e,n,r){if(e.customInspect&&n&&E(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return y(o)||(o=u(e,o,r)),o}var i=function(e,t){if(v(t))return e.stylize(\"undefined\",\"undefined\");if(y(t)){var n=\"'\"+JSON.stringify(t).replace(/^\"|\"$/g,\"\").replace(/'/g,\"\\\\'\").replace(/\\\\\"/g,'\"')+\"'\";return e.stylize(n,\"string\")}if(g(t))return e.stylize(\"\"+t,\"number\");if(h(t))return e.stylize(\"\"+t,\"boolean\");if(m(t))return e.stylize(\"null\",\"null\")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),k(n)&&(a.indexOf(\"message\")>=0||a.indexOf(\"description\")>=0))return p(n);if(0===a.length){if(E(n)){var l=n.name?\": \"+n.name:\"\";return e.stylize(\"[Function\"+l+\"]\",\"special\")}if(b(n))return e.stylize(RegExp.prototype.toString.call(n),\"regexp\");if(x(n))return e.stylize(Date.prototype.toString.call(n),\"date\");if(k(n))return p(n)}var c,w=\"\",S=!1,_=[\"{\",\"}\"];(d(n)&&(S=!0,_=[\"[\",\"]\"]),E(n))&&(w=\" [Function\"+(n.name?\": \"+n.name:\"\")+\"]\");return b(n)&&(w=\" \"+RegExp.prototype.toString.call(n)),x(n)&&(w=\" \"+Date.prototype.toUTCString.call(n)),k(n)&&(w=\" \"+p(n)),0!==a.length||S&&0!=n.length?r<0?b(n)?e.stylize(RegExp.prototype.toString.call(n),\"regexp\"):e.stylize(\"[Object]\",\"special\"):(e.seen.push(n),c=S?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a<s;++a)C(t,String(a))?i.push(f(e,t,n,r,String(a),!0)):i.push(\"\");return o.forEach(function(o){o.match(/^\\d+$/)||i.push(f(e,t,n,r,o,!0))}),i}(e,n,r,s,a):a.map(function(t){return f(e,n,r,s,t,S)}),e.seen.pop(),function(e,t,n){if(e.reduce(function(e,t){return 0,t.indexOf(\"\\n\")>=0&&0,e+t.replace(/\\u001b\\[\\d\\d?m/g,\"\").length+1},0)>60)return n[0]+(\"\"===t?\"\":t+\"\\n \")+\" \"+e.join(\",\\n  \")+\" \"+n[1];return n[0]+t+\" \"+e.join(\", \")+\" \"+n[1]}(c,w,_)):_[0]+w+_[1]}function p(e){return\"[\"+Error.prototype.toString.call(e)+\"]\"}function f(e,t,n,r,o,i){var a,s,l;if((l=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=l.set?e.stylize(\"[Getter/Setter]\",\"special\"):e.stylize(\"[Getter]\",\"special\"):l.set&&(s=e.stylize(\"[Setter]\",\"special\")),C(r,o)||(a=\"[\"+o+\"]\"),s||(e.seen.indexOf(l.value)<0?(s=m(n)?u(e,l.value,null):u(e,l.value,n-1)).indexOf(\"\\n\")>-1&&(s=i?s.split(\"\\n\").map(function(e){return\"  \"+e}).join(\"\\n\").substr(2):\"\\n\"+s.split(\"\\n\").map(function(e){return\"   \"+e}).join(\"\\n\")):s=e.stylize(\"[Circular]\",\"special\")),v(a)){if(i&&o.match(/^\\d+$/))return s;(a=JSON.stringify(\"\"+o)).match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,\"name\")):(a=a.replace(/'/g,\"\\\\'\").replace(/\\\\\"/g,'\"').replace(/(^\"|\"$)/g,\"'\"),a=e.stylize(a,\"string\"))}return a+\": \"+s}function d(e){return Array.isArray(e)}function h(e){return\"boolean\"==typeof e}function m(e){return null===e}function g(e){return\"number\"==typeof e}function y(e){return\"string\"==typeof e}function v(e){return void 0===e}function b(e){return w(e)&&\"[object RegExp]\"===S(e)}function w(e){return\"object\"==typeof e&&null!==e}function x(e){return w(e)&&\"[object Date]\"===S(e)}function k(e){return w(e)&&(\"[object Error]\"===S(e)||e instanceof Error)}function E(e){return\"function\"==typeof e}function S(e){return Object.prototype.toString.call(e)}function _(e){return e<10?\"0\"+e.toString(10):e.toString(10)}t.debuglog=function(e){if(v(i)&&(i=r.env.NODE_DEBUG||\"\"),e=e.toUpperCase(),!a[e])if(new RegExp(\"\\\\b\"+e+\"\\\\b\",\"i\").test(i)){var n=r.pid;a[e]=function(){var r=t.format.apply(t,arguments);console.error(\"%s %d: %s\",e,n,r)}}else a[e]=function(){};return a[e]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:\"cyan\",number:\"yellow\",boolean:\"yellow\",undefined:\"grey\",null:\"bold\",string:\"green\",date:\"magenta\",regexp:\"red\"},t.isArray=d,t.isBoolean=h,t.isNull=m,t.isNullOrUndefined=function(e){return null==e},t.isNumber=g,t.isString=y,t.isSymbol=function(e){return\"symbol\"==typeof e},t.isUndefined=v,t.isRegExp=b,t.isObject=w,t.isDate=x,t.isError=k,t.isFunction=E,t.isPrimitive=function(e){return null===e||\"boolean\"==typeof e||\"number\"==typeof e||\"string\"==typeof e||\"symbol\"==typeof e||void 0===e},t.isBuffer=n(242);var O=[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log(\"%s - %s\",(e=new Date,n=[_(e.getHours()),_(e.getMinutes()),_(e.getSeconds())].join(\":\"),[e.getDate(),O[e.getMonth()],n].join(\" \")),t.format.apply(t,arguments))},t.inherits=n(20),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e}}).call(this,n(4),n(6))},function(e,t){e.exports=function(e){return e&&\"object\"==typeof e&&\"function\"==typeof e.copy&&\"function\"==typeof e.fill&&\"function\"==typeof e.readUInt8}},function(e,t,n){\"use strict\";function r(){return{depth:0,seen:new WeakMap,top:!0,combine:!1,allowRefSiblings:!1}}e.exports={getDefaultState:r,walkSchema:function e(t,n,o,i){if(void 0===o.depth&&(o=r()),null==t)return t;if(void 0!==t.$ref){var a={$ref:t.$ref};return o.allowRefSiblings&&t.description&&(a.description=t.description),i(a,n,o),a}if(o.combine&&(t.allOf&&Array.isArray(t.allOf)&&1===t.allOf.length&&delete(t=Object.assign({},t.allOf[0],t)).allOf,t.anyOf&&Array.isArray(t.anyOf)&&1===t.anyOf.length&&delete(t=Object.assign({},t.anyOf[0],t)).anyOf,t.oneOf&&Array.isArray(t.oneOf)&&1===t.oneOf.length&&delete(t=Object.assign({},t.oneOf[0],t)).oneOf),i(t,n,o),o.seen.has(t))return t;if(\"object\"==typeof t&&null!==t&&o.seen.set(t,!0),o.top=!1,o.depth++,void 0!==t.items&&(o.property=\"items\",e(t.items,t,o,i)),t.additionalItems&&\"object\"==typeof t.additionalItems&&(o.property=\"additionalItems\",e(t.additionalItems,t,o,i)),t.additionalProperties&&\"object\"==typeof t.additionalProperties&&(o.property=\"additionalProperties\",e(t.additionalProperties,t,o,i)),t.properties)for(var s in t.properties){var l=t.properties[s];o.property=\"properties/\"+s,e(l,t,o,i)}if(t.patternProperties)for(var s in t.patternProperties)l=t.patternProperties[s],o.property=\"patternProperties/\"+s,e(l,t,o,i);if(t.allOf)for(var c in t.allOf)l=t.allOf[c],o.property=\"allOf/\"+c,e(l,t,o,i);if(t.anyOf)for(var c in t.anyOf)l=t.anyOf[c],o.property=\"anyOf/\"+c,e(l,t,o,i);if(t.oneOf)for(var c in t.oneOf)l=t.oneOf[c],o.property=\"oneOf/\"+c,e(l,t,o,i);return t.not&&(o.property=\"not\",e(t.not,t,o,i)),o.depth--,t}}},function(e,t,n){\"use strict\";e.exports={statusCodes:[{code:\"default\",phrase:\"Default response\"},{code:\"1XX\",phrase:\"Informational\"},{code:\"100\",phrase:\"Continue\"},{code:\"101\",phrase:\"Switching Protocols\"},{code:\"2XX\",phrase:\"Successful\"},{code:\"200\",phrase:\"OK\"},{code:\"201\",phrase:\"Created\"},{code:\"202\",phrase:\"Accepted\"},{code:\"203\",phrase:\"Non-Authoritative Information\"},{code:\"204\",phrase:\"No Content\"},{code:\"205\",phrase:\"Reset Content\"},{code:\"206\",phrase:\"Partial Content\"},{code:\"3XX\",phrase:\"Redirection\"},{code:\"300\",phrase:\"Multiple Choices\"},{code:\"301\",phrase:\"Moved Permanently\"},{code:\"302\",phrase:\"Found\"},{code:\"303\",phrase:\"See Other\"},{code:\"304\",phrase:\"Not Modified\"},{code:\"305\",phrase:\"Use Proxy\"},{code:\"307\",phrase:\"Temporary Redirect\"},{code:\"4XX\",phrase:\"Client Error\"},{code:\"400\",phrase:\"Bad Request\"},{code:\"401\",phrase:\"Unauthorized\"},{code:\"402\",phrase:\"Payment Required\"},{code:\"403\",phrase:\"Forbidden\"},{code:\"404\",phrase:\"Not Found\"},{code:\"405\",phrase:\"Method Not Allowed\"},{code:\"406\",phrase:\"Not Acceptable\"},{code:\"407\",phrase:\"Proxy Authentication Required\"},{code:\"408\",phrase:\"Request Timeout\"},{code:\"409\",phrase:\"Conflict\"},{code:\"410\",phrase:\"Gone\"},{code:\"411\",phrase:\"Length Required\"},{code:\"412\",phrase:\"Precondition Failed\"},{code:\"413\",phrase:\"Payload Too Large\"},{code:\"414\",phrase:\"URI Too Long\"},{code:\"415\",phrase:\"Unsupported Media Type\"},{code:\"416\",phrase:\"Range Not Satisfiable\"},{code:\"417\",phrase:\"Expectation Failed\"},{code:\"418\",phrase:\"I'm a teapot\"},{code:\"421\",phrase:\"Misdirected request\"},{code:\"426\",phrase:\"Upgrade Required\"},{code:\"5XX\",phrase:\"Server Error\"},{code:\"500\",phrase:\"Internal Server Error\"},{code:\"501\",phrase:\"Not Implemented\"},{code:\"502\",phrase:\"Bad Gateway\"},{code:\"503\",phrase:\"Service Unavailable\"},{code:\"504\",phrase:\"Gateway Time-out\"},{code:\"505\",phrase:\"HTTP Version Not Supported\"},{code:\"102\",phrase:\"Processing\"},{code:\"103\",phrase:\"Early Hints\"},{code:\"207\",phrase:\"Multi-Status\"},{code:\"226\",phrase:\"IM Used\"},{code:\"308\",phrase:\"Permanent Redirect\"},{code:\"422\",phrase:\"Unprocessable Entity\"},{code:\"423\",phrase:\"Locked\"},{code:\"424\",phrase:\"Failed Dependency\"},{code:\"428\",phrase:\"Precondition Required\"},{code:\"429\",phrase:\"Too Many Requests\"},{code:\"431\",phrase:\"Request Header Fields Too Large\"},{code:\"451\",phrase:\"Unavailable For Legal Reasons\"},{code:\"506\",phrase:\"Variant Also Negotiates\"},{code:\"507\",phrase:\"Insufficient Storage\"},{code:\"511\",phrase:\"Network Authentication Required\"},{code:\"7XX\",phrase:\"Developer Error\"}]}},function(e){e.exports={name:\"swagger2openapi\",version:\"3.2.14\",description:\"Convert Swagger 2.0 definitions to OpenApi 3.0 and validate\",main:\"index.js\",bin:{swagger2openapi:\"./swagger2openapi.js\",\"oas-validate\":\"./oas-validate.js\",\"oas-resolve\":\"./oas-resolve.js\"},scripts:{test:\"mocha\"},browserify:{transform:[[\"babelify\",{presets:[\"es2015\"]}]]},repository:{url:\"https://github.com/Mermade/oas-kit.git\",type:\"git\"},author:\"Mike Ralphson <mike.ralphson@gmail.com>\",license:\"BSD-3-Clause\",dependencies:{\"call-me-maybe\":\"^1.0.1\",\"js-yaml\":\"^3.12.0\",\"node-fetch\":\"^2.3.0\",\"node-readfiles\":\"^0.2.0\",\"oas-kit-common\":\"^1.0.4\",\"oas-resolver\":\"^1.0.12\",\"oas-schema-walker\":\"^1.1.0\",\"oas-validator\":\"^1.1.13\",reftools:\"^1.0.3\",yargs:\"^12.0.2\"},keywords:[\"swagger\",\"openapi\",\"openapi2\",\"openapi3\",\"converter\",\"conversion\",\"validator\",\"validation\",\"resolver\",\"lint\",\"linter\"],gitHead:\"4862e159745d6ca06044bc3ebabe57a2ad8b7152\"}},function(e,t){var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;e.exports=function(e,t,o){if(\"[object Function]\"!==r.call(t))throw new TypeError(\"iterator must be a function\");var i=e.length;if(i===+i)for(var a=0;a<i;a++)t.call(o,e[a],a,e);else for(var s in e)n.call(e,s)&&t.call(o,e[s],s,e)}},function(e,t){!function(e){var t={variable:[{pattern:/\\$?\\(\\([\\s\\S]+?\\)\\)/,inside:{variable:[{pattern:/(^\\$\\(\\([\\s\\S]+)\\)\\)/,lookbehind:!0},/^\\$\\(\\(/],number:/\\b0x[\\dA-Fa-f]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:[Ee]-?\\d+)?/,operator:/--?|-=|\\+\\+?|\\+=|!=?|~|\\*\\*?|\\*=|\\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\\^=?|\\|\\|?|\\|=|\\?|:/,punctuation:/\\(\\(?|\\)\\)?|,|;/}},{pattern:/\\$\\([^)]+\\)|`[^`]+`/,greedy:!0,inside:{variable:/^\\$\\(|^`|\\)$|`$/}},/\\$(?:[\\w#?*!@]+|\\{[^}]+\\})/i]};e.languages.bash={shebang:{pattern:/^#!\\s*\\/bin\\/bash|^#!\\s*\\/bin\\/sh/,alias:\"important\"},comment:{pattern:/(^|[^\"{\\\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\\s*)[\"']?(\\w+?)[\"']?\\s*\\r?\\n(?:[\\s\\S])*?\\r?\\n\\2/,lookbehind:!0,greedy:!0,inside:t},{pattern:/([\"'])(?:\\\\[\\s\\S]|\\$\\([^)]+\\)|`[^`]+`|(?!\\1)[^\\\\])*\\1/,greedy:!0,inside:t}],variable:t.variable,function:{pattern:/(^|[\\s;|&])(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|[\\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\\s;|&])(?:let|:|\\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\\s;|&])/,lookbehind:!0},boolean:{pattern:/(^|[\\s;|&])(?:true|false)(?=$|[\\s;|&])/,lookbehind:!0},operator:/&&?|\\|\\|?|==?|!=?|<<<?|>>|<=?|>=?|=~/,punctuation:/\\$?\\(\\(?|\\)\\)?|\\.\\.|[{}[\\];]/};var n=t.variable[1].inside;n.string=e.languages.bash.string,n.function=e.languages.bash.function,n.keyword=e.languages.bash.keyword,n.boolean=e.languages.bash.boolean,n.operator=e.languages.bash.operator,n.punctuation=e.languages.bash.punctuation,e.languages.shell=e.languages.bash}(Prism)},function(e,t){Prism.languages.c=Prism.languages.extend(\"clike\",{keyword:/\\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\\b/,operator:/-[>-]?|\\+\\+?|!=?|<<?=?|>>?=?|==?|&&?|\\|\\|?|[~^%?*\\/]/,number:/(?:\\b0x[\\da-f]+|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?)[ful]*/i}),Prism.languages.insertBefore(\"c\",\"string\",{macro:{pattern:/(^\\s*)#\\s*[a-z]+(?:[^\\r\\n\\\\]|\\\\(?:\\r\\n|[\\s\\S]))*/im,lookbehind:!0,alias:\"property\",inside:{string:{pattern:/(#\\s*include\\s*)(?:<.+?>|(\"|')(?:\\\\?.)+?\\2)/,lookbehind:!0},directive:{pattern:/(#\\s*)\\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\\b/,lookbehind:!0,alias:\"keyword\"}}},constant:/\\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\\b/}),delete Prism.languages.c[\"class-name\"],delete Prism.languages.c.boolean},function(e,t){Prism.languages.clike={comment:[{pattern:/(^|[^\\\\])\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,lookbehind:!0},{pattern:/(^|[^\\\\:])\\/\\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/([\"'])(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0},\"class-name\":{pattern:/((?:\\b(?:class|interface|extends|implements|trait|instanceof|new)\\s+)|(?:catch\\s+\\())[\\w.\\\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\\\]/}},keyword:/\\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\\b/,boolean:/\\b(?:true|false)\\b/,function:/[a-z0-9_]+(?=\\()/i,number:/\\b0x[\\da-f]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?/i,operator:/--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*|\\/|~|\\^|%/,punctuation:/[{}[\\];(),.:]/}},function(e,t){!function(e){var t=/#(?!\\{).+/,n={pattern:/#\\{[^}]+\\}/,alias:\"variable\"};e.languages.coffeescript=e.languages.extend(\"javascript\",{comment:t,string:[{pattern:/'(?:\\\\[\\s\\S]|[^\\\\'])*'/,greedy:!0},{pattern:/\"(?:\\\\[\\s\\S]|[^\\\\\"])*\"/,greedy:!0,inside:{interpolation:n}}],keyword:/\\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\\b/,\"class-member\":{pattern:/@(?!\\d)\\w+/,alias:\"variable\"}}),e.languages.insertBefore(\"coffeescript\",\"comment\",{\"multiline-comment\":{pattern:/###[\\s\\S]+?###/,alias:\"comment\"},\"block-regex\":{pattern:/\\/{3}[\\s\\S]*?\\/{3}/,alias:\"regex\",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore(\"coffeescript\",\"string\",{\"inline-javascript\":{pattern:/`(?:\\\\[\\s\\S]|[^\\\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:\"punctuation\"},rest:e.languages.javascript}},\"multiline-string\":[{pattern:/'''[\\s\\S]*?'''/,greedy:!0,alias:\"string\"},{pattern:/\"\"\"[\\s\\S]*?\"\"\"/,greedy:!0,alias:\"string\",inside:{interpolation:n}}]}),e.languages.insertBefore(\"coffeescript\",\"keyword\",{property:/(?!\\d)\\w+(?=\\s*:(?!:))/}),delete e.languages.coffeescript[\"template-string\"]}(Prism)},function(e,t){Prism.languages.cpp=Prism.languages.extend(\"c\",{keyword:/\\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\\b/,boolean:/\\b(?:true|false)\\b/,operator:/--?|\\+\\+?|!=?|<{1,2}=?|>{1,2}=?|->|:{1,2}|={1,2}|\\^|~|%|&{1,2}|\\|\\|?|\\?|\\*|\\/|\\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\\b/}),Prism.languages.insertBefore(\"cpp\",\"keyword\",{\"class-name\":{pattern:/(class\\s+)\\w+/i,lookbehind:!0}}),Prism.languages.insertBefore(\"cpp\",\"string\",{\"raw-string\":{pattern:/R\"([^()\\\\ ]{0,16})\\([\\s\\S]*?\\)\\1\"/,alias:\"string\",greedy:!0}})},function(e,t){Prism.languages.csharp=Prism.languages.extend(\"clike\",{keyword:/\\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\\b/,string:[{pattern:/@(\"|')(?:\\1\\1|\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1/,greedy:!0},{pattern:/(\"|')(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*?\\1/,greedy:!0}],\"class-name\":[{pattern:/\\b[A-Z]\\w*(?:\\.\\w+)*\\b(?=\\s+\\w+)/,inside:{punctuation:/\\./}},{pattern:/(\\[)[A-Z]\\w*(?:\\.\\w+)*\\b/,lookbehind:!0,inside:{punctuation:/\\./}},{pattern:/(\\b(?:class|interface)\\s+[A-Z]\\w*(?:\\.\\w+)*\\s*:\\s*)[A-Z]\\w*(?:\\.\\w+)*\\b/,lookbehind:!0,inside:{punctuation:/\\./}},{pattern:/((?:\\b(?:class|interface|new)\\s+)|(?:catch\\s+\\())[A-Z]\\w*(?:\\.\\w+)*\\b/,lookbehind:!0,inside:{punctuation:/\\./}}],number:/\\b0x[\\da-f]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)f?/i}),Prism.languages.insertBefore(\"csharp\",\"class-name\",{\"generic-method\":{pattern:/\\w+\\s*<[^>\\r\\n]+?>\\s*(?=\\()/,inside:{function:/^\\w+/,\"class-name\":{pattern:/\\b[A-Z]\\w*(?:\\.\\w+)*\\b/,inside:{punctuation:/\\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\\s*)#.*/m,lookbehind:!0,alias:\"property\",inside:{directive:{pattern:/(\\s*#)\\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\\b/,lookbehind:!0,alias:\"keyword\"}}}}),Prism.languages.dotnet=Prism.languages.csharp},function(e,t){Prism.languages.go=Prism.languages.extend(\"clike\",{keyword:/\\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\\b/,builtin:/\\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\\b/,boolean:/\\b(?:_|iota|nil|true|false)\\b/,operator:/[*\\/%^!=]=?|\\+[=+]?|-[=-]?|\\|[=|]?|&(?:=|&|\\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\\.\\.\\./,number:/(?:\\b0x[a-f\\d]+|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[-+]?\\d+)?)i?/i,string:{pattern:/([\"'`])(\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1/,greedy:!0}}),delete Prism.languages.go[\"class-name\"]},function(e,t){Prism.languages.java=Prism.languages.extend(\"clike\",{keyword:/\\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\\b/,number:/\\b0b[01]+\\b|\\b0x[\\da-f]*\\.?[\\da-fp-]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?[df]?/i,operator:{pattern:/(^|[^.])(?:\\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\\|[|=]?|\\*=?|\\/=?|%=?|\\^=?|[?:~])/m,lookbehind:!0}}),Prism.languages.insertBefore(\"java\",\"function\",{annotation:{alias:\"punctuation\",pattern:/(^|[^.])@\\w+/,lookbehind:!0}}),Prism.languages.insertBefore(\"java\",\"class-name\",{generics:{pattern:/<\\s*\\w+(?:\\.\\w+)?(?:\\s*,\\s*\\w+(?:\\.\\w+)?)*>/i,alias:\"function\",inside:{keyword:Prism.languages.java.keyword,punctuation:/[<>(),.:]/}}})},function(e,t){Prism.languages.lua={comment:/^#!.+|--(?:\\[(=*)\\[[\\s\\S]*?\\]\\1\\]|.*)/m,string:{pattern:/([\"'])(?:(?!\\1)[^\\\\\\r\\n]|\\\\z(?:\\r\\n|\\s)|\\\\(?:\\r\\n|[\\s\\S]))*\\1|\\[(=*)\\[[\\s\\S]*?\\]\\2\\]/,greedy:!0},number:/\\b0x[a-f\\d]+\\.?[a-f\\d]*(?:p[+-]?\\d+)?\\b|\\b\\d+(?:\\.\\B|\\.?\\d*(?:e[+-]?\\d+)?\\b)|\\B\\.\\d+(?:e[+-]?\\d+)?\\b/i,keyword:/\\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b/,function:/(?!\\d)\\w+(?=\\s*(?:[({]))/,operator:[/[-+*%^&|#]|\\/\\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\\.\\.(?!\\.)/,lookbehind:!0}],punctuation:/[\\[\\](){},;]|\\.+|:+/}},function(e,t){Prism.languages[\"markup-templating\"]={},Object.defineProperties(Prism.languages[\"markup-templating\"],{buildPlaceholders:{value:function(e,t,n,r){e.language===t&&(e.tokenStack=[],e.code=e.code.replace(n,function(n){if(\"function\"==typeof r&&!r(n))return n;for(var o=e.tokenStack.length;-1!==e.code.indexOf(\"___\"+t.toUpperCase()+o+\"___\");)++o;return e.tokenStack[o]=n,\"___\"+t.toUpperCase()+o+\"___\"}),e.grammar=Prism.languages.markup)}},tokenizePlaceholders:{value:function(e,t){if(e.language===t&&e.tokenStack){e.grammar=Prism.languages[t];var n=0,r=Object.keys(e.tokenStack),o=function(i){if(!(n>=r.length))for(var a=0;a<i.length;a++){var s=i[a];if(\"string\"==typeof s||s.content&&\"string\"==typeof s.content){var l=r[n],c=e.tokenStack[l],u=\"string\"==typeof s?s:s.content,p=u.indexOf(\"___\"+t.toUpperCase()+l+\"___\");if(p>-1){++n;var f,d=u.substring(0,p),h=new Prism.Token(t,Prism.tokenize(c,e.grammar,t),\"language-\"+t,c),m=u.substring(p+(\"___\"+t.toUpperCase()+l+\"___\").length);if(d||m?(f=[d,h,m].filter(function(e){return!!e}),o(f)):f=h,\"string\"==typeof s?Array.prototype.splice.apply(i,[a,1].concat(f)):s.content=f,n>=r.length)break}}else s.content&&\"string\"!=typeof s.content&&o(s.content)}};o(e.tokens)}}}})},function(e,t){Prism.languages.markup={comment:/<!--[\\s\\S]*?-->/,prolog:/<\\?[\\s\\S]+?\\?>/,doctype:/<!DOCTYPE[\\s\\S]+?>/i,cdata:/<!\\[CDATA\\[[\\s\\S]*?]]>/i,tag:{pattern:/<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s+[^\\s>\\/=]+(?:=(?:(\"|')(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1|[^\\s'\">=]+))?)*\\s*\\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\\/?[^\\s>\\/]+/i,inside:{punctuation:/^<\\/?/,namespace:/^[^\\s>\\/:]+:/}},\"attr-value\":{pattern:/=(?:(\"|')(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1|[^\\s'\">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\\\])[\"']/,lookbehind:!0}]}},punctuation:/\\/?>/,\"attr-name\":{pattern:/[^\\s>\\/]+/,inside:{namespace:/^[^\\s>\\/:]+:/}}}},entity:/&#?[\\da-z]{1,8};/i},Prism.languages.markup.tag.inside[\"attr-value\"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add(\"wrap\",function(e){\"entity\"===e.type&&(e.attributes.title=e.content.replace(/&amp;/,\"&\"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup},function(e,t){Prism.languages.objectivec=Prism.languages.extend(\"c\",{keyword:/\\b(?:asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\\b/,string:/(\"|')(?:\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1|@\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"/,operator:/-[->]?|\\+\\+?|!=?|<<?=?|>>?=?|==?|&&?|\\|\\|?|[~^%?*\\/@]/})},function(e,t){Prism.languages.perl={comment:[{pattern:/(^\\s*)=\\w+[\\s\\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\\\$])#.*/,lookbehind:!0}],string:[{pattern:/\\b(?:q|qq|qx|qw)\\s*([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1/,greedy:!0},{pattern:/\\b(?:q|qq|qx|qw)\\s+([a-zA-Z0-9])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1/,greedy:!0},{pattern:/\\b(?:q|qq|qx|qw)\\s*\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)/,greedy:!0},{pattern:/\\b(?:q|qq|qx|qw)\\s*\\{(?:[^{}\\\\]|\\\\[\\s\\S])*\\}/,greedy:!0},{pattern:/\\b(?:q|qq|qx|qw)\\s*\\[(?:[^[\\]\\\\]|\\\\[\\s\\S])*\\]/,greedy:!0},{pattern:/\\b(?:q|qq|qx|qw)\\s*<(?:[^<>\\\\]|\\\\[\\s\\S])*>/,greedy:!0},{pattern:/(\"|`)(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1/,greedy:!0},{pattern:/'(?:[^'\\\\\\r\\n]|\\\\.)*'/,greedy:!0}],regex:[{pattern:/\\b(?:m|qr)\\s*([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1[msixpodualngc]*/,greedy:!0},{pattern:/\\b(?:m|qr)\\s+([a-zA-Z0-9])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1[msixpodualngc]*/,greedy:!0},{pattern:/\\b(?:m|qr)\\s*\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)[msixpodualngc]*/,greedy:!0},{pattern:/\\b(?:m|qr)\\s*\\{(?:[^{}\\\\]|\\\\[\\s\\S])*\\}[msixpodualngc]*/,greedy:!0},{pattern:/\\b(?:m|qr)\\s*\\[(?:[^[\\]\\\\]|\\\\[\\s\\S])*\\][msixpodualngc]*/,greedy:!0},{pattern:/\\b(?:m|qr)\\s*<(?:[^<>\\\\]|\\\\[\\s\\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s*([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\2)[^\\\\]|\\\\[\\s\\S])*\\2(?:(?!\\2)[^\\\\]|\\\\[\\s\\S])*\\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s+([a-zA-Z0-9])(?:(?!\\2)[^\\\\]|\\\\[\\s\\S])*\\2(?:(?!\\2)[^\\\\]|\\\\[\\s\\S])*\\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s*\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)\\s*\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s*\\{(?:[^{}\\\\]|\\\\[\\s\\S])*\\}\\s*\\{(?:[^{}\\\\]|\\\\[\\s\\S])*\\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s*\\[(?:[^[\\]\\\\]|\\\\[\\s\\S])*\\]\\s*\\[(?:[^[\\]\\\\]|\\\\[\\s\\S])*\\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\\b)(?:s|tr|y)\\s*<(?:[^<>\\\\]|\\\\[\\s\\S])*>\\s*<(?:[^<>\\\\]|\\\\[\\s\\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\\/(?:[^\\/\\\\\\r\\n]|\\\\.)*\\/[msixpodualngc]*(?=\\s*(?:$|[\\r\\n,.;})&|\\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\\b))/,greedy:!0}],variable:[/[&*$@%]\\{\\^[A-Z]+\\}/,/[&*$@%]\\^[A-Z_]/,/[&*$@%]#?(?=\\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\\d)[\\w$]+)+(?:::)*/i,/[&*$@%]\\d+/,/(?!%=)[$@%][!\"#$%&'()*+,\\-.\\/:;<=>?@[\\\\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\\S*>|\\b_\\b/,alias:\"symbol\"},vstring:{pattern:/v\\d+(?:\\.\\d+)*|\\d+(?:\\.\\d+){2,}/,alias:\"string\"},function:{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\\b/,number:/\\b(?:0x[\\dA-Fa-f](?:_?[\\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\\d(?:_?\\d)*)?\\.?\\d(?:_?\\d)*(?:[Ee][+-]?\\d+)?)\\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\\b|\\+[+=]?|-[-=>]?|\\*\\*?=?|\\/\\/?=?|=[=~>]?|~[~=]?|\\|\\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\\.(?:=|\\.\\.?)?|[\\\\?]|\\bx(?:=|\\b)|\\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\\b/,punctuation:/[{}[\\];(),:]/}},function(e,t){!function(e){e.languages.php=e.languages.extend(\"clike\",{keyword:/\\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\\b/i,constant:/\\b[A-Z0-9_]{2,}\\b/,comment:{pattern:/(^|[^\\\\])(?:\\/\\*[\\s\\S]*?\\*\\/|\\/\\/.*)/,lookbehind:!0}}),e.languages.insertBefore(\"php\",\"string\",{\"shell-comment\":{pattern:/(^|[^\\\\])#.*/,lookbehind:!0,alias:\"comment\"}}),e.languages.insertBefore(\"php\",\"keyword\",{delimiter:{pattern:/\\?>|<\\?(?:php|=)?/i,alias:\"important\"},variable:/\\$+(?:\\w+\\b|(?={))/i,package:{pattern:/(\\\\|namespace\\s+|use\\s+)[\\w\\\\]+/,lookbehind:!0,inside:{punctuation:/\\\\/}}}),e.languages.insertBefore(\"php\",\"operator\",{property:{pattern:/(->)[\\w]+/,lookbehind:!0}}),e.languages.insertBefore(\"php\",\"string\",{\"nowdoc-string\":{pattern:/<<<'([^']+)'(?:\\r\\n?|\\n)(?:.*(?:\\r\\n?|\\n))*?\\1;/,greedy:!0,alias:\"string\",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\\w*;$/i,alias:\"symbol\",inside:{punctuation:/^<<<'?|[';]$/}}}},\"heredoc-string\":{pattern:/<<<(?:\"([^\"]+)\"(?:\\r\\n?|\\n)(?:.*(?:\\r\\n?|\\n))*?\\1;|([a-z_]\\w*)(?:\\r\\n?|\\n)(?:.*(?:\\r\\n?|\\n))*?\\2;)/i,greedy:!0,alias:\"string\",inside:{delimiter:{pattern:/^<<<(?:\"[^\"]+\"|[a-z_]\\w*)|[a-z_]\\w*;$/i,alias:\"symbol\",inside:{punctuation:/^<<<\"?|[\";]$/}},interpolation:null}},\"single-quoted-string\":{pattern:/'(?:\\\\[\\s\\S]|[^\\\\'])*'/,greedy:!0,alias:\"string\"},\"double-quoted-string\":{pattern:/\"(?:\\\\[\\s\\S]|[^\\\\\"])*\"/,greedy:!0,alias:\"string\",inside:{interpolation:null}}}),delete e.languages.php.string;var t={pattern:/{\\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\\\{])\\$+(?:\\w+(?:\\[.+?]|->\\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.php[\"heredoc-string\"].inside.interpolation=t,e.languages.php[\"double-quoted-string\"].inside.interpolation=t,e.hooks.add(\"before-tokenize\",function(t){if(/(?:<\\?php|<\\?)/gi.test(t.code)){e.languages[\"markup-templating\"].buildPlaceholders(t,\"php\",/(?:<\\?php|<\\?)[\\s\\S]*?(?:\\?>|$)/gi)}}),e.hooks.add(\"after-tokenize\",function(t){e.languages[\"markup-templating\"].tokenizePlaceholders(t,\"php\")})}(Prism)},function(e,t){Prism.languages.python={comment:{pattern:/(^|[^\\\\])#.*/,lookbehind:!0},\"triple-quoted-string\":{pattern:/(\"\"\"|''')[\\s\\S]+?\\1/,greedy:!0,alias:\"string\"},string:{pattern:/(\"|')(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0},function:{pattern:/((?:^|\\s)def[ \\t]+)[a-zA-Z_]\\w*(?=\\s*\\()/g,lookbehind:!0},\"class-name\":{pattern:/(\\bclass\\s+)\\w+/i,lookbehind:!0},keyword:/\\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|pass|print|raise|return|try|while|with|yield)\\b/,builtin:/\\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\\b/,boolean:/\\b(?:True|False|None)\\b/,number:/(?:\\b(?=\\d)|\\B(?=\\.))(?:0[bo])?(?:(?:\\d|0x[\\da-f])[\\da-f]*\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?j?\\b/i,operator:/[-+%=]=?|!=|\\*\\*?=?|\\/\\/?=?|<[<=>]?|>[=>]?|[&|^~]|\\b(?:or|and|not)\\b/,punctuation:/[{}[\\];(),.:]/}},function(e,t){!function(e){e.languages.ruby=e.languages.extend(\"clike\",{comment:[/#.*/,{pattern:/^=begin(?:\\r?\\n|\\r)(?:.*(?:\\r?\\n|\\r))*?=end/m,greedy:!0}],keyword:/\\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\\b/});var t={pattern:/#\\{[^}]+\\}/,inside:{delimiter:{pattern:/^#\\{|\\}$/,alias:\"tag\"},rest:e.languages.ruby}};e.languages.insertBefore(\"ruby\",\"keyword\",{regex:[{pattern:/%r([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[\\s\\S])*\\}[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\\[(?:[^\\[\\]\\\\]|\\\\[\\s\\S])*\\][gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r<(?:[^<>\\\\]|\\\\[\\s\\S])*>[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/(^|[^\\/])\\/(?!\\/)(\\[.+?]|\\\\.|[^\\/\\\\\\r\\n])+\\/[gim]{0,3}(?=\\s*($|[\\r\\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_]\\w*(?:[?!]|\\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\\w*(?:[?!]|\\b)/,lookbehind:!0}}),e.languages.insertBefore(\"ruby\",\"number\",{builtin:/\\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\\b/,constant:/\\b[A-Z]\\w*(?:[?!]|\\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[\\s\\S])*\\1/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\\((?:[^()\\\\]|\\\\[\\s\\S])*\\)/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[\\s\\S])*\\}/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\\[(?:[^\\[\\]\\\\]|\\\\[\\s\\S])*\\]/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?<(?:[^<>\\\\]|\\\\[\\s\\S])*>/,greedy:!0,inside:{interpolation:t}},{pattern:/(\"|')(?:#\\{[^}]+\\}|\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0,inside:{interpolation:t}}]}(Prism)},function(e,t){Prism.languages.scala=Prism.languages.extend(\"java\",{keyword:/<-|=>|\\b(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|null|object|override|package|private|protected|return|sealed|self|super|this|throw|trait|try|type|val|var|while|with|yield)\\b/,string:[{pattern:/\"\"\"[\\s\\S]*?\"\"\"/,greedy:!0},{pattern:/(\"|')(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0}],builtin:/\\b(?:String|Int|Long|Short|Byte|Boolean|Double|Float|Char|Any|AnyRef|AnyVal|Unit|Nothing)\\b/,number:/\\b0x[\\da-f]*\\.?[\\da-f]+|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e\\d+)?[dfl]?/i,symbol:/'[^\\d\\s\\\\]\\w*/}),delete Prism.languages.scala[\"class-name\"],delete Prism.languages.scala.function},function(e,t){Prism.languages.sql={comment:{pattern:/(^|[^\\\\])(?:\\/\\*[\\s\\S]*?\\*\\/|(?:--|\\/\\/|#).*)/,lookbehind:!0},string:{pattern:/(^|[^@\\\\])(\"|')(?:\\\\[\\s\\S]|(?!\\2)[^\\\\])*\\2/,greedy:!0,lookbehind:!0},variable:/@[\\w.$]+|@([\"'`])(?:\\\\[\\s\\S]|(?!\\1)[^\\\\])+\\1/,function:/\\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\\s*\\()/i,keyword:/\\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\\b/i,boolean:/\\b(?:TRUE|FALSE|NULL)\\b/i,number:/\\b0x[\\da-f]+\\b|\\b\\d+\\.?\\d*|\\B\\.\\d+\\b/i,operator:/[-+*\\/=%^~]|&&?|\\|\\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\\b/i,punctuation:/[;[\\]()`,.]/}},function(e,t){Prism.languages.swift=Prism.languages.extend(\"clike\",{string:{pattern:/(\"|')(\\\\(?:\\((?:[^()]|\\([^)]+\\))+\\)|\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/,greedy:!0,inside:{interpolation:{pattern:/\\\\\\((?:[^()]|\\([^)]+\\))+\\)/,inside:{delimiter:{pattern:/^\\\\\\(|\\)$/,alias:\"variable\"}}}}},keyword:/\\b(?:as|associativity|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic(?:Type)?|else|enum|extension|fallthrough|final|for|func|get|guard|if|import|in|infix|init|inout|internal|is|lazy|left|let|mutating|new|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|Self|set|static|struct|subscript|super|switch|throws?|try|Type|typealias|unowned|unsafe|var|weak|where|while|willSet|__(?:COLUMN__|FILE__|FUNCTION__|LINE__))\\b/,number:/\\b(?:[\\d_]+(?:\\.[\\de_]+)?|0x[a-f0-9_]+(?:\\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b/i,constant:/\\b(?:nil|[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\\b/,atrule:/@\\b(?:IB(?:Outlet|Designable|Action|Inspectable)|class_protocol|exported|noreturn|NS(?:Copying|Managed)|objc|UIApplicationMain|auto_closure)\\b/,builtin:/\\b(?:[A-Z]\\S+|abs|advance|alignof(?:Value)?|assert|contains|count(?:Elements)?|debugPrint(?:ln)?|distance|drop(?:First|Last)|dump|enumerate|equal|filter|find|first|getVaList|indices|isEmpty|join|last|lexicographicalCompare|map|max(?:Element)?|min(?:Element)?|numericCast|overlaps|partition|print(?:ln)?|reduce|reflect|reverse|sizeof(?:Value)?|sort(?:ed)?|split|startsWith|stride(?:of(?:Value)?)?|suffix|swap|toDebugString|toString|transcode|underestimateCount|unsafeBitCast|with(?:ExtendedLifetime|Unsafe(?:MutablePointers?|Pointers?)|VaList))\\b/}),Prism.languages.swift.string.inside.interpolation.inside.rest=Prism.languages.swift},function(e,t,n){var r=n(267),o=[\"add\",\"done\",\"toJS\",\"load\",\"search\"];e.exports=function(){var e=new Worker(URL.createObjectURL(new Blob(['/*!\\n * ReDoc - OpenAPI/Swagger-generated API Reference Documentation\\n * -------------------------------------------------------------\\n *   Version: \"2.0.0-rc.1\"\\n *   Repo: https://github.com/Rebilly/ReDoc\\n */!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\"object\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\"default\",{enumerable:!0,value:e}),2&t&&\"string\"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\"a\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\"\",r(r.s=69)}([function(e,t,r){var n=r(24)(\"wks\"),i=r(17),o=r(1).Symbol,s=\"function\"==typeof o;(e.exports=function(e){return n[e]||(n[e]=s&&o[e]||(s?o:i)(\"Symbol.\"+e))}).store=n},function(e,t){var r=e.exports=\"undefined\"!=typeof window&&window.Math==Math?window:\"undefined\"!=typeof self&&self.Math==Math?self:Function(\"return this\")();\"number\"==typeof __g&&(__g=r)},function(e,t,r){var n,i;\\n/**\\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.5\\n * Copyright (C) 2018 Oliver Nightingale\\n * @license MIT\\n */!function(){var o,s,u,a,c,l,f,h,d,p,y,v,m,g,x,w,S,b,k,P,Q,E,L,_,T,O,j=function(e){var t=new j.Builder;return t.pipeline.add(j.trimmer,j.stopWordFilter,j.stemmer),t.searchPipeline.add(j.stemmer),e.call(t,t),t.build()};j.version=\"2.3.5\"\\n/*!\\n * lunr.utils\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.utils={},j.utils.warn=(o=this,function(e){o.console&&console.warn&&console.warn(e)}),j.utils.asString=function(e){return null==e?\"\":e.toString()},j.utils.clone=function(e){if(null==e)return e;for(var t=Object.create(null),r=Object.keys(e),n=0;n<r.length;n++){var i=r[n],o=e[i];if(Array.isArray(o))t[i]=o.slice();else{if(\"string\"!=typeof o&&\"number\"!=typeof o&&\"boolean\"!=typeof o)throw new TypeError(\"clone is not deep and does not support nested objects\");t[i]=o}}return t},j.FieldRef=function(e,t,r){this.docRef=e,this.fieldName=t,this._stringValue=r},j.FieldRef.joiner=\"/\",j.FieldRef.fromString=function(e){var t=e.indexOf(j.FieldRef.joiner);if(-1===t)throw\"malformed field ref string\";var r=e.slice(0,t),n=e.slice(t+1);return new j.FieldRef(n,r,e)},j.FieldRef.prototype.toString=function(){return null==this._stringValue&&(this._stringValue=this.fieldName+j.FieldRef.joiner+this.docRef),this._stringValue}\\n/*!\\n * lunr.Set\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.Set=function(e){if(this.elements=Object.create(null),e){this.length=e.length;for(var t=0;t<this.length;t++)this.elements[e[t]]=!0}else this.length=0},j.Set.complete={intersect:function(e){return e},union:function(e){return e},contains:function(){return!0}},j.Set.empty={intersect:function(){return this},union:function(e){return e},contains:function(){return!1}},j.Set.prototype.contains=function(e){return!!this.elements[e]},j.Set.prototype.intersect=function(e){var t,r,n,i=[];if(e===j.Set.complete)return this;if(e===j.Set.empty)return e;this.length<e.length?(t=this,r=e):(t=e,r=this),n=Object.keys(t.elements);for(var o=0;o<n.length;o++){var s=n[o];s in r.elements&&i.push(s)}return new j.Set(i)},j.Set.prototype.union=function(e){return e===j.Set.complete?j.Set.complete:e===j.Set.empty?this:new j.Set(Object.keys(this.elements).concat(Object.keys(e.elements)))},j.idf=function(e,t){var r=0;for(var n in e)\"_index\"!=n&&(r+=Object.keys(e[n]).length);var i=(t-r+.5)/(r+.5);return Math.log(1+Math.abs(i))},j.Token=function(e,t){this.str=e||\"\",this.metadata=t||{}},j.Token.prototype.toString=function(){return this.str},j.Token.prototype.update=function(e){return this.str=e(this.str,this.metadata),this},j.Token.prototype.clone=function(e){return e=e||function(e){return e},new j.Token(e(this.str,this.metadata),this.metadata)}\\n/*!\\n * lunr.tokenizer\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.tokenizer=function(e,t){if(null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return new j.Token(j.utils.asString(e).toLowerCase(),j.utils.clone(t))});for(var r=e.toString().trim().toLowerCase(),n=r.length,i=[],o=0,s=0;o<=n;o++){var u=o-s;if(r.charAt(o).match(j.tokenizer.separator)||o==n){if(u>0){var a=j.utils.clone(t)||{};a.position=[s,u],a.index=i.length,i.push(new j.Token(r.slice(s,o),a))}s=o+1}}return i},j.tokenizer.separator=/[\\\\s\\\\-]+/\\n/*!\\n * lunr.Pipeline\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.Pipeline=function(){this._stack=[]},j.Pipeline.registeredFunctions=Object.create(null),j.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&j.utils.warn(\"Overwriting existing registered function: \"+t),e.label=t,j.Pipeline.registeredFunctions[e.label]=e},j.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||j.utils.warn(\"Function is not registered with pipeline. This may cause problems when serialising the index.\\\\n\",e)},j.Pipeline.load=function(e){var t=new j.Pipeline;return e.forEach(function(e){var r=j.Pipeline.registeredFunctions[e];if(!r)throw new Error(\"Cannot load unregistered function: \"+e);t.add(r)}),t},j.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){j.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},j.Pipeline.prototype.after=function(e,t){j.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error(\"Cannot find existingFn\");r+=1,this._stack.splice(r,0,t)},j.Pipeline.prototype.before=function(e,t){j.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error(\"Cannot find existingFn\");this._stack.splice(r,0,t)},j.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},j.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r<t;r++){for(var n=this._stack[r],i=[],o=0;o<e.length;o++){var s=n(e[o],o,e);if(void 0!==s&&\"\"!==s)if(Array.isArray(s))for(var u=0;u<s.length;u++)i.push(s[u]);else i.push(s)}e=i}return e},j.Pipeline.prototype.runString=function(e,t){var r=new j.Token(e,t);return this.run([r]).map(function(e){return e.toString()})},j.Pipeline.prototype.reset=function(){this._stack=[]},j.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return j.Pipeline.warnIfFunctionNotRegistered(e),e.label})}\\n/*!\\n * lunr.Vector\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.Vector=function(e){this._magnitude=0,this.elements=e||[]},j.Vector.prototype.positionForIndex=function(e){if(0==this.elements.length)return 0;for(var t=0,r=this.elements.length/2,n=r-t,i=Math.floor(n/2),o=this.elements[2*i];n>1&&(o<e&&(t=i),o>e&&(r=i),o!=e);)n=r-t,i=t+Math.floor(n/2),o=this.elements[2*i];return o==e?2*i:o>e?2*i:o<e?2*(i+1):void 0},j.Vector.prototype.insert=function(e,t){this.upsert(e,t,function(){throw\"duplicate index\"})},j.Vector.prototype.upsert=function(e,t,r){this._magnitude=0;var n=this.positionForIndex(e);this.elements[n]==e?this.elements[n+1]=r(this.elements[n+1],t):this.elements.splice(n,0,e,t)},j.Vector.prototype.magnitude=function(){if(this._magnitude)return this._magnitude;for(var e=0,t=this.elements.length,r=1;r<t;r+=2){var n=this.elements[r];e+=n*n}return this._magnitude=Math.sqrt(e)},j.Vector.prototype.dot=function(e){for(var t=0,r=this.elements,n=e.elements,i=r.length,o=n.length,s=0,u=0,a=0,c=0;a<i&&c<o;)(s=r[a])<(u=n[c])?a+=2:s>u?c+=2:s==u&&(t+=r[a+1]*n[c+1],a+=2,c+=2);return t},j.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},j.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t<this.elements.length;t+=2,r++)e[r]=this.elements[t];return e},j.Vector.prototype.toJSON=function(){return this.elements}\\n/*!\\n * lunr.stemmer\\n * Copyright (C) 2018 Oliver Nightingale\\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\\n */,j.stemmer=(s={ational:\"ate\",tional:\"tion\",enci:\"ence\",anci:\"ance\",izer:\"ize\",bli:\"ble\",alli:\"al\",entli:\"ent\",eli:\"e\",ousli:\"ous\",ization:\"ize\",ation:\"ate\",ator:\"ate\",alism:\"al\",iveness:\"ive\",fulness:\"ful\",ousness:\"ous\",aliti:\"al\",iviti:\"ive\",biliti:\"ble\",logi:\"log\"},u={icate:\"ic\",ative:\"\",alize:\"al\",iciti:\"ic\",ical:\"ic\",ful:\"\",ness:\"\"},a=\"[aeiouy]\",c=\"[^aeiou][^aeiouy]*\",l=new RegExp(\"^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*\"),f=new RegExp(\"^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*\"),h=new RegExp(\"^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*([aeiouy][aeiou]*)?$\"),d=new RegExp(\"^([^aeiou][^aeiouy]*)?[aeiouy]\"),p=/^(.+?)(ss|i)es$/,y=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,m=/^(.+?)(ed|ing)$/,g=/.$/,x=/(at|bl|iz)$/,w=new RegExp(\"([^aeiouylsz])\\\\\\\\1$\"),S=new RegExp(\"^\"+c+a+\"[^aeiouwxy]$\"),b=/^(.+?[^aeiou])y$/,k=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,P=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,Q=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,E=/^(.+?)(s|t)(ion)$/,L=/^(.+?)e$/,_=/ll$/,T=new RegExp(\"^\"+c+a+\"[^aeiouwxy]$\"),O=function(e){var t,r,n,i,o,a,c;if(e.length<3)return e;if(\"y\"==(n=e.substr(0,1))&&(e=n.toUpperCase()+e.substr(1)),o=y,(i=p).test(e)?e=e.replace(i,\"$1$2\"):o.test(e)&&(e=e.replace(o,\"$1$2\")),o=m,(i=v).test(e)){var O=i.exec(e);(i=l).test(O[1])&&(i=g,e=e.replace(i,\"\"))}else if(o.test(e)){t=(O=o.exec(e))[1],(o=d).test(t)&&(a=w,c=S,(o=x).test(e=t)?e+=\"e\":a.test(e)?(i=g,e=e.replace(i,\"\")):c.test(e)&&(e+=\"e\"))}if((i=b).test(e)&&(e=(t=(O=i.exec(e))[1])+\"i\"),(i=k).test(e)&&(t=(O=i.exec(e))[1],r=O[2],(i=l).test(t)&&(e=t+s[r])),(i=P).test(e)&&(t=(O=i.exec(e))[1],r=O[2],(i=l).test(t)&&(e=t+u[r])),o=E,(i=Q).test(e))t=(O=i.exec(e))[1],(i=f).test(t)&&(e=t);else if(o.test(e)){t=(O=o.exec(e))[1]+O[2],(o=f).test(t)&&(e=t)}return(i=L).test(e)&&(t=(O=i.exec(e))[1],o=h,a=T,((i=f).test(t)||o.test(t)&&!a.test(t))&&(e=t)),o=f,(i=_).test(e)&&o.test(e)&&(i=g,e=e.replace(i,\"\")),\"y\"==n&&(e=n.toLowerCase()+e.substr(1)),e},function(e){return e.update(O)}),j.Pipeline.registerFunction(j.stemmer,\"stemmer\")\\n/*!\\n * lunr.stopWordFilter\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.generateStopWordFilter=function(e){var t=e.reduce(function(e,t){return e[t]=t,e},{});return function(e){if(e&&t[e.toString()]!==e.toString())return e}},j.stopWordFilter=j.generateStopWordFilter([\"a\",\"able\",\"about\",\"across\",\"after\",\"all\",\"almost\",\"also\",\"am\",\"among\",\"an\",\"and\",\"any\",\"are\",\"as\",\"at\",\"be\",\"because\",\"been\",\"but\",\"by\",\"can\",\"cannot\",\"could\",\"dear\",\"did\",\"do\",\"does\",\"either\",\"else\",\"ever\",\"every\",\"for\",\"from\",\"get\",\"got\",\"had\",\"has\",\"have\",\"he\",\"her\",\"hers\",\"him\",\"his\",\"how\",\"however\",\"i\",\"if\",\"in\",\"into\",\"is\",\"it\",\"its\",\"just\",\"least\",\"let\",\"like\",\"likely\",\"may\",\"me\",\"might\",\"most\",\"must\",\"my\",\"neither\",\"no\",\"nor\",\"not\",\"of\",\"off\",\"often\",\"on\",\"only\",\"or\",\"other\",\"our\",\"own\",\"rather\",\"said\",\"say\",\"says\",\"she\",\"should\",\"since\",\"so\",\"some\",\"than\",\"that\",\"the\",\"their\",\"them\",\"then\",\"there\",\"these\",\"they\",\"this\",\"tis\",\"to\",\"too\",\"twas\",\"us\",\"wants\",\"was\",\"we\",\"were\",\"what\",\"when\",\"where\",\"which\",\"while\",\"who\",\"whom\",\"why\",\"will\",\"with\",\"would\",\"yet\",\"you\",\"your\"]),j.Pipeline.registerFunction(j.stopWordFilter,\"stopWordFilter\")\\n/*!\\n * lunr.trimmer\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.trimmer=function(e){return e.update(function(e){return e.replace(/^\\\\W+/,\"\").replace(/\\\\W+$/,\"\")})},j.Pipeline.registerFunction(j.trimmer,\"trimmer\")\\n/*!\\n * lunr.TokenSet\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.TokenSet=function(){this.final=!1,this.edges={},this.id=j.TokenSet._nextId,j.TokenSet._nextId+=1},j.TokenSet._nextId=1,j.TokenSet.fromArray=function(e){for(var t=new j.TokenSet.Builder,r=0,n=e.length;r<n;r++)t.insert(e[r]);return t.finish(),t.root},j.TokenSet.fromClause=function(e){return\"editDistance\"in e?j.TokenSet.fromFuzzyString(e.term,e.editDistance):j.TokenSet.fromString(e.term)},j.TokenSet.fromFuzzyString=function(e,t){for(var r=new j.TokenSet,n=[{node:r,editsRemaining:t,str:e}];n.length;){var i,o,s,u=n.pop();if(u.str.length>0)(o=u.str.charAt(0))in u.node.edges?i=u.node.edges[o]:(i=new j.TokenSet,u.node.edges[o]=i),1==u.str.length&&(i.final=!0),n.push({node:i,editsRemaining:u.editsRemaining,str:u.str.slice(1)});if(u.editsRemaining>0&&u.str.length>1)(o=u.str.charAt(1))in u.node.edges?s=u.node.edges[o]:(s=new j.TokenSet,u.node.edges[o]=s),u.str.length<=2?s.final=!0:n.push({node:s,editsRemaining:u.editsRemaining-1,str:u.str.slice(2)});if(u.editsRemaining>0&&1==u.str.length&&(u.node.final=!0),u.editsRemaining>0&&u.str.length>=1){if(\"*\"in u.node.edges)var a=u.node.edges[\"*\"];else{a=new j.TokenSet;u.node.edges[\"*\"]=a}1==u.str.length?a.final=!0:n.push({node:a,editsRemaining:u.editsRemaining-1,str:u.str.slice(1)})}if(u.editsRemaining>0){if(\"*\"in u.node.edges)var c=u.node.edges[\"*\"];else{c=new j.TokenSet;u.node.edges[\"*\"]=c}0==u.str.length?c.final=!0:n.push({node:c,editsRemaining:u.editsRemaining-1,str:u.str})}if(u.editsRemaining>0&&u.str.length>1){var l,f=u.str.charAt(0),h=u.str.charAt(1);h in u.node.edges?l=u.node.edges[h]:(l=new j.TokenSet,u.node.edges[h]=l),1==u.str.length?l.final=!0:n.push({node:l,editsRemaining:u.editsRemaining-1,str:f+u.str.slice(2)})}}return r},j.TokenSet.fromString=function(e){for(var t=new j.TokenSet,r=t,n=0,i=e.length;n<i;n++){var o=e[n],s=n==i-1;if(\"*\"==o)t.edges[o]=t,t.final=s;else{var u=new j.TokenSet;u.final=s,t.edges[o]=u,t=u}}return r},j.TokenSet.prototype.toArray=function(){for(var e=[],t=[{prefix:\"\",node:this}];t.length;){var r=t.pop(),n=Object.keys(r.node.edges),i=n.length;r.node.final&&(r.prefix.charAt(0),e.push(r.prefix));for(var o=0;o<i;o++){var s=n[o];t.push({prefix:r.prefix.concat(s),node:r.node.edges[s]})}}return e},j.TokenSet.prototype.toString=function(){if(this._str)return this._str;for(var e=this.final?\"1\":\"0\",t=Object.keys(this.edges).sort(),r=t.length,n=0;n<r;n++){var i=t[n];e=e+i+this.edges[i].id}return e},j.TokenSet.prototype.intersect=function(e){for(var t=new j.TokenSet,r=void 0,n=[{qNode:e,output:t,node:this}];n.length;){r=n.pop();for(var i=Object.keys(r.qNode.edges),o=i.length,s=Object.keys(r.node.edges),u=s.length,a=0;a<o;a++)for(var c=i[a],l=0;l<u;l++){var f=s[l];if(f==c||\"*\"==c){var h=r.node.edges[f],d=r.qNode.edges[c],p=h.final&&d.final,y=void 0;f in r.output.edges?(y=r.output.edges[f]).final=y.final||p:((y=new j.TokenSet).final=p,r.output.edges[f]=y),n.push({qNode:d,output:y,node:h})}}}return t},j.TokenSet.Builder=function(){this.previousWord=\"\",this.root=new j.TokenSet,this.uncheckedNodes=[],this.minimizedNodes={}},j.TokenSet.Builder.prototype.insert=function(e){var t,r=0;if(e<this.previousWord)throw new Error(\"Out of order word insertion\");for(var n=0;n<e.length&&n<this.previousWord.length&&e[n]==this.previousWord[n];n++)r++;this.minimize(r),t=0==this.uncheckedNodes.length?this.root:this.uncheckedNodes[this.uncheckedNodes.length-1].child;for(n=r;n<e.length;n++){var i=new j.TokenSet,o=e[n];t.edges[o]=i,this.uncheckedNodes.push({parent:t,char:o,child:i}),t=i}t.final=!0,this.previousWord=e},j.TokenSet.Builder.prototype.finish=function(){this.minimize(0)},j.TokenSet.Builder.prototype.minimize=function(e){for(var t=this.uncheckedNodes.length-1;t>=e;t--){var r=this.uncheckedNodes[t],n=r.child.toString();n in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[n]:(r.child._str=n,this.minimizedNodes[n]=r.child),this.uncheckedNodes.pop()}}\\n/*!\\n * lunr.Index\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},j.Index.prototype.search=function(e){return this.query(function(t){new j.QueryParser(e,t).parse()})},j.Index.prototype.query=function(e){for(var t=new j.Query(this.fields),r=Object.create(null),n=Object.create(null),i=Object.create(null),o=Object.create(null),s=Object.create(null),u=0;u<this.fields.length;u++)n[this.fields[u]]=new j.Vector;e.call(t,t);for(u=0;u<t.clauses.length;u++){var a=t.clauses[u],c=null,l=j.Set.complete;c=a.usePipeline?this.pipeline.runString(a.term,{fields:a.fields}):[a.term];for(var f=0;f<c.length;f++){var h=c[f];a.term=h;var d=j.TokenSet.fromClause(a),p=this.tokenSet.intersect(d).toArray();if(0===p.length&&a.presence===j.Query.presence.REQUIRED){for(var y=0;y<a.fields.length;y++){o[R=a.fields[y]]=j.Set.empty}break}for(var v=0;v<p.length;v++){var m=p[v],g=this.invertedIndex[m],x=g._index;for(y=0;y<a.fields.length;y++){var w=g[R=a.fields[y]],S=Object.keys(w),b=m+\"/\"+R,k=new j.Set(S);if(a.presence==j.Query.presence.REQUIRED&&(l=l.union(k),void 0===o[R]&&(o[R]=j.Set.complete)),a.presence!=j.Query.presence.PROHIBITED){if(n[R].upsert(x,a.boost,function(e,t){return e+t}),!i[b]){for(var P=0;P<S.length;P++){var Q,E=S[P],L=new j.FieldRef(E,R),_=w[E];void 0===(Q=r[L])?r[L]=new j.MatchData(m,R,_):Q.add(m,R,_)}i[b]=!0}}else void 0===s[R]&&(s[R]=j.Set.empty),s[R]=s[R].union(k)}}}if(a.presence===j.Query.presence.REQUIRED)for(y=0;y<a.fields.length;y++){o[R=a.fields[y]]=o[R].intersect(l)}}var T=j.Set.complete,O=j.Set.empty;for(u=0;u<this.fields.length;u++){var R;o[R=this.fields[u]]&&(T=T.intersect(o[R])),s[R]&&(O=O.union(s[R]))}var I=Object.keys(r),F=[],C=Object.create(null);if(t.isNegated()){I=Object.keys(this.fieldVectors);for(u=0;u<I.length;u++){L=I[u];var N=j.FieldRef.fromString(L);r[L]=new j.MatchData}}for(u=0;u<I.length;u++){var A=(N=j.FieldRef.fromString(I[u])).docRef;if(T.contains(A)&&!O.contains(A)){var D,M=this.fieldVectors[N],B=n[N.fieldName].similarity(M);if(void 0!==(D=C[A]))D.score+=B,D.matchData.combine(r[N]);else{var V={ref:A,score:B,matchData:r[N]};C[A]=V,F.push(V)}}}return F.sort(function(e,t){return t.score-e.score})},j.Index.prototype.toJSON=function(){var e=Object.keys(this.invertedIndex).sort().map(function(e){return[e,this.invertedIndex[e]]},this),t=Object.keys(this.fieldVectors).map(function(e){return[e,this.fieldVectors[e].toJSON()]},this);return{version:j.version,fields:this.fields,fieldVectors:t,invertedIndex:e,pipeline:this.pipeline.toJSON()}},j.Index.load=function(e){var t={},r={},n=e.fieldVectors,i=Object.create(null),o=e.invertedIndex,s=new j.TokenSet.Builder,u=j.Pipeline.load(e.pipeline);e.version!=j.version&&j.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr \\'\"+j.version+\"\\' does not match serialized index \\'\"+e.version+\"\\'\");for(var a=0;a<n.length;a++){var c=(f=n[a])[0],l=f[1];r[c]=new j.Vector(l)}for(a=0;a<o.length;a++){var f,h=(f=o[a])[0],d=f[1];s.insert(h),i[h]=d}return s.finish(),t.fields=e.fields,t.fieldVectors=r,t.invertedIndex=i,t.tokenSet=s.root,t.pipeline=u,new j.Index(t)}\\n/*!\\n * lunr.Builder\\n * Copyright (C) 2018 Oliver Nightingale\\n */,j.Builder=function(){this._ref=\"id\",this._fields=Object.create(null),this._documents=Object.create(null),this.invertedIndex=Object.create(null),this.fieldTermFrequencies={},this.fieldLengths={},this.tokenizer=j.tokenizer,this.pipeline=new j.Pipeline,this.searchPipeline=new j.Pipeline,this.documentCount=0,this._b=.75,this._k1=1.2,this.termIndex=0,this.metadataWhitelist=[]},j.Builder.prototype.ref=function(e){this._ref=e},j.Builder.prototype.field=function(e,t){if(/\\\\//.test(e))throw new RangeError(\"Field \\'\"+e+\"\\' contains illegal character \\'/\\'\");this._fields[e]=t||{}},j.Builder.prototype.b=function(e){this._b=e<0?0:e>1?1:e},j.Builder.prototype.k1=function(e){this._k1=e},j.Builder.prototype.add=function(e,t){var r=e[this._ref],n=Object.keys(this._fields);this._documents[r]=t||{},this.documentCount+=1;for(var i=0;i<n.length;i++){var o=n[i],s=this._fields[o].extractor,u=s?s(e):e[o],a=this.tokenizer(u,{fields:[o]}),c=this.pipeline.run(a),l=new j.FieldRef(r,o),f=Object.create(null);this.fieldTermFrequencies[l]=f,this.fieldLengths[l]=0,this.fieldLengths[l]+=c.length;for(var h=0;h<c.length;h++){var d=c[h];if(null==f[d]&&(f[d]=0),f[d]+=1,null==this.invertedIndex[d]){var p=Object.create(null);p._index=this.termIndex,this.termIndex+=1;for(var y=0;y<n.length;y++)p[n[y]]=Object.create(null);this.invertedIndex[d]=p}null==this.invertedIndex[d][o][r]&&(this.invertedIndex[d][o][r]=Object.create(null));for(var v=0;v<this.metadataWhitelist.length;v++){var m=this.metadataWhitelist[v],g=d.metadata[m];null==this.invertedIndex[d][o][r][m]&&(this.invertedIndex[d][o][r][m]=[]),this.invertedIndex[d][o][r][m].push(g)}}}},j.Builder.prototype.calculateAverageFieldLengths=function(){for(var e=Object.keys(this.fieldLengths),t=e.length,r={},n={},i=0;i<t;i++){var o=j.FieldRef.fromString(e[i]),s=o.fieldName;n[s]||(n[s]=0),n[s]+=1,r[s]||(r[s]=0),r[s]+=this.fieldLengths[o]}var u=Object.keys(this._fields);for(i=0;i<u.length;i++){var a=u[i];r[a]=r[a]/n[a]}this.averageFieldLength=r},j.Builder.prototype.createFieldVectors=function(){for(var e={},t=Object.keys(this.fieldTermFrequencies),r=t.length,n=Object.create(null),i=0;i<r;i++){for(var o=j.FieldRef.fromString(t[i]),s=o.fieldName,u=this.fieldLengths[o],a=new j.Vector,c=this.fieldTermFrequencies[o],l=Object.keys(c),f=l.length,h=this._fields[s].boost||1,d=this._documents[o.docRef].boost||1,p=0;p<f;p++){var y,v,m,g=l[p],x=c[g],w=this.invertedIndex[g]._index;void 0===n[g]?(y=j.idf(this.invertedIndex[g],this.documentCount),n[g]=y):y=n[g],v=y*((this._k1+1)*x)/(this._k1*(1-this._b+this._b*(u/this.averageFieldLength[s]))+x),v*=h,v*=d,m=Math.round(1e3*v)/1e3,a.insert(w,m)}e[o]=a}this.fieldVectors=e},j.Builder.prototype.createTokenSet=function(){this.tokenSet=j.TokenSet.fromArray(Object.keys(this.invertedIndex).sort())},j.Builder.prototype.build=function(){return this.calculateAverageFieldLengths(),this.createFieldVectors(),this.createTokenSet(),new j.Index({invertedIndex:this.invertedIndex,fieldVectors:this.fieldVectors,tokenSet:this.tokenSet,fields:Object.keys(this._fields),pipeline:this.searchPipeline})},j.Builder.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},j.MatchData=function(e,t,r){for(var n=Object.create(null),i=Object.keys(r||{}),o=0;o<i.length;o++){var s=i[o];n[s]=r[s].slice()}this.metadata=Object.create(null),void 0!==e&&(this.metadata[e]=Object.create(null),this.metadata[e][t]=n)},j.MatchData.prototype.combine=function(e){for(var t=Object.keys(e.metadata),r=0;r<t.length;r++){var n=t[r],i=Object.keys(e.metadata[n]);null==this.metadata[n]&&(this.metadata[n]=Object.create(null));for(var o=0;o<i.length;o++){var s=i[o],u=Object.keys(e.metadata[n][s]);null==this.metadata[n][s]&&(this.metadata[n][s]=Object.create(null));for(var a=0;a<u.length;a++){var c=u[a];null==this.metadata[n][s][c]?this.metadata[n][s][c]=e.metadata[n][s][c]:this.metadata[n][s][c]=this.metadata[n][s][c].concat(e.metadata[n][s][c])}}}},j.MatchData.prototype.add=function(e,t,r){if(!(e in this.metadata))return this.metadata[e]=Object.create(null),void(this.metadata[e][t]=r);if(t in this.metadata[e])for(var n=Object.keys(r),i=0;i<n.length;i++){var o=n[i];o in this.metadata[e][t]?this.metadata[e][t][o]=this.metadata[e][t][o].concat(r[o]):this.metadata[e][t][o]=r[o]}else this.metadata[e][t]=r},j.Query=function(e){this.clauses=[],this.allFields=e},j.Query.wildcard=new String(\"*\"),j.Query.wildcard.NONE=0,j.Query.wildcard.LEADING=1,j.Query.wildcard.TRAILING=2,j.Query.presence={OPTIONAL:1,REQUIRED:2,PROHIBITED:3},j.Query.prototype.clause=function(e){return\"fields\"in e||(e.fields=this.allFields),\"boost\"in e||(e.boost=1),\"usePipeline\"in e||(e.usePipeline=!0),\"wildcard\"in e||(e.wildcard=j.Query.wildcard.NONE),e.wildcard&j.Query.wildcard.LEADING&&e.term.charAt(0)!=j.Query.wildcard&&(e.term=\"*\"+e.term),e.wildcard&j.Query.wildcard.TRAILING&&e.term.slice(-1)!=j.Query.wildcard&&(e.term=e.term+\"*\"),\"presence\"in e||(e.presence=j.Query.presence.OPTIONAL),this.clauses.push(e),this},j.Query.prototype.isNegated=function(){for(var e=0;e<this.clauses.length;e++)if(this.clauses[e].presence!=j.Query.presence.PROHIBITED)return!1;return!0},j.Query.prototype.term=function(e,t){if(Array.isArray(e))return e.forEach(function(e){this.term(e,j.utils.clone(t))},this),this;var r=t||{};return r.term=e.toString(),this.clause(r),this},j.QueryParseError=function(e,t,r){this.name=\"QueryParseError\",this.message=e,this.start=t,this.end=r},j.QueryParseError.prototype=new Error,j.QueryLexer=function(e){this.lexemes=[],this.str=e,this.length=e.length,this.pos=0,this.start=0,this.escapeCharPositions=[]},j.QueryLexer.prototype.run=function(){for(var e=j.QueryLexer.lexText;e;)e=e(this)},j.QueryLexer.prototype.sliceString=function(){for(var e=[],t=this.start,r=this.pos,n=0;n<this.escapeCharPositions.length;n++)r=this.escapeCharPositions[n],e.push(this.str.slice(t,r)),t=r+1;return e.push(this.str.slice(t,this.pos)),this.escapeCharPositions.length=0,e.join(\"\")},j.QueryLexer.prototype.emit=function(e){this.lexemes.push({type:e,str:this.sliceString(),start:this.start,end:this.pos}),this.start=this.pos},j.QueryLexer.prototype.escapeCharacter=function(){this.escapeCharPositions.push(this.pos-1),this.pos+=1},j.QueryLexer.prototype.next=function(){if(this.pos>=this.length)return j.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},j.QueryLexer.prototype.width=function(){return this.pos-this.start},j.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},j.QueryLexer.prototype.backup=function(){this.pos-=1},j.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=j.QueryLexer.EOS&&this.backup()},j.QueryLexer.prototype.more=function(){return this.pos<this.length},j.QueryLexer.EOS=\"EOS\",j.QueryLexer.FIELD=\"FIELD\",j.QueryLexer.TERM=\"TERM\",j.QueryLexer.EDIT_DISTANCE=\"EDIT_DISTANCE\",j.QueryLexer.BOOST=\"BOOST\",j.QueryLexer.PRESENCE=\"PRESENCE\",j.QueryLexer.lexField=function(e){return e.backup(),e.emit(j.QueryLexer.FIELD),e.ignore(),j.QueryLexer.lexText},j.QueryLexer.lexTerm=function(e){if(e.width()>1&&(e.backup(),e.emit(j.QueryLexer.TERM)),e.ignore(),e.more())return j.QueryLexer.lexText},j.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(j.QueryLexer.EDIT_DISTANCE),j.QueryLexer.lexText},j.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(j.QueryLexer.BOOST),j.QueryLexer.lexText},j.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(j.QueryLexer.TERM)},j.QueryLexer.termSeparator=j.tokenizer.separator,j.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==j.QueryLexer.EOS)return j.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(\":\"==t)return j.QueryLexer.lexField;if(\"~\"==t)return e.backup(),e.width()>0&&e.emit(j.QueryLexer.TERM),j.QueryLexer.lexEditDistance;if(\"^\"==t)return e.backup(),e.width()>0&&e.emit(j.QueryLexer.TERM),j.QueryLexer.lexBoost;if(\"+\"==t&&1===e.width())return e.emit(j.QueryLexer.PRESENCE),j.QueryLexer.lexText;if(\"-\"==t&&1===e.width())return e.emit(j.QueryLexer.PRESENCE),j.QueryLexer.lexText;if(t.match(j.QueryLexer.termSeparator))return j.QueryLexer.lexTerm}else e.escapeCharacter()}},j.QueryParser=function(e,t){this.lexer=new j.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},j.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=j.QueryParser.parseClause;e;)e=e(this);return this.query},j.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},j.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},j.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},j.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case j.QueryLexer.PRESENCE:return j.QueryParser.parsePresence;case j.QueryLexer.FIELD:return j.QueryParser.parseField;case j.QueryLexer.TERM:return j.QueryParser.parseTerm;default:var r=\"expected either a field or a term, found \"+t.type;throw t.str.length>=1&&(r+=\" with value \\'\"+t.str+\"\\'\"),new j.QueryParseError(r,t.start,t.end)}},j.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case\"-\":e.currentClause.presence=j.Query.presence.PROHIBITED;break;case\"+\":e.currentClause.presence=j.Query.presence.REQUIRED;break;default:var r=\"unrecognised presence operator\\'\"+t.str+\"\\'\";throw new j.QueryParseError(r,t.start,t.end)}var n=e.peekLexeme();if(null==n){r=\"expecting term or field, found nothing\";throw new j.QueryParseError(r,t.start,t.end)}switch(n.type){case j.QueryLexer.FIELD:return j.QueryParser.parseField;case j.QueryLexer.TERM:return j.QueryParser.parseTerm;default:r=\"expecting term or field, found \\'\"+n.type+\"\\'\";throw new j.QueryParseError(r,n.start,n.end)}}},j.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var r=e.query.allFields.map(function(e){return\"\\'\"+e+\"\\'\"}).join(\", \"),n=\"unrecognised field \\'\"+t.str+\"\\', possible fields: \"+r;throw new j.QueryParseError(n,t.start,t.end)}e.currentClause.fields=[t.str];var i=e.peekLexeme();if(null==i){n=\"expecting term, found nothing\";throw new j.QueryParseError(n,t.start,t.end)}switch(i.type){case j.QueryLexer.TERM:return j.QueryParser.parseTerm;default:n=\"expecting term, found \\'\"+i.type+\"\\'\";throw new j.QueryParseError(n,i.start,i.end)}}},j.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf(\"*\")&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(null!=r)switch(r.type){case j.QueryLexer.TERM:return e.nextClause(),j.QueryParser.parseTerm;case j.QueryLexer.FIELD:return e.nextClause(),j.QueryParser.parseField;case j.QueryLexer.EDIT_DISTANCE:return j.QueryParser.parseEditDistance;case j.QueryLexer.BOOST:return j.QueryParser.parseBoost;case j.QueryLexer.PRESENCE:return e.nextClause(),j.QueryParser.parsePresence;default:var n=\"Unexpected lexeme type \\'\"+r.type+\"\\'\";throw new j.QueryParseError(n,r.start,r.end)}else e.nextClause()}},j.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n=\"edit distance must be numeric\";throw new j.QueryParseError(n,t.start,t.end)}e.currentClause.editDistance=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case j.QueryLexer.TERM:return e.nextClause(),j.QueryParser.parseTerm;case j.QueryLexer.FIELD:return e.nextClause(),j.QueryParser.parseField;case j.QueryLexer.EDIT_DISTANCE:return j.QueryParser.parseEditDistance;case j.QueryLexer.BOOST:return j.QueryParser.parseBoost;case j.QueryLexer.PRESENCE:return e.nextClause(),j.QueryParser.parsePresence;default:n=\"Unexpected lexeme type \\'\"+i.type+\"\\'\";throw new j.QueryParseError(n,i.start,i.end)}else e.nextClause()}},j.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n=\"boost must be numeric\";throw new j.QueryParseError(n,t.start,t.end)}e.currentClause.boost=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case j.QueryLexer.TERM:return e.nextClause(),j.QueryParser.parseTerm;case j.QueryLexer.FIELD:return e.nextClause(),j.QueryParser.parseField;case j.QueryLexer.EDIT_DISTANCE:return j.QueryParser.parseEditDistance;case j.QueryLexer.BOOST:return j.QueryParser.parseBoost;case j.QueryLexer.PRESENCE:return e.nextClause(),j.QueryParser.parsePresence;default:n=\"Unexpected lexeme type \\'\"+i.type+\"\\'\";throw new j.QueryParseError(n,i.start,i.end)}else e.nextClause()}},void 0===(i=\"function\"==typeof(n=function(){return j})?n.call(t,r,t,e):n)||(e.exports=i)}()},function(e,t,r){var n=r(7);e.exports=function(e){if(!n(e))throw TypeError(e+\" is not an object!\");return e}},function(e,t){var r=e.exports={version:\"2.5.7\"};\"number\"==typeof __e&&(__e=r)},function(e,t,r){var n=r(11),i=r(26);e.exports=r(8)?function(e,t,r){return n.f(e,t,i(1,r))}:function(e,t,r){return e[t]=r,e}},function(e,t,r){var n=r(1),i=r(5),o=r(12),s=r(17)(\"src\"),u=Function.toString,a=(\"\"+u).split(\"toString\");r(4).inspectSource=function(e){return u.call(e)},(e.exports=function(e,t,r,u){var c=\"function\"==typeof r;c&&(o(r,\"name\")||i(r,\"name\",t)),e[t]!==r&&(c&&(o(r,s)||i(r,s,e[t]?\"\"+e[t]:a.join(String(t)))),e===n?e[t]=r:u?e[t]?e[t]=r:i(e,t,r):(delete e[t],i(e,t,r)))})(Function.prototype,\"toString\",function(){return\"function\"==typeof this&&this[s]||u.call(this)})},function(e,t){e.exports=function(e){return\"object\"==typeof e?null!==e:\"function\"==typeof e}},function(e,t,r){e.exports=!r(25)(function(){return 7!=Object.defineProperty({},\"a\",{get:function(){return 7}}).a})},function(e,t){e.exports={}},function(e,t){var r={}.toString;e.exports=function(e){return r.call(e).slice(8,-1)}},function(e,t,r){var n=r(3),i=r(37),o=r(38),s=Object.defineProperty;t.f=r(8)?Object.defineProperty:function(e,t,r){if(n(e),t=o(t,!0),n(r),i)try{return s(e,t,r)}catch(e){}if(\"get\"in r||\"set\"in r)throw TypeError(\"Accessors not supported!\");return\"value\"in r&&(e[t]=r.value),e}},function(e,t){var r={}.hasOwnProperty;e.exports=function(e,t){return r.call(e,t)}},function(e,t,r){var n=r(14);e.exports=function(e,t,r){if(n(e),void 0===t)return e;switch(r){case 1:return function(r){return e.call(t,r)};case 2:return function(r,n){return e.call(t,r,n)};case 3:return function(r,n,i){return e.call(t,r,n,i)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if(\"function\"!=typeof e)throw TypeError(e+\" is not a function!\");return e}},function(e,t,r){var n=r(10),i=r(0)(\"toStringTag\"),o=\"Arguments\"==n(function(){return arguments}());e.exports=function(e){var t,r,s;return void 0===e?\"Undefined\":null===e?\"Null\":\"string\"==typeof(r=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),i))?r:o?n(t):\"Object\"==(s=n(t))&&\"function\"==typeof t.callee?\"Arguments\":s}},function(e,t){e.exports=!1},function(e,t){var r=0,n=Math.random();e.exports=function(e){return\"Symbol(\".concat(void 0===e?\"\":e,\")_\",(++r+n).toString(36))}},function(e,t,r){var n=r(7),i=r(1).document,o=n(i)&&n(i.createElement);e.exports=function(e){return o?i.createElement(e):{}}},function(e,t){var r=Math.ceil,n=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?n:r)(e)}},function(e,t){e.exports=function(e){if(null==e)throw TypeError(\"Can\\'t call method on  \"+e);return e}},function(e,t,r){var n=r(45),i=r(20);e.exports=function(e){return n(i(e))}},function(e,t,r){var n=r(24)(\"keys\"),i=r(17);e.exports=function(e){return n[e]||(n[e]=i(e))}},function(e,t,r){var n=r(11).f,i=r(12),o=r(0)(\"toStringTag\");e.exports=function(e,t,r){e&&!i(e=r?e:e.prototype,o)&&n(e,o,{configurable:!0,value:t})}},function(e,t,r){var n=r(4),i=r(1),o=i[\"__core-js_shared__\"]||(i[\"__core-js_shared__\"]={});(e.exports=function(e,t){return o[e]||(o[e]=void 0!==t?t:{})})(\"versions\",[]).push({version:n.version,mode:r(16)?\"pure\":\"global\",copyright:\"© 2018 Denis Pushkarev (zloirock.ru)\"})},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,r){\"use strict\";var n=r(16),i=r(28),o=r(6),s=r(5),u=r(9),a=r(41),c=r(23),l=r(48),f=r(0)(\"iterator\"),h=!([].keys&&\"next\"in[].keys()),d=function(){return this};e.exports=function(e,t,r,p,y,v,m){a(r,t,p);var g,x,w,S=function(e){if(!h&&e in Q)return Q[e];switch(e){case\"keys\":case\"values\":return function(){return new r(this,e)}}return function(){return new r(this,e)}},b=t+\" Iterator\",k=\"values\"==y,P=!1,Q=e.prototype,E=Q[f]||Q[\"@@iterator\"]||y&&Q[y],L=E||S(y),_=y?k?S(\"entries\"):L:void 0,T=\"Array\"==t&&Q.entries||E;if(T&&(w=l(T.call(new e)))!==Object.prototype&&w.next&&(c(w,b,!0),n||\"function\"==typeof w[f]||s(w,f,d)),k&&E&&\"values\"!==E.name&&(P=!0,L=function(){return E.call(this)}),n&&!m||!h&&!P&&Q[f]||s(Q,f,L),u[t]=L,u[b]=d,y)if(g={values:k?L:S(\"values\"),keys:v?L:S(\"keys\"),entries:_},m)for(x in g)x in Q||o(Q,x,g[x]);else i(i.P+i.F*(h||P),t,g);return g}},function(e,t,r){var n=r(1),i=r(4),o=r(5),s=r(6),u=r(13),a=function(e,t,r){var c,l,f,h,d=e&a.F,p=e&a.G,y=e&a.S,v=e&a.P,m=e&a.B,g=p?n:y?n[t]||(n[t]={}):(n[t]||{}).prototype,x=p?i:i[t]||(i[t]={}),w=x.prototype||(x.prototype={});for(c in p&&(r=t),r)f=((l=!d&&g&&void 0!==g[c])?g:r)[c],h=m&&l?u(f,n):v&&\"function\"==typeof f?u(Function.call,f):f,g&&s(g,c,f,e&a.U),x[c]!=f&&o(x,c,h),v&&w[c]!=f&&(w[c]=f)};n.core=i,a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,e.exports=a},function(e,t,r){var n=r(44),i=r(31);e.exports=Object.keys||function(e){return n(e,i)}},function(e,t,r){var n=r(19),i=Math.min;e.exports=function(e){return e>0?i(n(e),9007199254740991):0}},function(e,t){e.exports=\"constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf\".split(\",\")},function(e,t,r){var n=r(1).document;e.exports=n&&n.documentElement},function(e,t,r){var n,i,o,s=r(13),u=r(61),a=r(32),c=r(18),l=r(1),f=l.process,h=l.setImmediate,d=l.clearImmediate,p=l.MessageChannel,y=l.Dispatch,v=0,m={},g=function(){var e=+this;if(m.hasOwnProperty(e)){var t=m[e];delete m[e],t()}},x=function(e){g.call(e.data)};h&&d||(h=function(e){for(var t=[],r=1;arguments.length>r;)t.push(arguments[r++]);return m[++v]=function(){u(\"function\"==typeof e?e:Function(e),t)},n(v),v},d=function(e){delete m[e]},\"process\"==r(10)(f)?n=function(e){f.nextTick(s(g,e,1))}:y&&y.now?n=function(e){y.now(s(g,e,1))}:p?(o=(i=new p).port2,i.port1.onmessage=x,n=s(o.postMessage,o,1)):l.addEventListener&&\"function\"==typeof postMessage&&!l.importScripts?(n=function(e){l.postMessage(e+\"\",\"*\")},l.addEventListener(\"message\",x,!1)):n=\"onreadystatechange\"in c(\"script\")?function(e){a.appendChild(c(\"script\")).onreadystatechange=function(){a.removeChild(this),g.call(e)}}:function(e){setTimeout(s(g,e,1),0)}),e.exports={set:h,clear:d}},function(e,t,r){\"use strict\";var n=r(14);function i(e){var t,r;this.promise=new e(function(e,n){if(void 0!==t||void 0!==r)throw TypeError(\"Bad Promise constructor\");t=e,r=n}),this.resolve=n(t),this.reject=n(r)}e.exports.f=function(e){return new i(e)}},function(e,t,r){r(36),r(39),r(50),r(54),e.exports=r(4).Promise},function(e,t,r){\"use strict\";var n=r(15),i={};i[r(0)(\"toStringTag\")]=\"z\",i+\"\"!=\"[object z]\"&&r(6)(Object.prototype,\"toString\",function(){return\"[object \"+n(this)+\"]\"},!0)},function(e,t,r){e.exports=!r(8)&&!r(25)(function(){return 7!=Object.defineProperty(r(18)(\"div\"),\"a\",{get:function(){return 7}}).a})},function(e,t,r){var n=r(7);e.exports=function(e,t){if(!n(e))return e;var r,i;if(t&&\"function\"==typeof(r=e.toString)&&!n(i=r.call(e)))return i;if(\"function\"==typeof(r=e.valueOf)&&!n(i=r.call(e)))return i;if(!t&&\"function\"==typeof(r=e.toString)&&!n(i=r.call(e)))return i;throw TypeError(\"Can\\'t convert object to primitive value\")}},function(e,t,r){\"use strict\";var n=r(40)(!0);r(27)(String,\"String\",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,r=this._i;return r>=t.length?{value:void 0,done:!0}:(e=n(t,r),this._i+=e.length,{value:e,done:!1})})},function(e,t,r){var n=r(19),i=r(20);e.exports=function(e){return function(t,r){var o,s,u=String(i(t)),a=n(r),c=u.length;return a<0||a>=c?e?\"\":void 0:(o=u.charCodeAt(a))<55296||o>56319||a+1===c||(s=u.charCodeAt(a+1))<56320||s>57343?e?u.charAt(a):o:e?u.slice(a,a+2):s-56320+(o-55296<<10)+65536}}},function(e,t,r){\"use strict\";var n=r(42),i=r(26),o=r(23),s={};r(5)(s,r(0)(\"iterator\"),function(){return this}),e.exports=function(e,t,r){e.prototype=n(s,{next:i(1,r)}),o(e,t+\" Iterator\")}},function(e,t,r){var n=r(3),i=r(43),o=r(31),s=r(22)(\"IE_PROTO\"),u=function(){},a=function(){var e,t=r(18)(\"iframe\"),n=o.length;for(t.style.display=\"none\",r(32).appendChild(t),t.src=\"javascript:\",(e=t.contentWindow.document).open(),e.write(\"<script>document.F=Object<\\\\/script>\"),e.close(),a=e.F;n--;)delete a.prototype[o[n]];return a()};e.exports=Object.create||function(e,t){var r;return null!==e?(u.prototype=n(e),r=new u,u.prototype=null,r[s]=e):r=a(),void 0===t?r:i(r,t)}},function(e,t,r){var n=r(11),i=r(3),o=r(29);e.exports=r(8)?Object.defineProperties:function(e,t){i(e);for(var r,s=o(t),u=s.length,a=0;u>a;)n.f(e,r=s[a++],t[r]);return e}},function(e,t,r){var n=r(12),i=r(21),o=r(46)(!1),s=r(22)(\"IE_PROTO\");e.exports=function(e,t){var r,u=i(e),a=0,c=[];for(r in u)r!=s&&n(u,r)&&c.push(r);for(;t.length>a;)n(u,r=t[a++])&&(~o(c,r)||c.push(r));return c}},function(e,t,r){var n=r(10);e.exports=Object(\"z\").propertyIsEnumerable(0)?Object:function(e){return\"String\"==n(e)?e.split(\"\"):Object(e)}},function(e,t,r){var n=r(21),i=r(30),o=r(47);e.exports=function(e){return function(t,r,s){var u,a=n(t),c=i(a.length),l=o(s,c);if(e&&r!=r){for(;c>l;)if((u=a[l++])!=u)return!0}else for(;c>l;l++)if((e||l in a)&&a[l]===r)return e||l||0;return!e&&-1}}},function(e,t,r){var n=r(19),i=Math.max,o=Math.min;e.exports=function(e,t){return(e=n(e))<0?i(e+t,0):o(e,t)}},function(e,t,r){var n=r(12),i=r(49),o=r(22)(\"IE_PROTO\"),s=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=i(e),n(e,o)?e[o]:\"function\"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?s:null}},function(e,t,r){var n=r(20);e.exports=function(e){return Object(n(e))}},function(e,t,r){for(var n=r(51),i=r(29),o=r(6),s=r(1),u=r(5),a=r(9),c=r(0),l=c(\"iterator\"),f=c(\"toStringTag\"),h=a.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},p=i(d),y=0;y<p.length;y++){var v,m=p[y],g=d[m],x=s[m],w=x&&x.prototype;if(w&&(w[l]||u(w,l,h),w[f]||u(w,f,m),a[m]=h,g))for(v in n)w[v]||o(w,v,n[v],!0)}},function(e,t,r){\"use strict\";var n=r(52),i=r(53),o=r(9),s=r(21);e.exports=r(27)(Array,\"Array\",function(e,t){this._t=s(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,r=this._i++;return!e||r>=e.length?(this._t=void 0,i(1)):i(0,\"keys\"==t?r:\"values\"==t?e[r]:[r,e[r]])},\"values\"),o.Arguments=o.Array,n(\"keys\"),n(\"values\"),n(\"entries\")},function(e,t,r){var n=r(0)(\"unscopables\"),i=Array.prototype;null==i[n]&&r(5)(i,n,{}),e.exports=function(e){i[n][e]=!0}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,r){\"use strict\";var n,i,o,s,u=r(16),a=r(1),c=r(13),l=r(15),f=r(28),h=r(7),d=r(14),p=r(55),y=r(56),v=r(60),m=r(33).set,g=r(62)(),x=r(34),w=r(63),S=r(64),b=r(65),k=a.TypeError,P=a.process,Q=P&&P.versions,E=Q&&Q.v8||\"\",L=a.Promise,_=\"process\"==l(P),T=function(){},O=i=x.f,j=!!function(){try{var e=L.resolve(1),t=(e.constructor={})[r(0)(\"species\")]=function(e){e(T,T)};return(_||\"function\"==typeof PromiseRejectionEvent)&&e.then(T)instanceof t&&0!==E.indexOf(\"6.6\")&&-1===S.indexOf(\"Chrome/66\")}catch(e){}}(),R=function(e){var t;return!(!h(e)||\"function\"!=typeof(t=e.then))&&t},I=function(e,t){if(!e._n){e._n=!0;var r=e._c;g(function(){for(var n=e._v,i=1==e._s,o=0,s=function(t){var r,o,s,u=i?t.ok:t.fail,a=t.resolve,c=t.reject,l=t.domain;try{u?(i||(2==e._h&&N(e),e._h=1),!0===u?r=n:(l&&l.enter(),r=u(n),l&&(l.exit(),s=!0)),r===t.promise?c(k(\"Promise-chain cycle\")):(o=R(r))?o.call(r,a,c):a(r)):c(n)}catch(e){l&&!s&&l.exit(),c(e)}};r.length>o;)s(r[o++]);e._c=[],e._n=!1,t&&!e._h&&F(e)})}},F=function(e){m.call(a,function(){var t,r,n,i=e._v,o=C(e);if(o&&(t=w(function(){_?P.emit(\"unhandledRejection\",i,e):(r=a.onunhandledrejection)?r({promise:e,reason:i}):(n=a.console)&&n.error&&n.error(\"Unhandled promise rejection\",i)}),e._h=_||C(e)?2:1),e._a=void 0,o&&t.e)throw t.v})},C=function(e){return 1!==e._h&&0===(e._a||e._c).length},N=function(e){m.call(a,function(){var t;_?P.emit(\"rejectionHandled\",e):(t=a.onrejectionhandled)&&t({promise:e,reason:e._v})})},A=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),I(t,!0))},D=function(e){var t,r=this;if(!r._d){r._d=!0,r=r._w||r;try{if(r===e)throw k(\"Promise can\\'t be resolved itself\");(t=R(e))?g(function(){var n={_w:r,_d:!1};try{t.call(e,c(D,n,1),c(A,n,1))}catch(e){A.call(n,e)}}):(r._v=e,r._s=1,I(r,!1))}catch(e){A.call({_w:r,_d:!1},e)}}};j||(L=function(e){p(this,L,\"Promise\",\"_h\"),d(e),n.call(this);try{e(c(D,this,1),c(A,this,1))}catch(e){A.call(this,e)}},(n=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=r(66)(L.prototype,{then:function(e,t){var r=O(v(this,L));return r.ok=\"function\"!=typeof e||e,r.fail=\"function\"==typeof t&&t,r.domain=_?P.domain:void 0,this._c.push(r),this._a&&this._a.push(r),this._s&&I(this,!1),r.promise},catch:function(e){return this.then(void 0,e)}}),o=function(){var e=new n;this.promise=e,this.resolve=c(D,e,1),this.reject=c(A,e,1)},x.f=O=function(e){return e===L||e===s?new o(e):i(e)}),f(f.G+f.W+f.F*!j,{Promise:L}),r(23)(L,\"Promise\"),r(67)(\"Promise\"),s=r(4).Promise,f(f.S+f.F*!j,\"Promise\",{reject:function(e){var t=O(this);return(0,t.reject)(e),t.promise}}),f(f.S+f.F*(u||!j),\"Promise\",{resolve:function(e){return b(u&&this===s?L:this,e)}}),f(f.S+f.F*!(j&&r(68)(function(e){L.all(e).catch(T)})),\"Promise\",{all:function(e){var t=this,r=O(t),n=r.resolve,i=r.reject,o=w(function(){var r=[],o=0,s=1;y(e,!1,function(e){var u=o++,a=!1;r.push(void 0),s++,t.resolve(e).then(function(e){a||(a=!0,r[u]=e,--s||n(r))},i)}),--s||n(r)});return o.e&&i(o.v),r.promise},race:function(e){var t=this,r=O(t),n=r.reject,i=w(function(){y(e,!1,function(e){t.resolve(e).then(r.resolve,n)})});return i.e&&n(i.v),r.promise}})},function(e,t){e.exports=function(e,t,r,n){if(!(e instanceof t)||void 0!==n&&n in e)throw TypeError(r+\": incorrect invocation!\");return e}},function(e,t,r){var n=r(13),i=r(57),o=r(58),s=r(3),u=r(30),a=r(59),c={},l={};(t=e.exports=function(e,t,r,f,h){var d,p,y,v,m=h?function(){return e}:a(e),g=n(r,f,t?2:1),x=0;if(\"function\"!=typeof m)throw TypeError(e+\" is not iterable!\");if(o(m)){for(d=u(e.length);d>x;x++)if((v=t?g(s(p=e[x])[0],p[1]):g(e[x]))===c||v===l)return v}else for(y=m.call(e);!(p=y.next()).done;)if((v=i(y,g,p.value,t))===c||v===l)return v}).BREAK=c,t.RETURN=l},function(e,t,r){var n=r(3);e.exports=function(e,t,r,i){try{return i?t(n(r)[0],r[1]):t(r)}catch(t){var o=e.return;throw void 0!==o&&n(o.call(e)),t}}},function(e,t,r){var n=r(9),i=r(0)(\"iterator\"),o=Array.prototype;e.exports=function(e){return void 0!==e&&(n.Array===e||o[i]===e)}},function(e,t,r){var n=r(15),i=r(0)(\"iterator\"),o=r(9);e.exports=r(4).getIteratorMethod=function(e){if(null!=e)return e[i]||e[\"@@iterator\"]||o[n(e)]}},function(e,t,r){var n=r(3),i=r(14),o=r(0)(\"species\");e.exports=function(e,t){var r,s=n(e).constructor;return void 0===s||null==(r=n(s)[o])?t:i(r)}},function(e,t){e.exports=function(e,t,r){var n=void 0===r;switch(t.length){case 0:return n?e():e.call(r);case 1:return n?e(t[0]):e.call(r,t[0]);case 2:return n?e(t[0],t[1]):e.call(r,t[0],t[1]);case 3:return n?e(t[0],t[1],t[2]):e.call(r,t[0],t[1],t[2]);case 4:return n?e(t[0],t[1],t[2],t[3]):e.call(r,t[0],t[1],t[2],t[3])}return e.apply(r,t)}},function(e,t,r){var n=r(1),i=r(33).set,o=n.MutationObserver||n.WebKitMutationObserver,s=n.process,u=n.Promise,a=\"process\"==r(10)(s);e.exports=function(){var e,t,r,c=function(){var n,i;for(a&&(n=s.domain)&&n.exit();e;){i=e.fn,e=e.next;try{i()}catch(n){throw e?r():t=void 0,n}}t=void 0,n&&n.enter()};if(a)r=function(){s.nextTick(c)};else if(!o||n.navigator&&n.navigator.standalone)if(u&&u.resolve){var l=u.resolve(void 0);r=function(){l.then(c)}}else r=function(){i.call(n,c)};else{var f=!0,h=document.createTextNode(\"\");new o(c).observe(h,{characterData:!0}),r=function(){h.data=f=!f}}return function(n){var i={fn:n,next:void 0};t&&(t.next=i),e||(e=i,r()),t=i}}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,r){var n=r(1).navigator;e.exports=n&&n.userAgent||\"\"},function(e,t,r){var n=r(3),i=r(7),o=r(34);e.exports=function(e,t){if(n(e),i(t)&&t.constructor===e)return t;var r=o.f(e);return(0,r.resolve)(t),r.promise}},function(e,t,r){var n=r(6);e.exports=function(e,t,r){for(var i in t)n(e,i,t[i],r);return e}},function(e,t,r){\"use strict\";var n=r(1),i=r(11),o=r(8),s=r(0)(\"species\");e.exports=function(e){var t=n[e];o&&t&&!t[s]&&i.f(t,s,{configurable:!0,get:function(){return this}})}},function(e,t,r){var n=r(0)(\"iterator\"),i=!1;try{var o=[7][n]();o.return=function(){i=!0},Array.from(o,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!i)return!1;var r=!1;try{var o=[7],s=o[n]();s.next=function(){return{done:r=!0}},o[n]=function(){return s},e(o)}catch(e){}return r}},function(e,t,r){\"use strict\";r.r(t);function n(e,t,r,n){return new(r||(r=Promise))(function(i,o){function s(e){try{a(n.next(e))}catch(e){o(e)}}function u(e){try{a(n.throw(e))}catch(e){o(e)}}function a(e){e.done?i(e.value):new r(function(t){t(e.value)}).then(s,u)}a((n=n.apply(e,t||[])).next())})}function i(e,t){var r,n,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:u(0),throw:u(1),return:u(2)},\"function\"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function u(o){return function(u){return function(o){if(r)throw new TypeError(\"Generator is already executing.\");for(;s;)try{if(r=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,n=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],n=0}finally{r=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,u])}}}var o=r(2);r.d(t,\"add\",function(){return h}),r.d(t,\"done\",function(){return d}),r.d(t,\"toJS\",function(){return p}),r.d(t,\"load\",function(){return y}),r.d(t,\"search\",function(){return v});try{r(35)}catch(e){}var s=function(){return function(){this.add=h,this.done=d,this.search=v,this.toJS=p,this.load=y}}(),u=(t.default=s,[]),a=function(){throw new Error(\"Should not be called\")},c=new Promise(function(e){a=e});o.tokenizer.separator=/\\\\s+/;var l=new o.Builder;l.field(\"title\"),l.field(\"description\"),l.ref(\"ref\"),l.pipeline.add(o.trimmer,o.stopWordFilter,o.stemmer);var f=function(e){return\"*\"+o.stemmer(new o.Token(e,{}))+\"*\"};function h(e,t,r){var n=u.push(r)-1,i={title:e.toLowerCase(),description:t.toLowerCase(),ref:n};l.add(i)}function d(){return n(this,void 0,void 0,function(){return i(this,function(e){return a(l.build()),[2]})})}function p(){return n(this,void 0,void 0,function(){var e;return i(this,function(t){switch(t.label){case 0:return e={store:u},[4,c];case 1:return[2,(e.index=t.sent().toJSON(),e)]}})})}function y(e){return n(this,void 0,void 0,function(){return i(this,function(t){return u=e.store,a(o.Index.load(e.index)),[2]})})}function v(e,t){return void 0===t&&(t=0),n(this,void 0,void 0,function(){var r;return i(this,function(n){switch(n.label){case 0:return 0===e.trim().length?[2,[]]:[4,c];case 1:return r=n.sent().query(function(t){e.trim().toLowerCase().split(/\\\\s+/).forEach(function(e){var r=f(e);t.term(r,{})})}),t>0&&(r=r.slice(0,t)),[2,r.map(function(e){return{meta:u[e.ref],score:e.score}})]}})})}addEventListener(\"message\",function(e){var r,n=e.data,i=n.type,o=n.method,s=n.id,u=n.params;\"RPC\"===i&&o&&((r=t[o])?Promise.resolve().then(function(){return r.apply(t,u)}):Promise.reject(\"No such method\")).then(function(e){postMessage({type:\"RPC\",id:s,result:e})}).catch(function(e){var t={message:e};e.stack&&(t.message=e.message,t.stack=e.stack,t.name=e.name),postMessage({type:\"RPC\",id:s,error:t})})}),postMessage({type:\"RPC\",method:\"ready\"})}]);\\n//# sourceMappingURL=bbd40b5d662c7b796349.worker.js.map'])),{name:\"[hash].worker.js\"});return r(e,o),e}},function(e,t){e.exports=function(e,t){var n=0,r={};e.addEventListener(\"message\",function(t){var n=t.data;if(\"RPC\"===n.type)if(n.id){var o=r[n.id];o&&(delete r[n.id],n.error?o[1](Object.assign(Error(n.error.message),n.error)):o[0](n.result))}else{var i=document.createEvent(\"Event\");i.initEvent(n.method,!1,!1),i.data=n.params,e.dispatchEvent(i)}}),t.forEach(function(t){e[t]=function(){for(var o=[],i=arguments.length;i--;)o[i]=arguments[i];return new Promise(function(i,a){var s=++n;r[s]=[i,a],e.postMessage({type:\"RPC\",id:s,method:t,params:o})})}})}},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||\"\",r=e[3];if(!r)return n;if(t&&\"function\"==typeof btoa){var o=(a=r,\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,\"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+\" */\"),i=r.sources.map(function(e){return\"/*# sourceURL=\"+r.sourceRoot+e+\" */\"});return[n].concat(i).concat([o]).join(\"\\n\")}var a;return[n].join(\"\\n\")}(t,e);return t[2]?\"@media \"+t[2]+\"{\"+n+\"}\":n}).join(\"\")},t.i=function(e,n){\"string\"==typeof e&&(e=[[null,e,\"\"]]);for(var r={},o=0;o<this.length;o++){var i=this[o][0];\"number\"==typeof i&&(r[i]=!0)}for(o=0;o<e.length;o++){var a=e[o];\"number\"==typeof a[0]&&r[a[0]]||(n&&!a[2]?a[2]=n:n&&(a[2]=\"(\"+a[2]+\") and (\"+n+\")\"),t.push(a))}},t}},function(e,t){\n/*!\n * Stickyfill -- `position: sticky` polyfill\n * v. 1.1.1 | https://github.com/wilddeer/stickyfill\n * Copyright Oleg Korsunsky | http://wd.dizaina.net/\n *\n * MIT License\n */\ne.exports=function(e,t){e||(e=document),t||(t=window);var n,r,o=[],i=!1,a=e.documentElement,s=function(){},l=\"hidden\",c=\"visibilitychange\";void 0!==e.webkitHidden&&(l=\"webkitHidden\",c=\"webkitvisibilitychange\"),t.getComputedStyle||d();for(var u=[\"\",\"-webkit-\",\"-moz-\",\"-ms-\"],p=document.createElement(\"div\"),f=u.length-1;f>=0;f--){try{p.style.position=u[f]+\"sticky\"}catch(e){}\"\"!=p.style.position&&d()}function d(){A=L=I=P=R=N=s}function h(e){return parseFloat(e)||0}function m(){n={top:t.pageYOffset,left:t.pageXOffset}}function g(){if(t.pageXOffset!=n.left)return m(),void I();t.pageYOffset!=n.top&&(m(),v())}function y(e){setTimeout(function(){t.pageYOffset!=n.top&&(n.top=t.pageYOffset,v())},0)}function v(){for(var e=o.length-1;e>=0;e--)b(o[e])}function b(e){if(e.inited){var t=n.top<=e.limit.start?0:n.top>=e.limit.end?2:1;e.mode!=t&&function(e,t){var n=e.node.style;switch(t){case 0:n.position=\"absolute\",n.left=e.offset.left+\"px\",n.right=e.offset.right+\"px\",n.top=e.offset.top+\"px\",n.bottom=\"auto\",n.width=\"auto\",n.marginLeft=0,n.marginRight=0,n.marginTop=0;break;case 1:n.position=\"fixed\",n.left=e.box.left+\"px\",n.right=e.box.right+\"px\",n.top=e.css.top,n.bottom=\"auto\",n.width=\"auto\",n.marginLeft=0,n.marginRight=0,n.marginTop=0;break;case 2:n.position=\"absolute\",n.left=e.offset.left+\"px\",n.right=e.offset.right+\"px\",n.top=\"auto\",n.bottom=0,n.width=\"auto\",n.marginLeft=0,n.marginRight=0}e.mode=t}(e,t)}}function w(e){isNaN(parseFloat(e.computed.top))||e.isCell||(e.inited=!0,e.clone||function(e){e.clone=document.createElement(\"div\");var t=e.node.nextSibling||e.node,n=e.clone.style;n.height=e.height+\"px\",n.width=e.width+\"px\",n.marginTop=e.computed.marginTop,n.marginBottom=e.computed.marginBottom,n.marginLeft=e.computed.marginLeft,n.marginRight=e.computed.marginRight,n.padding=n.border=n.borderSpacing=0,n.fontSize=\"1em\",n.position=\"static\",n.cssFloat=e.computed.cssFloat,e.node.parentNode.insertBefore(e.clone,t)}(e),\"absolute\"!=e.parent.computed.position&&\"relative\"!=e.parent.computed.position&&(e.parent.node.style.position=\"relative\"),b(e),e.parent.height=e.parent.node.offsetHeight,e.docOffsetTop=_(e.clone))}function x(e){var t=!0;e.clone&&function(e){e.clone.parentNode.removeChild(e.clone),e.clone=void 0}(e),function(e,t){for(key in t)t.hasOwnProperty(key)&&(e[key]=t[key])}(e.node.style,e.css);for(var n=o.length-1;n>=0;n--)if(o[n].node!==e.node&&o[n].parent.node===e.parent.node){t=!1;break}t&&(e.parent.node.style.position=e.parent.css.position),e.mode=-1}function k(){for(var e=o.length-1;e>=0;e--)w(o[e])}function E(){for(var e=o.length-1;e>=0;e--)x(o[e])}function S(e){var t=getComputedStyle(e),n=e.parentNode,r=getComputedStyle(n),o=e.style.position;e.style.position=\"relative\";var i={top:t.top,marginTop:t.marginTop,marginBottom:t.marginBottom,marginLeft:t.marginLeft,marginRight:t.marginRight,cssFloat:t.cssFloat},s={top:h(t.top),marginBottom:h(t.marginBottom),paddingLeft:h(t.paddingLeft),paddingRight:h(t.paddingRight),borderLeftWidth:h(t.borderLeftWidth),borderRightWidth:h(t.borderRightWidth)};e.style.position=o;var l={position:e.style.position,top:e.style.top,bottom:e.style.bottom,left:e.style.left,right:e.style.right,width:e.style.width,marginTop:e.style.marginTop,marginLeft:e.style.marginLeft,marginRight:e.style.marginRight},c=O(e),u=O(n),p={node:n,css:{position:n.style.position},computed:{position:r.position},numeric:{borderLeftWidth:h(r.borderLeftWidth),borderRightWidth:h(r.borderRightWidth),borderTopWidth:h(r.borderTopWidth),borderBottomWidth:h(r.borderBottomWidth)}};return{node:e,box:{left:c.win.left,right:a.clientWidth-c.win.right},offset:{top:c.win.top-u.win.top-p.numeric.borderTopWidth,left:c.win.left-u.win.left-p.numeric.borderLeftWidth,right:-c.win.right+u.win.right-p.numeric.borderRightWidth},css:l,isCell:\"table-cell\"==t.display,computed:i,numeric:s,width:c.win.right-c.win.left,height:c.win.bottom-c.win.top,mode:-1,inited:!1,parent:p,limit:{start:c.doc.top-s.top,end:u.doc.top+n.offsetHeight-p.numeric.borderBottomWidth-e.offsetHeight-s.top-s.marginBottom}}}function _(e){for(var t=0;e;)t+=e.offsetTop,e=e.offsetParent;return t}function O(e){var n=e.getBoundingClientRect();return{doc:{top:n.top+t.pageYOffset,left:n.left+t.pageXOffset},win:n}}function C(){r=setInterval(function(){!function(){for(var e=o.length-1;e>=0;e--)if(o[e].inited){var t=Math.abs(_(o[e].clone)-o[e].docOffsetTop),n=Math.abs(o[e].parent.node.offsetHeight-o[e].parent.height);if(t>=2||n>=2)return!1}return!0}()&&I()},500)}function T(){clearInterval(r)}function j(){i&&(document[l]?T():C())}function A(){i||(m(),k(),t.addEventListener(\"scroll\",g),t.addEventListener(\"wheel\",y),t.addEventListener(\"resize\",I),t.addEventListener(\"orientationchange\",I),e.addEventListener(c,j),C(),i=!0)}function I(){if(i){E();for(var e=o.length-1;e>=0;e--)o[e]=S(o[e].node);k()}}function P(){t.removeEventListener(\"scroll\",g),t.removeEventListener(\"wheel\",y),t.removeEventListener(\"resize\",I),t.removeEventListener(\"orientationchange\",I),e.removeEventListener(c,j),T(),i=!1}function R(){P(),E()}function N(){for(R();o.length;)o.pop()}function L(e){for(var t=o.length-1;t>=0;t--)if(o[t].node===e)return;var n=S(e);o.push(n),i?w(n):A()}return m(),{stickies:o,add:L,remove:function(e){for(var t=o.length-1;t>=0;t--)o[t].node===e&&(x(o[t]),o.splice(t,1))},init:A,rebuild:I,pause:P,stop:R,kill:N}}},function(e,t,n){\"use strict\";n.r(t);var r={};n.r(r),n.d(r,\"default\",function(){return Nr});\n/*! *****************************************************************************\nCopyright (c) Microsoft Corporation. All rights reserved.\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at http://www.apache.org/licenses/LICENSE-2.0\n\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\nMERCHANTABLITY OR NON-INFRINGEMENT.\n\nSee the Apache Version 2.0 License for specific language governing permissions\nand limitations under the License.\n***************************************************************************** */\nvar o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function i(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};function s(e,t,n,r){var o,i=arguments.length,a=i<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}function l(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{l(r.next(e))}catch(e){i(e)}}function s(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}l((r=r.apply(e,t||[])).next())})}function c(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},\"function\"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError(\"Generator is already executing.\");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}}function u(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e}var p=n(0),f=n.n(p),d=n(13),h=n(11);function m(){return(m=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function g(e){return Math.round(255*e)}function y(e,t,n){return g(e)+\",\"+g(t)+\",\"+g(n)}function v(e,t,n,r){if(void 0===r&&(r=y),0===t)return r(n,n,n);var o=e%360/60,i=(1-Math.abs(2*n-1))*t,a=i*(1-Math.abs(o%2-1)),s=0,l=0,c=0;o>=0&&o<1?(s=i,l=a):o>=1&&o<2?(s=a,l=i):o>=2&&o<3?(l=i,c=a):o>=3&&o<4?(l=a,c=i):o>=4&&o<5?(s=a,c=i):o>=5&&o<6&&(s=i,c=a);var u=n-i/2;return r(s+u,l+u,c+u)}var b={aliceblue:\"f0f8ff\",antiquewhite:\"faebd7\",aqua:\"00ffff\",aquamarine:\"7fffd4\",azure:\"f0ffff\",beige:\"f5f5dc\",bisque:\"ffe4c4\",black:\"000\",blanchedalmond:\"ffebcd\",blue:\"0000ff\",blueviolet:\"8a2be2\",brown:\"a52a2a\",burlywood:\"deb887\",cadetblue:\"5f9ea0\",chartreuse:\"7fff00\",chocolate:\"d2691e\",coral:\"ff7f50\",cornflowerblue:\"6495ed\",cornsilk:\"fff8dc\",crimson:\"dc143c\",cyan:\"00ffff\",darkblue:\"00008b\",darkcyan:\"008b8b\",darkgoldenrod:\"b8860b\",darkgray:\"a9a9a9\",darkgreen:\"006400\",darkgrey:\"a9a9a9\",darkkhaki:\"bdb76b\",darkmagenta:\"8b008b\",darkolivegreen:\"556b2f\",darkorange:\"ff8c00\",darkorchid:\"9932cc\",darkred:\"8b0000\",darksalmon:\"e9967a\",darkseagreen:\"8fbc8f\",darkslateblue:\"483d8b\",darkslategray:\"2f4f4f\",darkslategrey:\"2f4f4f\",darkturquoise:\"00ced1\",darkviolet:\"9400d3\",deeppink:\"ff1493\",deepskyblue:\"00bfff\",dimgray:\"696969\",dimgrey:\"696969\",dodgerblue:\"1e90ff\",firebrick:\"b22222\",floralwhite:\"fffaf0\",forestgreen:\"228b22\",fuchsia:\"ff00ff\",gainsboro:\"dcdcdc\",ghostwhite:\"f8f8ff\",gold:\"ffd700\",goldenrod:\"daa520\",gray:\"808080\",green:\"008000\",greenyellow:\"adff2f\",grey:\"808080\",honeydew:\"f0fff0\",hotpink:\"ff69b4\",indianred:\"cd5c5c\",indigo:\"4b0082\",ivory:\"fffff0\",khaki:\"f0e68c\",lavender:\"e6e6fa\",lavenderblush:\"fff0f5\",lawngreen:\"7cfc00\",lemonchiffon:\"fffacd\",lightblue:\"add8e6\",lightcoral:\"f08080\",lightcyan:\"e0ffff\",lightgoldenrodyellow:\"fafad2\",lightgray:\"d3d3d3\",lightgreen:\"90ee90\",lightgrey:\"d3d3d3\",lightpink:\"ffb6c1\",lightsalmon:\"ffa07a\",lightseagreen:\"20b2aa\",lightskyblue:\"87cefa\",lightslategray:\"789\",lightslategrey:\"789\",lightsteelblue:\"b0c4de\",lightyellow:\"ffffe0\",lime:\"0f0\",limegreen:\"32cd32\",linen:\"faf0e6\",magenta:\"f0f\",maroon:\"800000\",mediumaquamarine:\"66cdaa\",mediumblue:\"0000cd\",mediumorchid:\"ba55d3\",mediumpurple:\"9370db\",mediumseagreen:\"3cb371\",mediumslateblue:\"7b68ee\",mediumspringgreen:\"00fa9a\",mediumturquoise:\"48d1cc\",mediumvioletred:\"c71585\",midnightblue:\"191970\",mintcream:\"f5fffa\",mistyrose:\"ffe4e1\",moccasin:\"ffe4b5\",navajowhite:\"ffdead\",navy:\"000080\",oldlace:\"fdf5e6\",olive:\"808000\",olivedrab:\"6b8e23\",orange:\"ffa500\",orangered:\"ff4500\",orchid:\"da70d6\",palegoldenrod:\"eee8aa\",palegreen:\"98fb98\",paleturquoise:\"afeeee\",palevioletred:\"db7093\",papayawhip:\"ffefd5\",peachpuff:\"ffdab9\",peru:\"cd853f\",pink:\"ffc0cb\",plum:\"dda0dd\",powderblue:\"b0e0e6\",purple:\"800080\",rebeccapurple:\"639\",red:\"f00\",rosybrown:\"bc8f8f\",royalblue:\"4169e1\",saddlebrown:\"8b4513\",salmon:\"fa8072\",sandybrown:\"f4a460\",seagreen:\"2e8b57\",seashell:\"fff5ee\",sienna:\"a0522d\",silver:\"c0c0c0\",skyblue:\"87ceeb\",slateblue:\"6a5acd\",slategray:\"708090\",slategrey:\"708090\",snow:\"fffafa\",springgreen:\"00ff7f\",steelblue:\"4682b4\",tan:\"d2b48c\",teal:\"008080\",thistle:\"d8bfd8\",tomato:\"ff6347\",turquoise:\"40e0d0\",violet:\"ee82ee\",wheat:\"f5deb3\",white:\"fff\",whitesmoke:\"f5f5f5\",yellow:\"ff0\",yellowgreen:\"9acd32\"};var w=/^#[a-fA-F0-9]{6}$/,x=/^#[a-fA-F0-9]{8}$/,k=/^#[a-fA-F0-9]{3}$/,E=/^#[a-fA-F0-9]{4}$/,S=/^rgb\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)$/,_=/^rgba\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*([-+]?[0-9]*[.]?[0-9]+)\\s*\\)$/,O=/^hsl\\(\\s*(\\d{0,3}[.]?[0-9]+)\\s*,\\s*(\\d{1,3})%\\s*,\\s*(\\d{1,3})%\\s*\\)$/,C=/^hsla\\(\\s*(\\d{0,3}[.]?[0-9]+)\\s*,\\s*(\\d{1,3})%\\s*,\\s*(\\d{1,3})%\\s*,\\s*([-+]?[0-9]*[.]?[0-9]+)\\s*\\)$/;function T(e){if(\"string\"!=typeof e)throw new Error(\"Passed an incorrect argument to a color function, please pass a string representation of a color.\");var t=function(e){if(\"string\"!=typeof e)return e;var t=e.toLowerCase();return b[t]?\"#\"+b[t]:e}(e);if(t.match(w))return{red:parseInt(\"\"+t[1]+t[2],16),green:parseInt(\"\"+t[3]+t[4],16),blue:parseInt(\"\"+t[5]+t[6],16)};if(t.match(x)){var n=parseFloat((parseInt(\"\"+t[7]+t[8],16)/255).toFixed(2));return{red:parseInt(\"\"+t[1]+t[2],16),green:parseInt(\"\"+t[3]+t[4],16),blue:parseInt(\"\"+t[5]+t[6],16),alpha:n}}if(t.match(k))return{red:parseInt(\"\"+t[1]+t[1],16),green:parseInt(\"\"+t[2]+t[2],16),blue:parseInt(\"\"+t[3]+t[3],16)};if(t.match(E)){var r=parseFloat((parseInt(\"\"+t[4]+t[4],16)/255).toFixed(2));return{red:parseInt(\"\"+t[1]+t[1],16),green:parseInt(\"\"+t[2]+t[2],16),blue:parseInt(\"\"+t[3]+t[3],16),alpha:r}}var o=S.exec(t);if(o)return{red:parseInt(\"\"+o[1],10),green:parseInt(\"\"+o[2],10),blue:parseInt(\"\"+o[3],10)};var i=_.exec(t);if(i)return{red:parseInt(\"\"+i[1],10),green:parseInt(\"\"+i[2],10),blue:parseInt(\"\"+i[3],10),alpha:parseFloat(\"\"+i[4])};var a=O.exec(t);if(a){var s=\"rgb(\"+v(parseInt(\"\"+a[1],10),parseInt(\"\"+a[2],10)/100,parseInt(\"\"+a[3],10)/100)+\")\",l=S.exec(s);if(!l)throw new Error(\"Couldn't generate valid rgb string from \"+t+\", it returned \"+s+\".\");return{red:parseInt(\"\"+l[1],10),green:parseInt(\"\"+l[2],10),blue:parseInt(\"\"+l[3],10)}}var c=C.exec(t);if(c){var u=\"rgb(\"+v(parseInt(\"\"+c[1],10),parseInt(\"\"+c[2],10)/100,parseInt(\"\"+c[3],10)/100)+\")\",p=S.exec(u);if(!p)throw new Error(\"Couldn't generate valid rgb string from \"+t+\", it returned \"+u+\".\");return{red:parseInt(\"\"+p[1],10),green:parseInt(\"\"+p[2],10),blue:parseInt(\"\"+p[3],10),alpha:parseFloat(\"\"+c[4])}}throw new Error(\"Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.\")}function j(e){return function(e){var t,n=e.red/255,r=e.green/255,o=e.blue/255,i=Math.max(n,r,o),a=Math.min(n,r,o),s=(i+a)/2;if(i===a)return void 0!==e.alpha?{hue:0,saturation:0,lightness:s,alpha:e.alpha}:{hue:0,saturation:0,lightness:s};var l=i-a,c=s>.5?l/(2-i-a):l/(i+a);switch(i){case n:t=(r-o)/l+(r<o?6:0);break;case r:t=(o-n)/l+2;break;default:t=(n-r)/l+4}return t*=60,void 0!==e.alpha?{hue:t,saturation:c,lightness:s,alpha:e.alpha}:{hue:t,saturation:c,lightness:s}}(T(e))}var A=function(e){return 7===e.length&&e[1]===e[2]&&e[3]===e[4]&&e[5]===e[6]?\"#\"+e[1]+e[3]+e[5]:e};function I(e){var t=e.toString(16);return 1===t.length?\"0\"+t:t}function P(e){return I(Math.round(255*e))}function R(e,t,n){return A(\"#\"+P(e)+P(t)+P(n))}function N(e,t,n){return v(e,t,n,R)}function L(e,t,n){if(\"number\"==typeof e&&\"number\"==typeof t&&\"number\"==typeof n)return A(\"#\"+I(e)+I(t)+I(n));if(\"object\"==typeof e&&void 0===t&&void 0===n)return A(\"#\"+I(e.red)+I(e.green)+I(e.blue));throw new Error(\"Passed invalid arguments to rgb, please pass multiple numbers e.g. rgb(255, 205, 100) or an object e.g. rgb({ red: 255, green: 205, blue: 100 }).\")}function M(e,t,n,r){if(\"string\"==typeof e&&\"number\"==typeof t){var o=T(e);return\"rgba(\"+o.red+\",\"+o.green+\",\"+o.blue+\",\"+t+\")\"}if(\"number\"==typeof e&&\"number\"==typeof t&&\"number\"==typeof n&&\"number\"==typeof r)return r>=1?L(e,t,n):\"rgba(\"+e+\",\"+t+\",\"+n+\",\"+r+\")\";if(\"object\"==typeof e&&void 0===t&&void 0===n&&void 0===r)return e.alpha>=1?L(e.red,e.green,e.blue):\"rgba(\"+e.red+\",\"+e.green+\",\"+e.blue+\",\"+e.alpha+\")\";throw new Error(\"Passed invalid arguments to rgba, please pass multiple numbers e.g. rgb(255, 205, 100, 0.75) or an object e.g. rgb({ red: 255, green: 205, blue: 100, alpha: 0.75 }).\")}var D=function(e){return\"number\"==typeof e.red&&\"number\"==typeof e.green&&\"number\"==typeof e.blue&&(\"number\"!=typeof e.alpha||void 0===e.alpha)},F=function(e){return\"number\"==typeof e.red&&\"number\"==typeof e.green&&\"number\"==typeof e.blue&&\"number\"==typeof e.alpha},U=function(e){return\"number\"==typeof e.hue&&\"number\"==typeof e.saturation&&\"number\"==typeof e.lightness&&(\"number\"!=typeof e.alpha||void 0===e.alpha)},B=function(e){return\"number\"==typeof e.hue&&\"number\"==typeof e.saturation&&\"number\"==typeof e.lightness&&\"number\"==typeof e.alpha},z=\"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\";function $(e){if(\"object\"!=typeof e)throw new Error(z);if(F(e))return M(e);if(D(e))return L(e);if(B(e))return function(e,t,n,r){if(\"number\"==typeof e&&\"number\"==typeof t&&\"number\"==typeof n&&\"number\"==typeof r)return r>=1?N(e,t,n):\"rgba(\"+v(e,t,n)+\",\"+r+\")\";if(\"object\"==typeof e&&void 0===t&&void 0===n&&void 0===r)return e.alpha>=1?N(e.hue,e.saturation,e.lightness):\"rgba(\"+v(e.hue,e.saturation,e.lightness)+\",\"+e.alpha+\")\";throw new Error(\"Passed invalid arguments to hsla, please pass multiple numbers e.g. hsl(360, 0.75, 0.4, 0.7) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75, alpha: 0.7 }).\")}(e);if(U(e))return function(e,t,n){if(\"number\"==typeof e&&\"number\"==typeof t&&\"number\"==typeof n)return N(e,t,n);if(\"object\"==typeof e&&void 0===t&&void 0===n)return N(e.hue,e.saturation,e.lightness);throw new Error(\"Passed invalid arguments to hsl, please pass multiple numbers e.g. hsl(360, 0.75, 0.4) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75 }).\")}(e);throw new Error(z)}function W(e){return function e(t,n,r){return function(){var o=r.concat(Array.prototype.slice.call(arguments));return o.length>=n?t.apply(this,o):e(t,n,o)}}(e,e.length,[])}function q(e,t,n){return Math.max(e,Math.min(t,n))}function H(e,t){var n=j(t);return $(m({},n,{lightness:q(0,1,n.lightness-parseFloat(e))}))}var Y=W(H);function V(e,t){var n=j(t);return $(m({},n,{saturation:q(0,1,n.saturation-parseFloat(e))}))}var Q=W(V);function G(e,t){var n=j(t);return $(m({},n,{lightness:q(0,1,n.lightness+parseFloat(e))}))}var X=W(G);function K(e){return function(e){var t=T(e),n=Object.keys(t).map(function(e){var n=t[e]/255;return n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4)}),r=n[0],o=n[1],i=n[2];return parseFloat((.2126*r+.7152*o+.0722*i).toFixed(3))}(e)>.179?\"#000\":\"#fff\"}var J=W(K);function Z(e,t){var n=T(t);return M(m({},n,{alpha:q(0,1,(100*(\"number\"==typeof n.alpha?n.alpha:1)-100*parseFloat(e))/100)}))}var ee=W(Z);var te={spacing:{unit:5,sectionHorizontal:function(e){return 8*e.spacing.unit},sectionVertical:function(e){return 8*e.spacing.unit}},breakpoints:{small:\"50rem\",medium:\"85rem\",large:\"105rem\"},colors:{tonalOffset:.3,primary:{main:\"#32329f\",light:function(e){var t=e.colors;return X(t.tonalOffset,t.primary.main)},dark:function(e){var t=e.colors;return Y(t.tonalOffset,t.primary.main)},contrastText:function(e){var t=e.colors;return J(t.primary.main)}},success:{main:\"#00aa13\",light:function(e){var t=e.colors;return X(t.tonalOffset,t.success.main)},dark:function(e){var t=e.colors;return Y(t.tonalOffset,t.success.main)},contrastText:function(e){var t=e.colors;return J(t.success.main)}},warning:{main:\"#d4ad03\",light:function(e){var t=e.colors;return X(t.tonalOffset,t.warning.main)},dark:function(e){var t=e.colors;return Y(t.tonalOffset,t.warning.main)},contrastText:\"#ffffff\"},error:{main:\"#e53935\",light:function(e){var t=e.colors;return X(t.tonalOffset,t.error.main)},dark:function(e){var t=e.colors;return Y(t.tonalOffset,t.error.main)},contrastText:function(e){var t=e.colors;return J(t.error.main)}},text:{primary:\"#333333\",secondary:function(e){var t=e.colors;return X(t.tonalOffset,t.text.primary)}},border:{dark:\"rgba(0,0,0, 0.1)\",light:\"#ffffff\"},responses:{success:{color:function(e){return e.colors.success.main},backgroundColor:function(e){var t=e.colors;return ee(.9,t.success.main)}},error:{color:function(e){return e.colors.error.main},backgroundColor:function(e){var t=e.colors;return ee(.9,t.error.main)}},redirect:{color:\"#ffa500\",backgroundColor:function(e){var t=e.colors;return ee(.9,t.responses.redirect.color)}},info:{color:\"#87ceeb\",backgroundColor:function(e){var t=e.colors;return ee(.9,t.responses.info.color)}}},http:{get:\"#6bbd5b\",post:\"#248fb2\",put:\"#9b708b\",options:\"#d3ca12\",patch:\"#e09d43\",delete:\"#e27a7a\",basic:\"#999\",link:\"#31bbb6\",head:\"#c167e4\"}},schema:{linesColor:function(e){return X(e.colors.tonalOffset,Q(e.colors.tonalOffset,e.colors.primary.main))},defaultDetailsWidth:\"75%\",typeNameColor:function(e){return e.colors.text.secondary},typeTitleColor:function(e){return e.schema.typeNameColor},requireLabelColor:function(e){return e.colors.error.main},labelsTextSize:\"0.9em\",nestingSpacing:\"1em\",nestedBackground:\"#fafafa\",arrow:{size:\"1.1em\",color:function(e){return e.colors.text.secondary}}},typography:{fontSize:\"14px\",lineHeight:\"1.5em\",fontWeightRegular:\"400\",fontWeightBold:\"600\",fontWeightLight:\"300\",fontFamily:\"Roboto, sans-serif\",smoothing:\"antialiased\",optimizeSpeed:!0,headings:{fontFamily:\"Montserrat, sans-serif\",fontWeight:\"400\"},code:{fontSize:\"13px\",fontFamily:\"Courier, monospace\",lineHeight:function(e){return e.typography.lineHeight},fontWeight:function(e){return e.typography.fontWeightRegular},color:\"#e53935\",backgroundColor:\"rgba(38, 50, 56, 0.05)\",wrap:!1},links:{color:function(e){return e.colors.primary.main},visited:function(e){return e.typography.links.color},hover:function(e){var t=e.typography;return X(.2,t.links.color)}}},menu:{width:\"260px\",backgroundColor:\"#fafafa\",textColor:\"#333333\",groupItems:{textTransform:\"uppercase\"},level1Items:{textTransform:\"none\"},arrow:{size:\"1.5em\",color:function(e){return e.menu.textColor}}},logo:{maxHeight:function(e){return e.menu.width},maxWidth:function(e){return e.menu.width}},rightPanel:{backgroundColor:\"#263238\",width:\"40%\",textColor:\"#ffffff\"},codeSample:{backgroundColor:function(e){var t=e.rightPanel;return Y(.1,t.backgroundColor)}}};var ne=\"undefined\"!=typeof window&&\"HTMLElement\"in window;function re(e){return\"undefined\"!=typeof document?document.querySelector(e):null}\"undefined\"==typeof Element||Element.prototype.scrollIntoViewIfNeeded||(Element.prototype.scrollIntoViewIfNeeded=function(e){e=0===arguments.length||!!e;var t=this.parentNode,n=window.getComputedStyle(t,void 0),r=parseInt(n.getPropertyValue(\"border-top-width\"),10),o=parseInt(n.getPropertyValue(\"border-left-width\"),10),i=this.offsetTop-t.offsetTop<t.scrollTop,a=this.offsetTop-t.offsetTop+this.clientHeight-r>t.scrollTop+t.clientHeight,s=this.offsetLeft-t.offsetLeft<t.scrollLeft,l=this.offsetLeft-t.offsetLeft+this.clientWidth-o>t.scrollLeft+t.clientWidth,c=i&&!a;(i||a)&&e&&(t.scrollTop=this.offsetTop-t.offsetTop-t.clientHeight/2-r+this.clientHeight/2),(s||l)&&e&&(t.scrollLeft=this.offsetLeft-t.offsetLeft-t.clientWidth/2-o+this.clientWidth/2),(i||a||s||l)&&!e&&this.scrollIntoView(c)});var oe=n(125),ie=n.n(oe),ae=n(10);function se(e,t){for(var n=[],r=0;r<e.length-1;r++)n.push(t(e[r],!1));return 0!==e.length&&n.push(t(e[e.length-1],!0)),n}function le(e){return e.endsWith(\"/\")?e.substring(0,e.length-1):e}function ce(e){return!isNaN(parseFloat(e))&&isFinite(e)}var ue=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];if(!t.length)return e;var r=t.shift();return void 0===r?e:(pe(e)&&pe(r)&&Object.keys(r).forEach(function(t){pe(r[t])?(e[t]||(e[t]={}),ue(e[t],r[t])):e[t]=r[t]}),ue.apply(void 0,[e].concat(t)))},pe=function(e){return function(e){return null!==e&&\"object\"==typeof e}(e)&&!Array.isArray(e)};function fe(e){return ie()(e)||e.toString().toLowerCase().replace(/\\s+/g,\"-\").replace(/&/g,\"-and-\").replace(/\\--+/g,\"-\").replace(/^-+/,\"\").replace(/-+$/,\"\")}function de(e){return void 0!==e&&(\"string\"==typeof e||e)}var he,me=function(){function e(t,n){void 0===n&&(n={});var r,o,i,s,l=(t=a({},n,t)).theme&&t.theme.extensionsHook;this.theme=(r=ue({},te,a({},t.theme,{extensionsHook:void 0})),o={},i=0,(s=function(e,t){Object.keys(e).forEach(function(n){var a=(t?t+\".\":\"\")+n,l=e[n];\"function\"==typeof l?Object.defineProperty(e,n,{get:function(){if(!o[a]){if(++i>1e3)throw new Error(\"Theme probably contains cirucal dependency at \"+a+\": \"+l.toString());o[a]=l(r)}return o[a]},enumerable:!0}):\"object\"==typeof l&&s(l,a)})})(r,\"\"),JSON.parse(JSON.stringify(r))),this.theme.extensionsHook=l,this.scrollYOffset=e.normalizeScrollYOffset(t.scrollYOffset),this.hideHostname=e.normalizeHideHostname(t.hideHostname),this.expandResponses=e.normalizeExpandResponses(t.expandResponses),this.requiredPropsFirst=de(t.requiredPropsFirst),this.sortPropsAlphabetically=de(t.sortPropsAlphabetically),this.noAutoAuth=de(t.noAutoAuth),this.nativeScrollbars=de(t.nativeScrollbars),this.pathInMiddlePanel=de(t.pathInMiddlePanel),this.untrustedSpec=de(t.untrustedSpec),this.hideDownloadButton=de(t.hideDownloadButton),this.disableSearch=de(t.disableSearch),this.onlyRequiredInSamples=de(t.onlyRequiredInSamples),this.showExtensions=e.normalizeShowExtensions(t.showExtensions),this.unstable_ignoreMimeParameters=de(t.unstable_ignoreMimeParameters),this.allowedMdComponents=t.allowedMdComponents||{}}return e.normalizeExpandResponses=function(e){if(\"all\"===e)return\"all\";if(\"string\"==typeof e){var t={};return e.split(\",\").forEach(function(e){t[e.trim()]=!0}),t}return void 0!==e&&console.warn('expandResponses must be a string but received value \"'+e+'\" of type '+typeof e),{}},e.normalizeHideHostname=function(e){return!!e},e.normalizeScrollYOffset=function(e){if(\"string\"==typeof e&&!ce(e)){var t=re(e);t||console.warn(\"scrollYOffset value is a selector to non-existing element. Using offset 0 by default\");var n=t&&t.getBoundingClientRect().bottom||0;return function(){return n}}return\"number\"==typeof e||ce(e)?function(){return\"number\"==typeof e?e:parseFloat(e)}:\"function\"==typeof e?function(){var t=e();return\"number\"!=typeof t&&console.warn('scrollYOffset should return number but returned value \"'+t+'\" of type '+typeof t),t}:(void 0!==e&&console.warn(\"Wrong value for scrollYOffset ReDoc option: should be string, number or function\"),function(){return 0})},e.normalizeShowExtensions=function(e){return void 0!==e&&(\"\"===e||(\"string\"==typeof e?e.split(\",\").map(function(e){return e.trim()}):e))},e}(),ge=n(126),ye=ge.default,ve=ge.css,be=ge.createGlobalStyle,we=ge.keyframes,xe=ge.ThemeProvider,ke=function(e,t){return function(){for(var n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];return ve(he||(he=u([\"\\n      @media \",\" screen and (max-width: \",\") {\\n        \",\";\\n      }\\n    \"],[\"\\n      @media \",\" screen and (max-width: \",\") {\\n        \",\";\\n      }\\n    \"])),t?\"print, \":\"\",function(t){return t.theme.breakpoints[e]},ve.apply(void 0,n))}},Ee=ye;function Se(e){return function(t){if(t.theme.extensionsHook)return t.theme.extensionsHook(e,t)}}var _e=Ee.div.withConfig({componentId:\"cxucko-0\"})([\"padding:20px;color:red;\"]),Oe=function(e){function t(t){var n=e.call(this,t)||this;return n.state={error:void 0},n}return i(t,e),t.prototype.componentDidCatch=function(e){return this.setState({error:e}),!1},t.prototype.render=function(){return this.state.error?p.createElement(_e,null,p.createElement(\"h1\",null,\"Something went wrong...\"),p.createElement(\"small\",null,\" \",this.state.error.message,\" \"),p.createElement(\"p\",null,p.createElement(\"details\",null,p.createElement(\"summary\",null,\"Stack trace\"),p.createElement(\"pre\",null,this.state.error.stack))),p.createElement(\"small\",null,\" ReDoc Version: \",\"2.0.0-rc.1\"),\" \",p.createElement(\"br\",null),p.createElement(\"small\",null,\" Commit: \",\"c16d3d5\")):p.Children.only(this.props.children)},t}(p.Component),Ce=we([\"0%{transform:rotate(0deg);}100%{transform:rotate(360deg);}\"]),Te=Ee(function(e){return p.createElement(\"svg\",{className:e.className,version:\"1.1\",width:\"512\",height:\"512\",viewBox:\"0 0 512 512\"},p.createElement(\"path\",{d:\"M275.682 147.999c0 10.864-8.837 19.661-19.682 19.661v0c-10.875 0-19.681-8.796-19.681-19.661v-96.635c0-10.885 8.806-19.661 19.681-19.661v0c10.844 0 19.682 8.776 19.682 19.661v96.635z\"}),p.createElement(\"path\",{d:\"M275.682 460.615c0 10.865-8.837 19.682-19.682 19.682v0c-10.875 0-19.681-8.817-19.681-19.682v-96.604c0-10.885 8.806-19.681 19.681-19.681v0c10.844 0 19.682 8.796 19.682 19.682v96.604z\"}),p.createElement(\"path\",{d:\"M147.978 236.339c10.885 0 19.681 8.755 19.681 19.641v0c0 10.885-8.796 19.702-19.681 19.702h-96.624c-10.864 0-19.661-8.817-19.661-19.702v0c0-10.885 8.796-19.641 19.661-19.641h96.624z\"}),p.createElement(\"path\",{d:\"M460.615 236.339c10.865 0 19.682 8.755 19.682 19.641v0c0 10.885-8.817 19.702-19.682 19.702h-96.584c-10.885 0-19.722-8.817-19.722-19.702v0c0-10.885 8.837-19.641 19.722-19.641h96.584z\"}),p.createElement(\"path\",{d:\"M193.546 165.703c7.69 7.66 7.68 20.142 0 27.822v0c-7.701 7.701-20.162 7.701-27.853 0.020l-68.311-68.322c-7.68-7.701-7.68-20.142 0-27.863v0c7.68-7.68 20.121-7.68 27.822 0l68.342 68.342z\"}),p.createElement(\"path\",{d:\"M414.597 386.775c7.7 7.68 7.7 20.163 0.021 27.863v0c-7.7 7.659-20.142 7.659-27.843-0.062l-68.311-68.26c-7.68-7.7-7.68-20.204 0-27.863v0c7.68-7.7 20.163-7.7 27.842 0l68.291 68.322z\"}),p.createElement(\"path\",{d:\"M165.694 318.464c7.69-7.7 20.153-7.7 27.853 0v0c7.68 7.659 7.69 20.163 0 27.863l-68.342 68.322c-7.67 7.659-20.142 7.659-27.822-0.062v0c-7.68-7.68-7.68-20.122 0-27.801l68.311-68.322z\"}),p.createElement(\"path\",{d:\"M386.775 97.362c7.7-7.68 20.142-7.68 27.822 0v0c7.7 7.68 7.7 20.183 0.021 27.863l-68.322 68.311c-7.68 7.68-20.163 7.68-27.843-0.020v0c-7.68-7.68-7.68-20.162 0-27.822l68.322-68.332z\"}))}).withConfig({componentId:\"sc-8xfcsx-0\"})([\"animation:2s \",\" linear infinite;width:50px;height:50px;content:'';display:inline-block;margin-left:-25px;path{fill:\",\";}\"],Ce,function(e){return e.color}),je=Ee.div.withConfig({componentId:\"xhqjuh-0\"})([\"font-family:helvetica,sans;width:100%;text-align:center;font-size:25px;margin:30px 0 20px 0;color:\",\";\"],function(e){return e.color}),Ae=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return p.createElement(\"div\",{style:{textAlign:\"center\"}},p.createElement(je,{color:this.props.color},\"Loading ...\"),p.createElement(Te,{color:this.props.color}))},t}(p.PureComponent),Ie=p.createContext(new me({})),Pe=Ie.Provider,Re=Ie.Consumer,Ne=n(1),Le=n(129),Me=n(130);function De(e){return l(this,void 0,void 0,function(){var t;return c(this,function(n){switch(n.label){case 0:return[4,(new Le).bundle(e,{resolve:{http:{withCredentials:!1}}})];case 1:return void 0!==(t=n.sent()).swagger?[2,function(e){return console.warn(\"[ReDoc Compatibility mode]: Converting OpenAPI 2.0 to OpenAPI 3.0\"),new Promise(function(t,n){return Object(Me.convertObj)(e,{patch:!0,warnOnly:!0},function(e,r){if(e)return n(e);t(r&&r.openapi)})})}(t)]:[2,t]}})})}var Fe=n(40),Ue=n(53),Be=n(15),ze=Be.parse,$e=function(){function e(){}return e.baseName=function(t,n){void 0===n&&(n=1);var r=e.parse(t);return r[r.length-n]},e.dirName=function(t,n){void 0===n&&(n=1);var r=e.parse(t);return Be.compile(r.slice(0,r.length-n))},e.relative=function(t,n){var r=e.parse(t);return e.parse(n).slice(r.length)},e.parse=function(e){var t=e;return\"#\"===t.charAt(0)&&(t=t.substring(1)),ze(t)},e.join=function(t,n){var r=e.parse(t).concat(n);return Be.compile(r)},e.get=function(e,t){return Be.get(e,t)},e.compile=function(e){return Be.compile(e)},e.escape=function(e){return Be.escape(e)},e}();Be.parse=$e.parse,Object.assign($e,Be);var We=n(52);function qe(e){return\"string\"==typeof e&&/\\dxx/i.test(e)}function He(e,t){if(void 0===t&&(t=!1),\"default\"===e)return t?\"error\":\"success\";var n=\"string\"==typeof e?parseInt(e,10):e;if(qe(e)&&(n*=100),n<100||n>599)throw new Error(\"invalid HTTP code\");var r=\"success\";return n>=300&&n<400?r=\"redirect\":n>=400?r=\"error\":n<200&&(r=\"info\"),r}var Ye={get:!0,post:!0,put:!0,head:!0,patch:!0,delete:!0,options:!0};function Ve(e){return e in Ye}var Qe={multipleOf:\"number\",maximum:\"number\",exclusiveMaximum:\"number\",minimum:\"number\",exclusiveMinimum:\"number\",maxLength:\"string\",minLength:\"string\",pattern:\"string\",items:\"array\",maxItems:\"array\",minItems:\"array\",uniqueItems:\"array\",maxProperties:\"object\",minProperties:\"object\",required:\"object\",additionalProperties:\"object\",properties:\"object\"};function Ge(e){return-1!==e.search(/json/i)}function Xe(e){return/^#\\/components\\/schemas\\/[^\\/]+$/.test(e||\"\")}function Ke(e,t,n){var r;return void 0!==t&&void 0!==n?r=t===n?t+\" \"+e:\"[ \"+t+\" .. \"+n+\" ] \"+e:void 0!==n?r=\"<= \"+n+\" \"+e:void 0!==t&&(r=1===t?\"non-empty\":\">= \"+t+\" \"+e),r}function Je(e,t){void 0===t&&(t=[]),e.sort(function(e,n){return!e.required&&n.required?1:e.required&&!n.required?-1:e.required&&n.required?t.indexOf(e.name)-t.indexOf(n.name):0})}function Ze(e,t){e.sort(function(e,n){return e[t].localeCompare(n[t])})}function et(e,t){var n=void 0===e?ne?window.location.href:\"\":Object(We.dirname)(e);if(0===t.length)return[{url:n}];function r(e,t){return e=function(e,t){return void 0===t&&(t={}),e.replace(/(?:{)(\\w+)(?:})/g,function(e,n){return t[n]&&t[n].default||e})}(e,t),function(e,t){var n;if(t.startsWith(\"//\"))n=\"\"+Object(ae.parse)(e).protocol+t;else if(function(e){return/(?:^[a-z][a-z0-9+.-]*:|\\/\\/)/i.test(e)}(t))n=t;else if(t.startsWith(\"/\")){var r=Object(ae.parse)(e);n=Object(ae.format)(a({},r,{pathname:t}))}else n=le(e)+\"/\"+t;return le(n)}(n,e)}return t.map(function(e){return a({},e,{url:r(e.url,e.variables),description:e.description||\"\"})})}var tt=\"section/Authentication/\";function nt(e,t){return Object.keys(e).filter(function(e){return!0===t?e.startsWith(\"x-\")&&!function(e){return e in{\"x-circular-ref\":!0,\"x-code-samples\":!0,\"x-displayName\":!0,\"x-examples\":!0,\"x-ignoredHeaderParameters\":!0,\"x-logo\":!0,\"x-nullable\":!0,\"x-servers\":!0,\"x-tagGroups\":!0,\"x-traitTag\":!0}}(e):e.startsWith(\"x-\")&&t.indexOf(e)>-1}).reduce(function(t,n){return t[n]=e[n],t},{})}var rt=n(55),ot=(n(247),n(248),n(249),n(250),n(251),n(252),n(253),n(254),n(255),n(256),n(257),n(258),n(259),n(260),n(261),n(262),n(263),n(264),n(265),\"clike\");function it(e,t){void 0===t&&(t=ot),t=t.toLowerCase();var n=rt.languages[t];return n||(n=rt.languages[function(e){return{json:\"js\",\"c++\":\"cpp\",\"c#\":\"csharp\",\"objective-c\":\"objectivec\",shell:\"bash\",viml:\"vim\"}[e]||ot}(t)]),rt.highlight(e,n)}function at(e){return function(t,n,r){var o,i,a,s,l,c,u,p;r.value=(o=r.value,i=e,c=null,u=0,p=function(){u=(new Date).getTime(),c=null,l=o.apply(a,s),c||(a=s=null)},function(){var e=(new Date).getTime(),t=i-(e-u);return a=this,s=arguments,t<=0||t>i?(c&&(clearTimeout(c),c=null),u=e,l=o.apply(a,s),c||(a=s=null)):c||(c=setTimeout(p,t)),l})}}function st(e){0}function lt(e){0}var ct={};function ut(e,t,n){if(\"function\"==typeof n.value)return function(e,t,n){if(!n.value||n.value.length>0)throw new Error(\"@memoize decorator can only be applied to methods of zero arguments\");var r=\"_memoized_\"+t,o=n.value;return e[r]=ct,a({},n,{value:function(){return this[r]===ct&&(this[r]=o.call(this)),this[r]}})}(e,t,n);if(\"function\"==typeof n.get)return function(e,t,n){var r=\"_memoized_\"+t,o=n.get;return e[r]=ct,a({},n,{get:function(){return this[r]===ct&&(this[r]=o.call(this)),this[r]}})}(e,t,n);throw new Error(\"@memoize decorator can be applied to methods or getters, got \"+String(n.value)+\" instead\")}var pt=\"hashchange\",ft=new(function(){function e(){var e=this;this.emit=function(){e._emiter.emit(pt,e.currentId)},this._emiter=new Ue.EventEmitter,this.bind()}return Object.defineProperty(e.prototype,\"currentId\",{get:function(){return ne?window.location.hash.substring(1):\"\"},enumerable:!0,configurable:!0}),e.prototype.linkForId=function(e){return e?\"#\"+e:\"\"},e.prototype.subscribe=function(e){var t=this._emiter.addListener(pt,e);return function(){return t.removeListener(pt,e)}},e.prototype.bind=function(){ne&&window.addEventListener(\"hashchange\",this.emit,!1)},e.prototype.dispose=function(){ne&&window.removeEventListener(\"hashchange\",this.emit)},e.prototype.replace=function(e,t){void 0===t&&(t=!1),ne&&null!=e&&e!==this.currentId&&(t?window.history.replaceState(null,\"\",window.location.href.split(\"#\")[0]+this.linkForId(e)):(window.history.pushState(null,\"\",window.location.href.split(\"#\")[0]+this.linkForId(e)),this.emit()))},s([Fe.bind,Fe.debounce],e.prototype,\"replace\",null),e}());var dt=n(79),ht=function(){function e(){this.map=new Map,this.prevTerm=\"\"}return e.prototype.add=function(e){this.map.set(e,new dt(e))},e.prototype.delete=function(e){this.map.delete(e)},e.prototype.addOnly=function(e){var t=this;this.map.forEach(function(n,r){-1===e.indexOf(r)&&(n.unmark(),t.map.delete(r))});for(var n=0,r=e;n<r.length;n++){var o=r[n];this.map.has(o)||this.map.set(o,new dt(o))}},e.prototype.clearAll=function(){this.unmark(),this.map.clear()},e.prototype.mark=function(e){var t=this;(e||this.prevTerm)&&(this.map.forEach(function(n){n.unmark(),n.mark(e||t.prevTerm)}),this.prevTerm=e||this.prevTerm)},e.prototype.unmark=function(){this.map.forEach(function(e){return e.unmark()}),this.prevTerm=\"\"},e}(),mt=n(41),gt=new mt.Renderer;mt.setOptions({renderer:gt,highlight:function(e,t){return it(e,t)}});var yt=\"(?:^ {0,3}\\x3c!-- ReDoc-Inject:\\\\s+?<({component}).*?/?>\\\\s+?--\\x3e\\\\s*$|(?:^ {0,3}<({component})([\\\\s\\\\S]*?)>([\\\\s\\\\S]*?)</\\\\2>|^ {0,3}<({component})([\\\\s\\\\S]*?)(?:/>|\\\\n{2,})))\";var vt=function(){function e(e){var t=this;this.options=e,this.headings=[],this.headingRule=function(e,n,r,o){return 1===n?t.currentTopHeading=t.saveHeading(e,n):2===n&&t.saveHeading(e,n,t.currentTopHeading&&t.currentTopHeading.items,t.currentTopHeading&&t.currentTopHeading.id),t.originalHeadingRule(e,n,r,o)},this.headingEnhanceRenderer=new mt.Renderer,this.originalHeadingRule=this.headingEnhanceRenderer.heading.bind(this.headingEnhanceRenderer),this.headingEnhanceRenderer.heading=this.headingRule}return e.containsComponent=function(e,t){return new RegExp(yt.replace(/{component}/g,t),\"gmi\").test(e)},e.prototype.saveHeading=function(e,t,n,r){void 0===n&&(n=this.headings);var o={id:r?r+\"/\"+fe(e):\"section/\"+fe(e),name:e,level:t,items:[]};return n.push(o),o},e.prototype.flattenHeadings=function(e){if(void 0===e)return[];for(var t=[],n=0,r=e;n<r.length;n++){var o=r[n];t.push(o),t.push.apply(t,this.flattenHeadings(o.items))}return t},e.prototype.attachHeadingsDescriptions=function(e){var t=function(e){return new RegExp(\"##?\\\\s+\"+e.name.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\"))},n=this.flattenHeadings(this.headings);if(!(n.length<1)){for(var r=n[0],o=t(r),i=e.search(o),a=1;a<n.length;a++){var s=n[a],l=t(s),c=e.substr(i+1).search(l)+i+1;r.description=e.substring(i,c).replace(o,\"\").trim(),r=s,o=l,i=c}r.description=e.substring(i).replace(o,\"\").trim()}},e.prototype.renderMd=function(e,t){void 0===t&&(t=!1);var n=t?{renderer:this.headingEnhanceRenderer}:void 0;return mt(e.toString(),n)},e.prototype.extractHeadings=function(e){this.renderMd(e,!0),this.attachHeadingsDescriptions(e);var t=this.headings;return this.headings=[],t},e.prototype.renderMdWithComponents=function(e){var t=this.options&&this.options.allowedMdComponents;if(!t||0===Object.keys(t).length)return[this.renderMd(e)];for(var n=Object.keys(t).join(\"|\"),r=new RegExp(yt.replace(/{component}/g,n),\"mig\"),o=[],i=[],s=r.exec(e),l=0;s;){o.push(e.substring(l,s.index)),l=r.lastIndex;var c=t[s[1]||s[2]||s[5]],u=s[3]||s[6],p=s[4];c&&i.push({component:c.component,propsSelector:c.propsSelector,props:a({},bt(u),c.props,{children:p})}),s=r.exec(e)}o.push(e.substring(l));for(var f=[],d=0;d<o.length;d++){var h=o[d];h&&f.push(this.renderMd(h)),i[d]&&f.push(i[d])}return f},e}();function bt(e){if(!e)return{};for(var t,n=/([\\w-]+)\\s*=\\s*(?:{([^}]+?)}|\"([^\"]+?)\")/gim,r={};null!==(t=n.exec(e));)if(t[3])r[t[1]]=t[3];else if(t[2]){var o=void 0;try{o=JSON.parse(t[2])}catch(e){}r[t[1]]=o}return r}var wt=function(){function e(e){this.parser=e,Object.assign(this,e.spec.info),this.description=e.spec.info.description||\"\";var t=this.description.search(/^##?\\s+/m);t>-1&&(this.description=this.description.substring(0,t)),this.downloadLink=this.getDownloadLink(),this.downloadFileName=this.getDownloadFileName()}return e.prototype.getDownloadLink=function(){if(this.parser.specUrl)return this.parser.specUrl;if(ne&&window.Blob&&window.URL&&window.URL.createObjectURL){var e=new Blob([JSON.stringify(this.parser.spec,null,2)],{type:\"application/json\"});return window.URL.createObjectURL(e)}},e.prototype.getDownloadFileName=function(){if(!this.parser.specUrl)return\"swagger.json\"},e}(),xt=function(){return function(e,t,n){var r=e.deref(n);this.id=t,this.sectionId=tt+t,this.type=r.type,this.description=r.description||\"\",\"apiKey\"===r.type&&(this.apiKey={name:r.name,in:r.in}),\"http\"===r.type&&(this.http={scheme:r.scheme,bearerFormat:r.bearerFormat}),\"openIdConnect\"===r.type&&(this.openId={connectUrl:r.openIdConnectUrl}),\"oauth2\"===r.type&&r.flows&&(this.flows=r.flows)}}(),kt=function(){return function(e){var t=e.spec.components&&e.spec.components.securitySchemes||{};this.schemes=Object.keys(t).map(function(n){return new xt(e,n,t[n])})}}(),Et=function(){function e(){this._counter={}}return e.prototype.reset=function(){this._counter={}},e.prototype.visit=function(e){this._counter[e]=this._counter[e]?this._counter[e]+1:1},e.prototype.exit=function(e){this._counter[e]=this._counter[e]&&this._counter[e]-1},e.prototype.visited=function(e){return!!this._counter[e]},e}(),St=function(){function e(e,t,n){void 0===n&&(n=new me({}));var r=this;this.options=n,this._refCounter=new Et,this.byRef=function(e){var t;if(r.spec){\"#\"!==e.charAt(0)&&(e=\"#\"+e),e=decodeURIComponent(e);try{t=$e.get(r.spec,e)}catch(e){}return t||{}}},this.validate(e),this.preprocess(e),this.spec=e;var o=ne?window.location.href:\"\";\"string\"==typeof t&&(this.specUrl=Object(ae.resolve)(o,t))}return e.prototype.validate=function(e){if(void 0===e.openapi)throw new Error(\"Document must be valid OpenAPI 3.0.0 definition\")},e.prototype.preprocess=function(e){if(!this.options.noAutoAuth&&e.info&&e.components&&e.components.securitySchemes){var t=e.info.description||\"\";if(!vt.containsComponent(t,\"security-definitions\")){var n=\"\\x3c!-- ReDoc-Inject: <\"+\"security-definitions\"+\"> --\\x3e\";e.info.description=function(e,t,n){var r=new RegExp(\"(^|\\\\n)#\\\\s?\"+t+\"\\\\s*\\\\n\",\"i\"),o=new RegExp(\"((\\\\n|^)#\\\\s*\"+t+\"\\\\s*(\\\\n|$)(?:.|\\\\n)*?)(\\\\n#|$)\",\"i\");if(r.test(e))return e.replace(o,\"$1\\n\\n\"+n+\"\\n$4\");var i=\"\"===e||e.endsWith(\"\\n\\n\")?\"\":e.endsWith(\"\\n\")?\"\\n\":\"\\n\\n\";return\"\"+e+i+\"# \"+t+\"\\n\\n\"+n}(t,\"Authentication\",n)}}},e.prototype.isRef=function(e){return!!e&&(void 0!==e.$ref&&null!==e.$ref)},e.prototype.resetVisited=function(){this._refCounter=new Et},e.prototype.exitRef=function(e){this.isRef(e)&&this._refCounter.exit(e.$ref)},e.prototype.deref=function(e,t){if(void 0===t&&(t=!1),this.isRef(e)){var n=this.byRef(e.$ref),r=this._refCounter.visited(e.$ref);if(this._refCounter.visit(e.$ref),r&&!t)return Object.assign({},n,{\"x-circular-ref\":!0});if(this.isRef(n)){var o=this.deref(n);return this.exitRef(n),o}return n}return e},e.prototype.shalowDeref=function(e){return this.isRef(e)?this.byRef(e.$ref):e},e.prototype.mergeAllOf=function(e,t,n){var r=this;if(void 0===n&&(n=!1),void 0===(e=this.hoistOneOfs(e)).allOf)return e;var o=a({},e,{allOf:void 0,parentRefs:[]});void 0!==o.properties&&\"object\"==typeof o.properties&&(o.properties=a({},o.properties)),void 0!==o.items&&\"object\"==typeof o.items&&(o.items=a({},o.items));for(var i=0,s=e.allOf.map(function(e){var t,i=r.deref(e,n),a=e.$ref||void 0,s=r.mergeAllOf(i,a,n);return(t=o.parentRefs).push.apply(t,s.parentRefs||[]),{$ref:a,schema:s}});i<s.length;i++){var l=s[i],c=l.$ref,u=l.schema;if(o.type!==u.type&&void 0!==o.type&&void 0!==u.type)throw new Error('Incompatible types in allOf at \"'+t+'\"');if(void 0!==u.type&&(o.type=u.type),void 0!==u.properties)for(var p in o.properties=o.properties||{},u.properties)o.properties[p]?o.properties[p]=this.mergeAllOf({allOf:[o.properties[p],u.properties[p]]},t+\"/properties/\"+p):o.properties[p]=u.properties[p];void 0!==u.items&&(o.items=o.items||{},o.items=this.mergeAllOf({allOf:[o.items,u.items]},t+\"/items\")),void 0!==u.required&&(o.required=(o.required||[]).concat(u.required)),o=a({},u,o),c&&(o.parentRefs.push(c),void 0===o.title&&Xe(c))}return void 0===e.title&&Xe(t)&&(o.title=$e.baseName(t)),o},e.prototype.findDerived=function(e){var t={},n=this.spec.components&&this.spec.components.schemas||{};for(var r in n){var o=this.deref(n[r]);void 0!==o.allOf&&o.allOf.find(function(t){return void 0!==t.$ref&&e.indexOf(t.$ref)>-1})&&(t[\"#/components/schemas/\"+r]=o[\"x-discriminator-value\"]||r)}return t},e.prototype.exitParents=function(e){for(var t=0,n=e.parentRefs||[];t<n.length;t++){var r=n[t];this.exitRef({$ref:r})}},e.prototype.hoistOneOfs=function(e){var t=this;if(void 0===e.allOf)return e;for(var n=e.allOf,r=function(e){var r=n[e];if(Array.isArray(r.oneOf)){var o=n.slice(0,e),i=n.slice(e+1);return{value:{oneOf:r.oneOf.map(function(e){var n=t.mergeAllOf({allOf:o.concat([e],i)});return t.exitParents(n),n})}}}},o=0;o<n.length;o++){var i=r(o);if(\"object\"==typeof i)return i.value}return e},e}(),_t=function(){return function(e,t,n){this.options=n,this.parser=new St(e,t,n),this.info=new wt(this.parser),this.externalDocs=this.parser.spec.externalDocs,this.contentItems=Ut.buildStructure(this.parser,this.options),this.securitySchemes=new kt(this.parser)}}(),Ot=function(){function e(e,t,n){this.items=[],this.active=!1,this.expanded=!1,this.id=t.id||e+\"/\"+fe(t.name),this.type=e,this.name=t[\"x-displayName\"]||t.name,this.level=t.level||1,this.description=t.description||\"\",this.parent=n,this.externalDocs=t.externalDocs,\"group\"===this.type&&(this.expanded=!0)}return e.prototype.activate=function(){this.active=!0},e.prototype.expand=function(){this.parent&&this.parent.expand(),this.expanded=!0},e.prototype.collapse=function(){\"group\"!==this.type&&(this.expanded=!1)},e.prototype.deactivate=function(){this.active=!1},s([Ne.l],e.prototype,\"active\",void 0),s([Ne.l],e.prototype,\"expanded\",void 0),s([Ne.d],e.prototype,\"activate\",null),s([Ne.d],e.prototype,\"expand\",null),s([Ne.d],e.prototype,\"collapse\",null),s([Ne.d],e.prototype,\"deactivate\",null),e}(),Ct=function(){return function(e,t){var n=t.spec.components&&t.spec.components.securitySchemes||{};this.schemes=Object.keys(e||{}).map(function(r){var o=t.deref(n[r]),i=e[r]||[];if(o)return a({},o,{id:r,sectionId:tt+r,scopes:i});console.warn(\"Non existing security scheme referenced: \"+r+\". Skipping\")}).filter(function(e){return void 0!==e})}}(),Tt=function(){function e(e,t,n,r,o){void 0===o&&(o=!1),this.options=r,this.typePrefix=\"\",this.isCircular=!1,this.activeOneOf=0,this.pointer=t.$ref||n||\"\",this.rawSchema=e.deref(t),this.schema=e.mergeAllOf(this.rawSchema,this.pointer,o),this.init(e,o),e.exitRef(t),e.exitParents(this.schema),r.showExtensions&&(this.extensions=nt(this.schema,r.showExtensions))}return e.prototype.activateOneOf=function(e){this.activeOneOf=e},e.prototype.init=function(t,n){var r=this.schema;if(this.isCircular=r[\"x-circular-ref\"],this.title=r.title||Xe(this.pointer)&&$e.baseName(this.pointer)||\"\",this.description=r.description||\"\",this.type=r.type||function(e){if(void 0!==e.type)return e.type;for(var t=0,n=Object.keys(Qe);t<n.length;t++){var r=n[t],o=Qe[r];if(void 0!==e[r])return o}return\"any\"}(r),this.format=r.format,this.nullable=!!r.nullable,this.enum=r.enum||[],this.example=r.example,this.deprecated=!!r.deprecated,this.pattern=r.pattern,this.externalDocs=r.externalDocs,this.constraints=function(e){var t=[],n=Ke(\"characters\",e.minLength,e.maxLength);void 0!==n&&t.push(n);var r,o=Ke(\"items\",e.minItems,e.maxItems);return void 0!==o&&t.push(o),void 0!==e.minimum&&void 0!==e.maximum?(r=e.exclusiveMinimum?\"( \":\"[ \",r+=e.minimum,r+=\" .. \",r+=e.maximum,r+=e.exclusiveMaximum?\" )\":\" ]\"):void 0!==e.maximum?(r=e.exclusiveMaximum?\"< \":\"<= \",r+=e.maximum):void 0!==e.minimum&&(r=e.exclusiveMinimum?\"> \":\">= \",r+=e.minimum),void 0!==r&&t.push(r),t}(r),this.displayType=this.type,this.displayFormat=this.format,this.isPrimitive=function(e,t){return void 0===t&&(t=e.type),void 0===e.oneOf&&void 0===e.anyOf&&(\"object\"===t?void 0!==e.properties?0===Object.keys(e.properties).length:void 0===e.additionalProperties:\"array\"!==t||void 0===e.items)}(r,this.type),this.default=r.default,this.readOnly=!!r.readOnly,this.writeOnly=!!r.writeOnly,!this.isCircular){if(n||void 0===jt(r))return void 0!==r.oneOf?(this.initOneOf(r.oneOf,t),this.oneOfType=\"One of\",void(void 0!==r.anyOf&&console.warn(\"oneOf and anyOf are not supported on the same level. Skipping anyOf at \"+this.pointer))):void 0!==r.anyOf?(this.initOneOf(r.anyOf,t),void(this.oneOfType=\"Any of\")):void(\"object\"===this.type?this.fields=function(e,t,n,r){var o=t.properties||{},i=t.additionalProperties,s=t.default||{},l=Object.keys(o||[]).map(function(i){var l=o[i];l||(console.warn('Field \"'+i+'\" is invalid, skipping.\\n Field must be an object but got '+typeof l+' at \"'+n+'\"'),l={});var c=void 0!==t.required&&t.required.indexOf(i)>-1;return new It(e,{name:i,required:c,schema:a({},l,{default:void 0===l.default?s[i]:l.default})},n+\"/properties/\"+i,r)});r.sortPropsAlphabetically&&Ze(l,\"name\");r.requiredPropsFirst&&Je(l,r.sortPropsAlphabetically?void 0:t.required);\"object\"!=typeof i&&!0!==i||l.push(new It(e,{name:\"property name *\",required:!1,schema:!0===i?{}:i,kind:\"additionalProperties\"},n+\"/additionalProperties\",r));return l}(t,r,this.pointer,this.options):\"array\"===this.type&&r.items&&(this.items=new e(t,r.items,this.pointer+\"/items\",this.options),this.displayType=this.items.displayType,this.displayFormat=this.items.format,this.typePrefix=this.items.typePrefix+\"Array of \",this.title=this.title||this.items.title,this.isPrimitive=this.items.isPrimitive,void 0===this.example&&void 0!==this.items.example&&(this.example=[this.items.example]),this.items.isPrimitive&&(this.enum=this.items.enum)));this.initDiscriminator(r,t)}},e.prototype.initOneOf=function(t,n){var r=this;this.oneOf=t.map(function(t,o){var i=n.mergeAllOf(t,r.pointer+\"/oneOf/\"+o),s=new e(n,a({},i,{allOf:[a({},r.schema,{oneOf:void 0,anyOf:void 0})]}),r.pointer+\"/oneOf/\"+o,r.options);return n.exitParents(i),s}),this.displayType=this.oneOf.map(function(e){var t=e.typePrefix+(e.title?e.title+\" (\"+e.displayType+\")\":e.displayType);return t.indexOf(\" or \")>-1&&(t=\"(\"+t+\")\"),t}).join(\" or \")},e.prototype.initDiscriminator=function(t,n){var r=this,o=jt(t);this.discriminatorProp=o.propertyName;var i=n.findDerived((t.parentRefs||[]).concat([this.pointer]));if(t.oneOf)for(var a=0,s=t.oneOf;a<s.length;a++){var l=s[a];if(void 0!==l.$ref){var c=$e.dirName(l.$ref);i[l.$ref]=c}}var u=o.mapping||{};for(var p in u)i[u[p]]=p;var f=Object.keys(i);this.oneOf=f.map(function(t){var o=new e(n,n.byRef(t),t,r.options,!0);return o.title=i[t],o})},s([Ne.l],e.prototype,\"activeOneOf\",void 0),s([Ne.d],e.prototype,\"activateOneOf\",null),e}();function jt(e){return e.discriminator||e[\"x-discriminator\"]}var At,It=function(){function e(e,t,n,r){this.expanded=!1;var o=e.deref(t);this.kind=t.kind||\"field\",this.name=t.name||o.name,this.in=o.in,this.required=!!o.required,this.schema=new Tt(e,o.schema||{},n,r),this.description=void 0===o.description?this.schema.description||\"\":o.description,this.example=o.example||this.schema.example,this.deprecated=void 0===o.deprecated?!!this.schema.deprecated:o.deprecated,e.exitRef(t),r.showExtensions&&(this.extensions=nt(o,r.showExtensions))}return e.prototype.toggle=function(){this.expanded=!this.expanded},s([Ne.l],e.prototype,\"expanded\",void 0),s([Ne.d],e.prototype,\"toggle\",null),e}(),Pt=n(80),Rt=function(){return function(e,t){Object.assign(this,e.deref(t)),e.exitRef(t)}}(),Nt=function(){function e(e,t,n,r,o){this.name=t,this.isRequestType=n,this.schema=r.schema&&new Tt(e,r.schema,\"\",o),this.onlyRequiredInSamples=o.onlyRequiredInSamples,void 0!==r.examples?this.examples=function(e,t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=t(e[r],r,e));return n}(r.examples,function(t){return new Rt(e,t)}):void 0!==r.example?this.examples={default:new Rt(e,{value:r.example})}:Ge(t)&&this.generateExample(e,r)}return e.prototype.generateExample=function(e,t){var n={skipReadOnly:this.isRequestType,skipNonRequired:this.isRequestType&&this.onlyRequiredInSamples,skipWriteOnly:!this.isRequestType};if(this.schema&&this.schema.oneOf){this.examples={};for(var r=0,o=this.schema.oneOf;r<o.length;r++){var i=o[r],a=Pt.sample(i.rawSchema,n,e.spec);this.schema.discriminatorProp&&\"object\"==typeof a&&a&&(a[this.schema.discriminatorProp]=i.title),this.examples[i.title]={value:a}}}else this.schema&&(this.examples={default:new Rt(e,{value:Pt.sample(t.schema,n,e.spec)})})},e}(),Lt=function(){function e(e,t,n,r){var o,i;this.parser=e,this.isRequestType=n,this.activeMimeIdx=0,r.unstable_ignoreMimeParameters&&(o=t,i={},Object.keys(o).forEach(function(e){var t=o[e],n=e.split(\";\")[0].trim();i[n]?i[n]=a({},i[n],t):i[n]=t}),t=i),this.mediaTypes=Object.keys(t).map(function(o){var i=t[o];return e.resetVisited(),new Nt(e,o,n,i,r)})}return e.prototype.activate=function(e){this.activeMimeIdx=e},Object.defineProperty(e.prototype,\"active\",{get:function(){return this.mediaTypes[this.activeMimeIdx]},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"hasSample\",{get:function(){return this.mediaTypes.filter(function(e){return!!e.examples}).length>0},enumerable:!0,configurable:!0}),s([Ne.l],e.prototype,\"activeMimeIdx\",void 0),s([Ne.d],e.prototype,\"activate\",null),s([Ne.e],e.prototype,\"active\",null),e}(),Mt=function(){return function(e,t,n){var r=e.deref(t);this.description=r.description||\"\",this.required=!!r.required,e.exitRef(t),void 0!==r.content&&(this.content=new Lt(e,r.content,!0,n))}}(),Dt=function(){function e(e,t,n,r,o){this.headers=[],this.expanded=\"all\"===o.expandResponses||o.expandResponses[t];var i=e.deref(r);e.exitRef(r),this.code=t,void 0!==i.content&&(this.content=new Lt(e,i.content,!1,o)),void 0!==i[\"x-summary\"]?(this.summary=i[\"x-summary\"],this.description=i.description||\"\"):(this.summary=i.description||\"\",this.description=\"\"),this.type=He(t,n);var s=i.headers;void 0!==s&&(this.headers=Object.keys(s).map(function(t){var n=s[t];return new It(e,a({},n,{name:t}),\"\",o)}))}return e.prototype.toggle=function(){this.expanded=!this.expanded},s([Ne.l],e.prototype,\"expanded\",void 0),s([Ne.d],e.prototype,\"toggle\",null),e}(),Ft=function(){function e(e,t,n,r){var o;this.parser=e,this.operationSpec=t,this.options=r,this.type=\"operation\",this.items=[],this.ready=!0,this.active=!1,this.expanded=!1,this.pointer=$e.compile([\"paths\",t.pathName,t.httpVerb]),this.id=void 0!==t.operationId?\"operation/\"+t.operationId:void 0!==n?n.id+this.pointer:this.pointer,this.name=(o=t).summary||o.operationId||o.description&&o.description.substring(0,50)||\"<no summary>\",this.description=t.description,this.parent=n,this.externalDocs=t.externalDocs,this.deprecated=!!t.deprecated,this.httpVerb=t.httpVerb,this.deprecated=!!t.deprecated,this.operationId=t.operationId,this.codeSamples=t[\"x-code-samples\"]||[],this.path=t.pathName;var i=e.byRef($e.compile([\"paths\",t.pathName]));this.servers=et(e.specUrl,t.servers||i&&i.servers||e.spec.servers||[]),this.security=(t.security||e.spec.security||[]).map(function(t){return new Ct(t,e)}),r.showExtensions&&(this.extensions=nt(t,r.showExtensions))}return e.prototype.activate=function(){this.active=!0},e.prototype.deactivate=function(){this.active=!1},e.prototype.expand=function(){this.parent&&this.parent.expand()},e.prototype.collapse=function(){},Object.defineProperty(e.prototype,\"requestBody\",{get:function(){return this.operationSpec.requestBody&&new Mt(this.parser,this.operationSpec.requestBody,this.options)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"parameters\",{get:function(){var e=this,t=function(e,t,n){void 0===t&&(t=[]),void 0===n&&(n=[]);var r={};return n.forEach(function(t){t=e.shalowDeref(t),r[t.name+\"_\"+t.in]=!0}),(t=t.filter(function(t){return t=e.shalowDeref(t),!r[t.name+\"_\"+t.in]})).concat(n)}(this.parser,this.operationSpec.pathParameters,this.operationSpec.parameters).map(function(t){return new It(e.parser,t,e.pointer,e.options)});return this.options.sortPropsAlphabetically&&Ze(t,\"name\"),this.options.requiredPropsFirst&&Je(t),t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"responses\",{get:function(){var e=this,t=!1;return Object.keys(this.operationSpec.responses||[]).filter(function(e){return\"default\"===e||(\"success\"===He(e)&&(t=!0),\"default\"===(n=e)||ce(n)||qe(n));var n}).map(function(n){return new Dt(e.parser,n,t,e.operationSpec.responses[n],e.options)})},enumerable:!0,configurable:!0}),s([Ne.l],e.prototype,\"ready\",void 0),s([Ne.l],e.prototype,\"active\",void 0),s([Ne.l],e.prototype,\"expanded\",void 0),s([Ne.d],e.prototype,\"activate\",null),s([Ne.d],e.prototype,\"deactivate\",null),s([ut],e.prototype,\"requestBody\",null),s([ut],e.prototype,\"parameters\",null),s([ut],e.prototype,\"responses\",null),e}(),Ut=function(){function e(){}return e.buildStructure=function(t,n){var r=t.spec,o=[],i=e.getTagsWithOperations(r);return o.push.apply(o,e.addMarkdownItems(r.info.description||\"\",n)),r[\"x-tagGroups\"]?o.push.apply(o,e.getTagGroupsItems(t,void 0,r[\"x-tagGroups\"],i,n)):o.push.apply(o,e.getTagsItems(t,i,void 0,void 0,n)),o},e.addMarkdownItems=function(e,t){var n=new vt(t).extractHeadings(e||\"\"),r=function(e,t,n){return void 0===n&&(n=1),t.map(function(t){var o,i=new Ot(\"section\",t,e);return i.depth=n,t.items&&(i.items=r(i,t.items,n+1)),vt.containsComponent(i.description||\"\",\"security-definitions\")&&(o=i.id+\"/\",tt=o),i})};return r(void 0,n)},e.getTagGroupsItems=function(t,n,r,o,i){for(var a=[],s=0,l=r;s<l.length;s++){var c=l[s],u=new Ot(\"group\",c,n);u.depth=0,u.items=e.getTagsItems(t,o,u,c,i),a.push(u)}return a},e.getTagsItems=function(e,t,n,r,o){for(var i=[],a=0,s=(void 0===r?Object.keys(t):r.tags).map(function(e){return t[e]?(t[e].used=!0,t[e]):(console.warn('Non-existing tag \"'+e+'\" is added to the group \"'+r.name+'\"'),null)});a<s.length;a++){var l=s[a];if(l){var c=new Ot(\"tag\",l,n);if(c.depth=1,c.items=this.getOperationsItems(e,c,l,c.depth+1,o),\"\"!==l.name)i.push(c);else{var u=this.getOperationsItems(e,void 0,l,c.depth+1,o);i.push.apply(i,u)}}}return i},e.getOperationsItems=function(e,t,n,r,o){if(0===n.operations.length)return[];for(var i=[],a=0,s=n.operations;a<s.length;a++){var l=s[a],c=new Ft(e,l,t,o);c.depth=r,i.push(c)}return i},e.getTagsWithOperations=function(e){for(var t={},n=0,r=e.tags||[];n<r.length;n++){t[(y=r[n]).name]=a({},y,{operations:[]})}for(var o=e.paths,i=0,s=Object.keys(o);i<s.length;i++)for(var l=s[i],c=o[l],u=0,p=Object.keys(c).filter(Ve);u<p.length;u++){var f=p[u],d=c[f],h=d.tags;h&&h.length||(h=[\"\"]);for(var m=0,g=h;m<g.length;m++){var y,v=g[m];void 0===(y=t[v])&&(y={name:v,operations:[]},t[v]=y),y[\"x-traitTag\"]||y.operations.push(a({},d,{pathName:l,httpVerb:f,pathParameters:c.parameters||[]}))}}return t},e}(),Bt=\"data-section-id\",zt=function(){function e(e,t,n){var r,o,i,a,s=this;this.scroll=t,this.history=n,this.activeItemIdx=-1,this.sideBarOpened=!1,this.updateOnScroll=function(e){for(var t=e?1:-1,n=s.activeItemIdx;(-1!==n||e)&&!(n>=s.flatItems.length-1&&e);){if(e){var r=s.getElementAt(n+1);if(s.scroll.isElementBellow(r))break}else{r=s.getElementAt(n);if(s.scroll.isElementAbove(r))break}n+=t}s.activate(s.flatItems[n],!0,!0)},this.updateOnHistory=function(e){var t;(void 0===e&&(e=s.history.currentId),e)&&((t=s.flatItems.find(function(t){return t.id===e}))?s.activateAndScroll(t,!1):(e.startsWith(tt)&&(t=s.flatItems.find(function(e){return tt.startsWith(e.id)}),s.activate(t)),s.scroll.scrollIntoViewBySelector(\"[\"+Bt+'=\"'+e+'\"]')))},this.getItemById=function(e){return s.flatItems.find(function(t){return t.id===e})},this.items=e.contentItems,this.flatItems=(r=this.items||[],o=\"items\",i=[],(a=function(e){for(var t=0,n=e;t<n.length;t++){var r=n[t];i.push(r),r[o]&&a(r[o])}})(r),i),this.flatItems.forEach(function(e,t){return e.absoluteIdx=t}),this.subscribe()}return e.updateOnHistory=function(e,t){void 0===e&&(e=ft.currentId),e&&t.scrollIntoViewBySelector(\"[\"+Bt+'=\"'+e+'\"]')},e.prototype.subscribe=function(){this._unsubscribe=this.scroll.subscribe(this.updateOnScroll),this._hashUnsubscribe=this.history.subscribe(this.updateOnHistory)},e.prototype.toggleSidebar=function(){this.sideBarOpened=!this.sideBarOpened},e.prototype.closeSidebar=function(){this.sideBarOpened=!1},e.prototype.getElementAt=function(e){var t=this.flatItems[e];return t&&re(\"[\"+Bt+'=\"'+t.id+'\"]')||null},Object.defineProperty(e.prototype,\"activeItem\",{get:function(){return this.flatItems[this.activeItemIdx]||void 0},enumerable:!0,configurable:!0}),e.prototype.activate=function(e,t,n){void 0===t&&(t=!0),void 0===n&&(n=!1),(this.activeItem&&this.activeItem.id)!==(e&&e.id)&&(this.deactivate(this.activeItem),e?e.depth<=0||(this.activeItemIdx=e.absoluteIdx,t&&this.history.replace(e.id,n),e.activate(),e.expand()):this.history.replace(\"\",n))},e.prototype.deactivate=function(e){if(void 0!==e)for(e.deactivate();void 0!==e;)e.collapse(),e=e.parent},e.prototype.activateAndScroll=function(e,t,n){var r=e&&this.getItemById(e.id)||e;this.activate(r,t,n),this.scrollToActive(),r&&r.items.length||this.closeSidebar()},e.prototype.scrollToActive=function(){this.scroll.scrollIntoView(this.getElementAt(this.activeItemIdx))},e.prototype.dispose=function(){this._unsubscribe(),this._hashUnsubscribe()},s([Ne.l],e.prototype,\"activeItemIdx\",void 0),s([Ne.l],e.prototype,\"sideBarOpened\",void 0),s([Ne.d],e.prototype,\"toggleSidebar\",null),s([Ne.d],e.prototype,\"closeSidebar\",null),s([Ne.d],e.prototype,\"activate\",null),s([Ne.d.bound],e.prototype,\"activateAndScroll\",null),e}(),$t=function(){function e(e){this.options=e,this._prevOffsetY=0,this._scrollParent=ne?window:void 0,this._emiter=new Ue,this.bind()}return e.prototype.bind=function(){this._prevOffsetY=this.scrollY(),this._scrollParent&&this._scrollParent.addEventListener(\"scroll\",this.handleScroll)},e.prototype.dispose=function(){this._scrollParent&&this._scrollParent.removeEventListener(\"scroll\",this.handleScroll),this._emiter.removeAllListeners(\"scroll\")},e.prototype.scrollY=function(){return\"undefined\"!=typeof HTMLElement&&this._scrollParent instanceof HTMLElement?this._scrollParent.scrollTop:void 0!==this._scrollParent?this._scrollParent.pageYOffset:0},e.prototype.isElementBellow=function(e){if(null!==e)return e.getBoundingClientRect().top>this.options.scrollYOffset()},e.prototype.isElementAbove=function(e){if(null!==e){var t=e.getBoundingClientRect().top;return(t>0?Math.floor(t):Math.ceil(t))<=this.options.scrollYOffset()}},e.prototype.subscribe=function(e){var t=this._emiter.addListener(\"scroll\",e);return function(){return t.removeListener(\"scroll\",e)}},e.prototype.scrollIntoView=function(e){null!==e&&(e.scrollIntoView(),this._scrollParent&&this._scrollParent.scrollBy&&this._scrollParent.scrollBy(0,1-this.options.scrollYOffset()))},e.prototype.scrollIntoViewBySelector=function(e){var t=re(e);this.scrollIntoView(t)},e.prototype.handleScroll=function(){var e=this.scrollY()-this._prevOffsetY>0;this._prevOffsetY=this.scrollY(),this._emiter.emit(\"scroll\",e)},s([Fe.bind,at(100)],e.prototype,\"handleScroll\",null),e}();if(ne)try{At=n(266)}catch(e){At=n(124).default}else At=n(124).default;var Wt,qt,Ht,Yt,Vt=function(){function e(){this.searchWorker=new At}return e.prototype.indexItems=function(e){var t=this,n=function(e){e.forEach(function(e){\"group\"!==e.type&&t.add(e.name,e.description||\"\",e.id),n(e.items)})};n(e),this.searchWorker.done()},e.prototype.add=function(e,t,n){this.searchWorker.add(e,t,n)},e.prototype.search=function(e){return this.searchWorker.search(e)},e.prototype.toJS=function(){return l(this,void 0,void 0,function(){return c(this,function(e){return[2,this.searchWorker.toJS()]})})},e.prototype.load=function(e){this.searchWorker.load(e)},e}(),Qt=Ee.div.withConfig({componentId:\"sc-6itmo6-0\"})([\"width:calc(100% - \",\");padding:0 \",\"px;\",\";\"],function(e){return e.theme.rightPanel.width},function(e){return e.theme.spacing.sectionHorizontal},ke(\"medium\",!0)(Wt||(Wt=u([\"\\n    width: 100%;\\n    padding: \",\";\\n  \"],[\"\\n    width: 100%;\\n    padding: \",\";\\n  \"])),function(e){return e.theme.spacing.sectionVertical+\"px \"+e.theme.spacing.sectionHorizontal+\"px\"})),Gt=Ee.div.attrs(function(e){var t;return(t={})[Bt]=e.id,t}).withConfig({componentId:\"sc-6itmo6-1\"})([\"padding:\",\"px 0;\",\" \",\"\"],function(e){return e.theme.spacing.sectionVertical},ke(\"medium\",!0)(qt||(qt=u([\"\\n    padding: 0;\\n  \"],[\"\\n    padding: 0;\\n  \"]))),function(e){return e.underlined?\"\\n    position: relative;\\n\\n    &:not(:last-of-type):after {\\n      position: absolute;\\n      bottom: 0;\\n      width: 100%;\\n      display: block;\\n      content: '';\\n      border-bottom: 1px solid rgba(0, 0, 0, 0.2);\\n    }\\n  \":\"\"}),Xt=Ee.div.withConfig({componentId:\"sc-6itmo6-2\"})([\"width:\",\";color:\",\";background-color:\",\";padding:0 \",\"px;\",\";\"],function(e){return e.theme.rightPanel.width},function(e){return e.theme.rightPanel.textColor},function(e){return e.theme.rightPanel.backgroundColor},function(e){return e.theme.spacing.sectionHorizontal},ke(\"medium\",!0)(Ht||(Ht=u([\"\\n    width: 100%;\\n    padding: \",\";\\n  \"],[\"\\n    width: 100%;\\n    padding: \",\";\\n  \"])),function(e){return e.theme.spacing.sectionVertical+\"px \"+e.theme.spacing.sectionHorizontal+\"px\"})),Kt=Ee(Xt).withConfig({componentId:\"sc-6itmo6-3\"})([\"background-color:\",\";\"],function(e){return e.theme.rightPanel.backgroundColor}),Jt=Ee.div.withConfig({componentId:\"sc-6itmo6-4\"})([\"display:flex;width:100%;padding:0;\",\";\"],ke(\"medium\",!0)(Yt||(Yt=u([\"\\n    flex-direction: column;\\n  \"],[\"\\n    flex-direction: column;\\n  \"])))),Zt={1:\"1.85714em\",2:\"1.57143em\",3:\"1.27em\"},en=function(e){return ve([\"font-family:\",\";font-weight:\",\";font-size:\",\";\"],function(e){return e.theme.typography.headings.fontFamily},function(e){return e.theme.typography.headings.fontWeight},Zt[e])},tn=Ee.h1.withConfig({componentId:\"shv3r-0\"})([\"\",\";color:\",\";\",\";\"],en(1),function(e){return e.theme.colors.primary.main},Se(\"H1\")),nn=Ee.h2.withConfig({componentId:\"shv3r-1\"})([\"\",\";color:black;\",\";\"],en(2),Se(\"H2\")),rn=(Ee.h2.withConfig({componentId:\"shv3r-2\"})([\"\",\";color:black;\",\";\"],en(3),Se(\"H3\")),Ee.h3.withConfig({componentId:\"shv3r-3\"})([\"color:\",\";\",\";\"],function(e){return e.theme.rightPanel.textColor},Se(\"RightPanelHeader\"))),on=Ee.h5.withConfig({componentId:\"shv3r-4\"})([\"border-bottom:1px solid rgba(38,50,56,0.3);margin:1em 0 1em 0;color:rgba(38,50,56,0.5);font-weight:normal;text-transform:uppercase;font-size:0.929em;line-height:20px;\",\";\"],Se(\"UnderlinedHeader\")),an=n(39),sn=Object(p.createContext)(void 0),ln=sn.Provider,cn=sn.Consumer,un=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.state={loading:!0,resolvedSpec:null},t}return i(t,e),t.getDerivedStateFromProps=function(e,t){return e.specUrl!==t.prevSpecUrl||e.spec!==t.prevSpec?{loading:!0,resolvedSpec:null,prevSpec:e.spec,prevSpecUrl:e.specUrl}:null},t.prototype.makeStore=function(e,t,n){if(e)try{return new eo(e,t,n)}catch(e){throw this.props.onLoaded&&this.props.onLoaded(e),e}},t.prototype.componentDidMount=function(){this.load()},t.prototype.componentDidUpdate=function(){null===this.state.resolvedSpec?this.load():!this.state.loading&&this.props.onLoaded&&this.props.onLoaded()},t.prototype.load=function(){return l(this,void 0,void 0,function(){var e,t,n,r,o;return c(this,function(i){switch(i.label){case 0:e=this.props,t=e.specUrl,n=e.spec,i.label=1;case 1:return i.trys.push([1,3,,4]),[4,De(n||t)];case 2:return r=i.sent(),this.setState({resolvedSpec:r,loading:!1}),[3,4];case 3:return o=i.sent(),this.props.onLoaded&&this.props.onLoaded(o),this.setState({error:o}),[3,4];case 4:return[2]}})})},t.prototype.render=function(){if(this.state.error)throw this.state.error;var e=this.props,t=e.specUrl,n=e.options,r=this.state,o=r.loading,i=r.resolvedSpec;return this.props.children({loading:o,store:this.makeStore(i,t,n)})},s([an.a],t.prototype,\"makeStore\",null),t}(p.Component),pn=function(e){return ve([\"\",\"{cursor:pointer;margin-left:-20px;padding:0;line-height:1;width:20px;display:inline-block;}\",\":before{content:'';width:15px;height:15px;background-size:contain;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSIjMDEwMTAxIiBkPSJNNDU5LjcgMjMzLjRsLTkwLjUgOTAuNWMtNTAgNTAtMTMxIDUwLTE4MSAwIC03LjktNy44LTE0LTE2LjctMTkuNC0yNS44bDQyLjEtNDIuMWMyLTIgNC41LTMuMiA2LjgtNC41IDIuOSA5LjkgOCAxOS4zIDE1LjggMjcuMiAyNSAyNSA2NS42IDI0LjkgOTAuNSAwbDkwLjUtOTAuNWMyNS0yNSAyNS02NS42IDAtOTAuNSAtMjQuOS0yNS02NS41LTI1LTkwLjUgMGwtMzIuMiAzMi4yYy0yNi4xLTEwLjItNTQuMi0xMi45LTgxLjYtOC45bDY4LjYtNjguNmM1MC01MCAxMzEtNTAgMTgxIDBDNTA5LjYgMTAyLjMgNTA5LjYgMTgzLjQgNDU5LjcgMjMzLjR6TTIyMC4zIDM4Mi4ybC0zMi4yIDMyLjJjLTI1IDI0LjktNjUuNiAyNC45LTkwLjUgMCAtMjUtMjUtMjUtNjUuNiAwLTkwLjVsOTAuNS05MC41YzI1LTI1IDY1LjUtMjUgOTAuNSAwIDcuOCA3LjggMTIuOSAxNy4yIDE1LjggMjcuMSAyLjQtMS40IDQuOC0yLjUgNi44LTQuNWw0Mi4xLTQyYy01LjQtOS4yLTExLjYtMTgtMTkuNC0yNS44IC01MC01MC0xMzEtNTAtMTgxIDBsLTkwLjUgOTAuNWMtNTAgNTAtNTAgMTMxIDAgMTgxIDUwIDUwIDEzMSA1MCAxODEgMGw2OC42LTY4LjZDMjc0LjYgMzk1LjEgMjQ2LjQgMzkyLjMgMjIwLjMgMzgyLjJ6Ii8+PC9zdmc+Cg==');opacity:0.5;visibility:hidden;display:inline-block;vertical-align:middle;}h1:hover > \",\"::before,h2:hover > \",\"::before,\",\":hover::before{visibility:visible;}\"],e,e,e,e,e)},fn=function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)},dn=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.navigate=function(e,n){n.defaultPrevented||0!==n.button||fn(n)||(n.preventDefault(),e.replace(t.props.to))},t}return i(t,e),t.prototype.render=function(){var e=this;return p.createElement(cn,null,function(t){return p.createElement(\"a\",{className:e.props.className,href:t.menu.history.linkForId(e.props.to),onClick:e.navigate.bind(e,t.menu.history)},e.props.children)})},t}(p.Component),hn=Ee(dn).withConfig({componentId:\"eb0njo-0\"})([\"\",\";\"],pn(\"&\"));function mn(e){return p.createElement(hn,{to:e.to})}var gn={left:\"90deg\",right:\"-90deg\",up:\"-180deg\",down:\"0\"},yn=Ee(function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return p.createElement(\"svg\",{className:this.props.className,style:this.props.style,version:\"1.1\",viewBox:\"0 0 24 24\",x:\"0\",xmlns:\"http://www.w3.org/2000/svg\",y:\"0\"},p.createElement(\"polygon\",{points:\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"}))},t}(p.PureComponent)).withConfig({componentId:\"sc-1g5rdgs-0\"})([\"height:\",\";width:\",\";vertical-align:middle;float:\",\";transition:transform 0.2s ease-out;transform:rotateZ(\",\");polygon{fill:\",\";}\"],function(e){return e.size||\"18px\"},function(e){return e.size||\"18px\"},function(e){return e.float||\"\"},function(e){return gn[e.direction||\"down\"]},function(e){return e.color&&e.theme.colors[e.color]&&e.theme.colors[e.color].main||e.color}),vn=Ee.span.withConfig({componentId:\"sc-1g5rdgs-1\"})([\"display:inline-block;padding:0 5px;margin:0;background-color:\",\";color:\",\";font-size:\",\";vertical-align:text-top;\"],function(e){return e.theme.colors[e.type].main},function(e){return e.theme.colors[e.type].contrastText},function(e){return e.theme.typography.code.fontSize}),bn=ve([\"text-decoration:line-through;color:#bdccd3;\"]),wn=Ee.caption.withConfig({componentId:\"dz44d2-0\"})([\"text-align:right;font-size:0.9em;font-weight:normal;color:\",\";\"],function(e){return e.theme.colors.text.secondary}),xn=Ee.td.withConfig({componentId:\"dz44d2-1\"})([\"border-left:1px solid \",\";box-sizing:border-box;position:relative;padding:10px 10px 10px 0;tr:first-of-type > &,tr.last > &{border-left-width:0;background-position:top left;background-repeat:no-repeat;background-size:1px 100%;}tr:first-of-type > &{background-image:linear-gradient( to bottom,transparent 0%,transparent 22px,\",\" 22px,\",\" 100% );}tr.last > &{background-image:linear-gradient( to bottom,\",\" 0%,\",\" 22px,transparent 22px,transparent 100% );}tr.last + tr > &{border-left-color:transparent;}tr.last:first-child > &{background:none;border-left-color:transparent;}\"],function(e){return e.theme.schema.linesColor},function(e){return e.theme.schema.linesColor},function(e){return e.theme.schema.linesColor},function(e){return e.theme.schema.linesColor},function(e){return e.theme.schema.linesColor}),kn=Ee(xn).withConfig({componentId:\"dz44d2-2\"})([\"padding:0;\"]),En=Ee(xn).withConfig({componentId:\"dz44d2-3\"})([\"vertical-align:top;line-height:20px;white-space:nowrap;font-size:0.929em;font-family:\",\";&.deprecated{\",\";}\",\";\",\";\"],function(e){return e.theme.typography.headings.fontFamily},bn,function(e){return\"field\"!==e.kind?\"font-style: italic\":\"\"},Se(\"PropertyNameCell\")),Sn=Ee.td.withConfig({componentId:\"dz44d2-4\"})([\"border-bottom:1px solid #9fb4be;padding:10px 0;width:\",\";box-sizing:border-box;tr.expanded &{border-bottom:none;}\"],function(e){return e.theme.schema.defaultDetailsWidth}),_n=Ee.span.withConfig({componentId:\"dz44d2-5\"})([\"color:\",\";font-family:\",\";margin-right:10px;&::before{content:'';display:inline-block;vertical-align:middle;width:10px;height:1px;background:\",\";}&::after{content:'';display:inline-block;vertical-align:middle;width:1px;background:\",\";height:7px;}\"],function(e){return e.theme.schema.linesColor},function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.schema.linesColor},function(e){return e.theme.schema.linesColor}),On=Ee.div.withConfig({componentId:\"dz44d2-6\"})([\"padding:\",\";\"],function(e){return e.theme.schema.nestingSpacing}),Cn=Ee.table.withConfig({componentId:\"dz44d2-7\"})([\"border-collapse:separate;border-radius:3px;font-size:\",\";border-spacing:0;width:100%;> tr{vertical-align:middle;}& \",\",& \",\" \",\" \",\",& \",\" \",\" \",\" \",\" \",\"{margin:\",\";margin-right:0;background:\",\";}& \",\" \",\",& \",\" \",\" \",\" \",\",& \",\" \",\" \",\" \",\" \",\" \",\"{background:#ffffff;}\"],function(e){return e.theme.typography.fontSize},On,On,On,On,On,On,On,On,On,function(e){return e.theme.schema.nestingSpacing},function(e){return e.theme.schema.nestedBackground},On,On,On,On,On,On,On,On,On,On,On,On),Tn=Ee.ul.withConfig({componentId:\"y3ai9j-0\"})([\"margin:0 0 3px 0;padding:0;list-style:none;display:inline-block;\"]),jn=Ee.span.withConfig({componentId:\"y3ai9j-1\"})([\"font-size:0.9em;margin-right:10px;color:\",\";font-family:Montserrat;}\"],function(e){return e.theme.colors.primary.main}),An=Ee.li.withConfig({componentId:\"y3ai9j-2\"})([\"display:inline-block;margin-right:10px;font-size:0.8em;cursor:pointer;border:1px solid \",\";padding:2px 10px;\",\"\"],function(e){return e.theme.colors.primary.main},function(e){return e.active?\"\\n      color: white;\\n      background-color: \"+e.theme.colors.primary.main+\";\\n      \":\"\\n        color: \"+e.theme.colors.primary.main+\";\\n        background-color: white;\\n      \"}),In=Ee.div.withConfig({componentId:\"y3ai9j-3\"})([\"font-size:0.9em;font-family:\",\";&::after{content:' [';}\"],function(e){return e.theme.typography.code.fontFamily}),Pn=Ee.div.withConfig({componentId:\"y3ai9j-4\"})([\"font-size:0.9em;font-family:\",\";&::after{content:']';}\"],function(e){return e.theme.typography.code.fontFamily}),Rn=n(131),Nn=Ee(n.n(Rn).a).withConfig({componentId:\"sc-1c2fwzw-0\"})([\"min-width:100px;display:inline-block;position:relative;width:auto;font-family:\",\";.Dropdown-control{font-family:\",\";position:relative;font-size:0.929em;width:100%;line-height:1.5em;vertical-align:middle;cursor:pointer;border-color:rgba(38,50,56,0.5);color:#263238;outline:none;padding:0.15em 1.5em 0.2em 0.5em;border-radius:2px;border-width:1px;border-style:solid;margin-top:5px;background:white;box-sizing:border-box;&:hover{border-color:\",\";color:\",\";box-shadow:0px 2px 4px 0px rgba(34,36,38,0.12);}}.Dropdown-arrow{border-color:\",\" transparent transparent;border-style:solid;border-width:0.35em 0.35em 0;content:' ';display:block;height:0;position:absolute;right:0.35em;top:50%;margin-top:-0.125em;width:0;}.Dropdown-menu{position:absolute;margin-top:2px;left:0;right:0;z-index:10;min-width:100px;background:white;border:1px solid rgba(38,50,56,0.2);box-shadow:0px 2px 4px 0px rgba(34,36,38,0.12),0px 2px 10px 0px rgba(34,36,38,0.08);max-height:220px;overflow:auto;}.Dropdown-option{font-size:0.9em;color:#263238;cursor:pointer;padding:0.4em;&.is-selected{background-color:rgba(0,0,0,0.05);}&:hover{background-color:rgba(38,50,56,0.12);}}\"],function(e){return e.theme.typography.headings.fontFamily},function(e){return e.theme.typography.headings.fontFamily},function(e){return e.theme.colors.primary.main},function(e){return e.theme.colors.primary.main},function(e){return e.theme.colors.primary.main}),Ln=Ee(Nn).withConfig({componentId:\"sc-1c2fwzw-1\"})([\"margin-left:10px;text-transform:none;font-size:0.929em;.Dropdown-control{font-size:1em;border:none;padding:0 1.2em 0 0;background:transparent;&:hover{color:\",\";box-shadow:none;}}\"],function(e){return e.theme.colors.primary.main}),Mn=Ee.span.withConfig({componentId:\"sc-1c2fwzw-2\"})([\"margin-left:10px;text-transform:none;font-size:0.929em;color:black;\"]);function Dn(e){return e.type&&\"Tab\"===e.type.tabsRole}function Fn(e){return e.type&&\"TabPanel\"===e.type.tabsRole}function Un(e){return e.type&&\"TabList\"===e.type.tabsRole}function Bn(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function zn(e,t){return p.Children.map(e,function(e){return null===e?null:function(e){return Dn(e)||Un(e)||Fn(e)}(e)?t(e):e.props&&e.props.children&&\"object\"==typeof e.props.children?Object(p.cloneElement)(e,function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);\"function\"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){Bn(e,t,n[t])})}return e}({},e.props,{children:zn(e.props.children,t)})):e})}function $n(e,t){return p.Children.forEach(e,function(e){null!==e&&(Dn(e)||Fn(e)?t(e):e.props&&e.props.children&&\"object\"==typeof e.props.children&&(Un(e)&&t(e),$n(e.props.children,t)))})}var Wn,qn=n(12),Hn=n.n(qn),Yn=0;function Vn(){return\"react-tabs-\"+Yn++}function Qn(e){var t=0;return $n(e,function(e){Dn(e)&&t++}),t}function Gn(){return(Gn=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function Xn(e){return\"getAttribute\"in e&&\"tab\"===e.getAttribute(\"role\")}function Kn(e){return\"true\"===e.getAttribute(\"aria-disabled\")}try{Wn=!(\"undefined\"==typeof window||!window.document||!window.document.activeElement)}catch(e){Wn=!1}var Jn=function(e){var t,n;function r(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).tabNodes=[],t.handleKeyDown=function(e){if(t.isTabFromContainer(e.target)){var n=t.props.selectedIndex,r=!1,o=!1;32!==e.keyCode&&13!==e.keyCode||(r=!0,o=!1,t.handleClick(e)),37===e.keyCode||38===e.keyCode?(n=t.getPrevTab(n),r=!0,o=!0):39===e.keyCode||40===e.keyCode?(n=t.getNextTab(n),r=!0,o=!0):35===e.keyCode?(n=t.getLastTab(),r=!0,o=!0):36===e.keyCode&&(n=t.getFirstTab(),r=!0,o=!0),r&&e.preventDefault(),o&&t.setSelected(n,e)}},t.handleClick=function(e){var n=e.target;do{if(t.isTabFromContainer(n)){if(Kn(n))return;var r=[].slice.call(n.parentNode.children).filter(Xn).indexOf(n);return void t.setSelected(r,e)}}while(null!==(n=n.parentNode))},t}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var o=r.prototype;return o.setSelected=function(e,t){if(!(e<0||e>=this.getTabsCount())){var n=this.props;(0,n.onSelect)(e,n.selectedIndex,t)}},o.getNextTab=function(e){for(var t=this.getTabsCount(),n=e+1;n<t;n++)if(!Kn(this.getTab(n)))return n;for(var r=0;r<e;r++)if(!Kn(this.getTab(r)))return r;return e},o.getPrevTab=function(e){for(var t=e;t--;)if(!Kn(this.getTab(t)))return t;for(t=this.getTabsCount();t-- >e;)if(!Kn(this.getTab(t)))return t;return e},o.getFirstTab=function(){for(var e=this.getTabsCount(),t=0;t<e;t++)if(!Kn(this.getTab(t)))return t;return null},o.getLastTab=function(){for(var e=this.getTabsCount();e--;)if(!Kn(this.getTab(e)))return e;return null},o.getTabsCount=function(){return Qn(this.props.children)},o.getPanelsCount=function(){return function(e){var t=0;return $n(e,function(e){Fn(e)&&t++}),t}(this.props.children)},o.getTab=function(e){return this.tabNodes[\"tabs-\"+e]},o.getChildren=function(){var e=this,t=0,n=this.props,r=n.children,o=n.disabledTabClassName,i=n.focus,a=n.forceRenderTabPanel,s=n.selectedIndex,l=n.selectedTabClassName,c=n.selectedTabPanelClassName;this.tabIds=this.tabIds||[],this.panelIds=this.panelIds||[];for(var u=this.tabIds.length-this.getTabsCount();u++<0;)this.tabIds.push(Vn()),this.panelIds.push(Vn());return zn(r,function(n){var r=n;if(Un(n)){var u=0,d=!1;Wn&&(d=f.a.Children.toArray(n.props.children).filter(Dn).some(function(t,n){return document.activeElement===e.getTab(n)})),r=Object(p.cloneElement)(n,{children:zn(n.props.children,function(t){var n=\"tabs-\"+u,r=s===u,a={tabRef:function(t){e.tabNodes[n]=t},id:e.tabIds[u],panelId:e.panelIds[u],selected:r,focus:r&&(i||d)};return l&&(a.selectedClassName=l),o&&(a.disabledClassName=o),u++,Object(p.cloneElement)(t,a)})})}else if(Fn(n)){var h={id:e.panelIds[t],tabId:e.tabIds[t],selected:s===t};a&&(h.forceRender=a),c&&(h.selectedClassName=c),t++,r=Object(p.cloneElement)(n,h)}return r})},o.isTabFromContainer=function(e){if(!Xn(e))return!1;var t=e.parentElement;do{if(t===this.node)return!0;if(t.getAttribute(\"data-tabs\"))break;t=t.parentElement}while(t);return!1},o.render=function(){var e=this,t=this.props,n=(t.children,t.className),r=(t.disabledTabClassName,t.domRef),o=(t.focus,t.forceRenderTabPanel,t.onSelect,t.selectedIndex,t.selectedTabClassName,t.selectedTabPanelClassName,function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(t,[\"children\",\"className\",\"disabledTabClassName\",\"domRef\",\"focus\",\"forceRenderTabPanel\",\"onSelect\",\"selectedIndex\",\"selectedTabClassName\",\"selectedTabPanelClassName\"]));return f.a.createElement(\"div\",Gn({},o,{className:Hn()(n),onClick:this.handleClick,onKeyDown:this.handleKeyDown,ref:function(t){e.node=t,r&&r(t)},\"data-tabs\":!0}),this.getChildren())},r}(p.Component);Jn.defaultProps={className:\"react-tabs\",focus:!1},Jn.propTypes={};var Zn=function(e){var t,n;function r(t){var n;return(n=e.call(this,t)||this).handleSelected=function(e,t,o){var i=n.props.onSelect;if(\"function\"!=typeof i||!1!==i(e,t,o)){var a={focus:\"keydown\"===o.type};r.inUncontrolledMode(n.props)&&(a.selectedIndex=e),n.setState(a)}},n.state=r.copyPropsToState(n.props,{},t.defaultFocus),n}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var o=r.prototype;return o.componentWillReceiveProps=function(e){this.setState(function(t){return r.copyPropsToState(e,t)})},r.inUncontrolledMode=function(e){return null===e.selectedIndex},r.copyPropsToState=function(e,t,n){void 0===n&&(n=!1);var o={focus:n};if(r.inUncontrolledMode(e)){var i=Qn(e.children)-1,a=null;a=null!=t.selectedIndex?Math.min(t.selectedIndex,i):e.defaultIndex||0,o.selectedIndex=a}return o},o.render=function(){var e=this.props,t=e.children,n=(e.defaultIndex,e.defaultFocus,function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,[\"children\",\"defaultIndex\",\"defaultFocus\"])),r=this.state,o=r.focus,i=r.selectedIndex;return n.focus=o,n.onSelect=this.handleSelected,null!=i&&(n.selectedIndex=i),f.a.createElement(Jn,n,t)},r}(p.Component);function er(){return(er=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}Zn.defaultProps={defaultFocus:!1,forceRenderTabPanel:!1,selectedIndex:null,defaultIndex:null},Zn.propTypes={},Zn.tabsRole=\"Tabs\";var tr=function(e){var t,n;function r(){return e.apply(this,arguments)||this}return n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,r.prototype.render=function(){var e=this.props,t=e.children,n=e.className,r=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,[\"children\",\"className\"]);return f.a.createElement(\"ul\",er({},r,{className:Hn()(n),role:\"tablist\"}),t)},r}(p.Component);function nr(){return(nr=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}tr.defaultProps={className:\"react-tabs__tab-list\"},tr.propTypes={},tr.tabsRole=\"TabList\";var rr=function(e){var t,n;function r(){return e.apply(this,arguments)||this}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var o=r.prototype;return o.componentDidMount=function(){this.checkFocus()},o.componentDidUpdate=function(){this.checkFocus()},o.checkFocus=function(){var e=this.props,t=e.selected,n=e.focus;t&&n&&this.node.focus()},o.render=function(){var e,t=this,n=this.props,r=n.children,o=n.className,i=n.disabled,a=n.disabledClassName,s=(n.focus,n.id),l=n.panelId,c=n.selected,u=n.selectedClassName,p=n.tabIndex,d=n.tabRef,h=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(n,[\"children\",\"className\",\"disabled\",\"disabledClassName\",\"focus\",\"id\",\"panelId\",\"selected\",\"selectedClassName\",\"tabIndex\",\"tabRef\"]);return f.a.createElement(\"li\",nr({},h,{className:Hn()(o,(e={},e[u]=c,e[a]=i,e)),ref:function(e){t.node=e,d&&d(e)},role:\"tab\",id:s,\"aria-selected\":c?\"true\":\"false\",\"aria-disabled\":i?\"true\":\"false\",\"aria-controls\":l,tabIndex:p||(c?\"0\":null)}),r)},r}(p.Component);function or(){return(or=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}rr.defaultProps={className:\"react-tabs__tab\",disabledClassName:\"react-tabs__tab--disabled\",focus:!1,id:null,panelId:null,selected:!1,selectedClassName:\"react-tabs__tab--selected\"},rr.propTypes={},rr.tabsRole=\"Tab\";var ir=function(e){var t,n;function r(){return e.apply(this,arguments)||this}return n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,r.prototype.render=function(){var e,t=this.props,n=t.children,r=t.className,o=t.forceRender,i=t.id,a=t.selected,s=t.selectedClassName,l=t.tabId,c=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(t,[\"children\",\"className\",\"forceRender\",\"id\",\"selected\",\"selectedClassName\",\"tabId\"]);return f.a.createElement(\"div\",or({},c,{className:Hn()(r,(e={},e[s]=a,e)),role:\"tabpanel\",id:i,\"aria-labelledby\":l}),o||a?n:null)},r}(p.Component);ir.defaultProps={className:\"react-tabs__tab-panel\",forceRender:!1,selectedClassName:\"react-tabs__tab-panel--selected\"},ir.propTypes={},ir.tabsRole=\"TabPanel\";var ar=Ee(Zn).withConfig({componentId:\"sc-1vrf7wa-0\"})([\"> ul{list-style:none;padding:0;margin:0;margin:0 -5px;> li{padding:5px 10px;display:inline-block;background-color:\",\";border-bottom:1px solid rgba(0,0,0,0.5);cursor:pointer;text-align:center;outline:none;color:\",\";margin:5px;border:1px solid \",\";border-radius:5px;min-width:60px;font-size:0.9em;font-weight:bold;&.react-tabs__tab--selected{color:\",\";background:\",\";}&:only-child{flex:none;min-width:100px;}&.tab-success{color:\",\";}&.tab-redirect{color:\",\";}&.tab-info{color:\",\";}&.tab-error{color:\",\";}}}> .react-tabs__tab-panel{background:\",\";& > div,& > pre{padding:20px;margin:0;}}\"],function(e){var t=e.theme;return Y(.05,t.rightPanel.backgroundColor)},function(e){var t=e.theme;return Y(t.colors.tonalOffset,t.rightPanel.textColor)},function(e){var t=e.theme;return Y(.1,t.rightPanel.backgroundColor)},function(e){return e.theme.colors.text.primary},function(e){return e.theme.rightPanel.textColor},function(e){return e.theme.colors.responses.success.color},function(e){return e.theme.colors.responses.redirect.color},function(e){return e.theme.colors.responses.info.color},function(e){return e.theme.colors.responses.error.color},function(e){return e.theme.codeSample.backgroundColor}),sr=Ee(ar).withConfig({componentId:\"sc-1vrf7wa-1\"})([\"> ul{display:block;> li{padding:2px 5px;min-width:auto;margin:0 15px 0 0;font-size:13px;font-weight:normal;border-bottom:1px dashed;color:\",\";border-radius:0;background:none;&:last-child{margin-right:0;}&.react-tabs__tab--selected{color:\",\";background:none;}}}> .react-tabs__tab-panel{& > div,& > pre{padding:10px 0;margin:0;}}\"],function(e){var t=e.theme;return Y(t.colors.tonalOffset,t.rightPanel.textColor)},function(e){return e.theme.rightPanel.textColor}),lr=Ee.div.withConfig({componentId:\"sc-1rd7dj7-0\"})([\"opacity:0.4;transition:opacity 0.3s ease;text-align:right;> span{display:inline-block;padding:2px 10px;cursor:pointer;:hover{background:rgba(255,255,255,0.1);}}\"]),cr=Ee.div.withConfig({componentId:\"sc-1rd7dj7-1\"})([\"&:hover \",\"{opacity:1;}\"],lr);\n/*!\n * perfect-scrollbar v1.4.0\n * (c) 2018 Hyunje Jun\n * @license MIT\n */\nfunction ur(e){return getComputedStyle(e)}function pr(e,t){for(var n in t){var r=t[n];\"number\"==typeof r&&(r+=\"px\"),e.style[n]=r}return e}function fr(e){var t=document.createElement(\"div\");return t.className=e,t}var dr=\"undefined\"!=typeof Element&&(Element.prototype.matches||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector);function hr(e,t){if(!dr)throw new Error(\"No element matching method supported\");return dr.call(e,t)}function mr(e){e.remove?e.remove():e.parentNode&&e.parentNode.removeChild(e)}function gr(e,t){return Array.prototype.filter.call(e.children,function(e){return hr(e,t)})}var yr={main:\"ps\",element:{thumb:function(e){return\"ps__thumb-\"+e},rail:function(e){return\"ps__rail-\"+e},consuming:\"ps__child--consume\"},state:{focus:\"ps--focus\",clicking:\"ps--clicking\",active:function(e){return\"ps--active-\"+e},scrolling:function(e){return\"ps--scrolling-\"+e}}},vr={x:null,y:null};function br(e,t){var n=e.element.classList,r=yr.state.scrolling(t);n.contains(r)?clearTimeout(vr[t]):n.add(r)}function wr(e,t){vr[t]=setTimeout(function(){return e.isAlive&&e.element.classList.remove(yr.state.scrolling(t))},e.settings.scrollingThreshold)}var xr=function(e){this.element=e,this.handlers={}},kr={isEmpty:{configurable:!0}};xr.prototype.bind=function(e,t){void 0===this.handlers[e]&&(this.handlers[e]=[]),this.handlers[e].push(t),this.element.addEventListener(e,t,!1)},xr.prototype.unbind=function(e,t){var n=this;this.handlers[e]=this.handlers[e].filter(function(r){return!(!t||r===t)||(n.element.removeEventListener(e,r,!1),!1)})},xr.prototype.unbindAll=function(){for(var e in this.handlers)this.unbind(e)},kr.isEmpty.get=function(){var e=this;return Object.keys(this.handlers).every(function(t){return 0===e.handlers[t].length})},Object.defineProperties(xr.prototype,kr);var Er=function(){this.eventElements=[]};function Sr(e){if(\"function\"==typeof window.CustomEvent)return new CustomEvent(e);var t=document.createEvent(\"CustomEvent\");return t.initCustomEvent(e,!1,!1,void 0),t}Er.prototype.eventElement=function(e){var t=this.eventElements.filter(function(t){return t.element===e})[0];return t||(t=new xr(e),this.eventElements.push(t)),t},Er.prototype.bind=function(e,t,n){this.eventElement(e).bind(t,n)},Er.prototype.unbind=function(e,t,n){var r=this.eventElement(e);r.unbind(t,n),r.isEmpty&&this.eventElements.splice(this.eventElements.indexOf(r),1)},Er.prototype.unbindAll=function(){this.eventElements.forEach(function(e){return e.unbindAll()}),this.eventElements=[]},Er.prototype.once=function(e,t,n){var r=this.eventElement(e),o=function(e){r.unbind(t,o),n(e)};r.bind(t,o)};var _r=function(e,t,n,r,o){var i;if(void 0===r&&(r=!0),void 0===o&&(o=!1),\"top\"===t)i=[\"contentHeight\",\"containerHeight\",\"scrollTop\",\"y\",\"up\",\"down\"];else{if(\"left\"!==t)throw new Error(\"A proper axis should be provided\");i=[\"contentWidth\",\"containerWidth\",\"scrollLeft\",\"x\",\"left\",\"right\"]}!function(e,t,n,r,o){var i=n[0],a=n[1],s=n[2],l=n[3],c=n[4],u=n[5];void 0===r&&(r=!0);void 0===o&&(o=!1);var p=e.element;e.reach[l]=null,p[s]<1&&(e.reach[l]=\"start\");p[s]>e[i]-e[a]-1&&(e.reach[l]=\"end\");t&&(p.dispatchEvent(Sr(\"ps-scroll-\"+l)),t<0?p.dispatchEvent(Sr(\"ps-scroll-\"+c)):t>0&&p.dispatchEvent(Sr(\"ps-scroll-\"+u)),r&&function(e,t){br(e,t),wr(e,t)}(e,l));e.reach[l]&&(t||o)&&p.dispatchEvent(Sr(\"ps-\"+l+\"-reach-\"+e.reach[l]))}(e,n,i,r,o)};function Or(e){return parseInt(e,10)||0}var Cr={isWebKit:\"undefined\"!=typeof document&&\"WebkitAppearance\"in document.documentElement.style,supportsTouch:\"undefined\"!=typeof window&&(\"ontouchstart\"in window||window.DocumentTouch&&document instanceof window.DocumentTouch),supportsIePointer:\"undefined\"!=typeof navigator&&navigator.msMaxTouchPoints,isChrome:\"undefined\"!=typeof navigator&&/Chrome/i.test(navigator&&navigator.userAgent)},Tr=function(e){var t=e.element,n=Math.floor(t.scrollTop);e.containerWidth=t.clientWidth,e.containerHeight=t.clientHeight,e.contentWidth=t.scrollWidth,e.contentHeight=t.scrollHeight,t.contains(e.scrollbarXRail)||(gr(t,yr.element.rail(\"x\")).forEach(function(e){return mr(e)}),t.appendChild(e.scrollbarXRail)),t.contains(e.scrollbarYRail)||(gr(t,yr.element.rail(\"y\")).forEach(function(e){return mr(e)}),t.appendChild(e.scrollbarYRail)),!e.settings.suppressScrollX&&e.containerWidth+e.settings.scrollXMarginOffset<e.contentWidth?(e.scrollbarXActive=!0,e.railXWidth=e.containerWidth-e.railXMarginWidth,e.railXRatio=e.containerWidth/e.railXWidth,e.scrollbarXWidth=jr(e,Or(e.railXWidth*e.containerWidth/e.contentWidth)),e.scrollbarXLeft=Or((e.negativeScrollAdjustment+t.scrollLeft)*(e.railXWidth-e.scrollbarXWidth)/(e.contentWidth-e.containerWidth))):e.scrollbarXActive=!1,!e.settings.suppressScrollY&&e.containerHeight+e.settings.scrollYMarginOffset<e.contentHeight?(e.scrollbarYActive=!0,e.railYHeight=e.containerHeight-e.railYMarginHeight,e.railYRatio=e.containerHeight/e.railYHeight,e.scrollbarYHeight=jr(e,Or(e.railYHeight*e.containerHeight/e.contentHeight)),e.scrollbarYTop=Or(n*(e.railYHeight-e.scrollbarYHeight)/(e.contentHeight-e.containerHeight))):e.scrollbarYActive=!1,e.scrollbarXLeft>=e.railXWidth-e.scrollbarXWidth&&(e.scrollbarXLeft=e.railXWidth-e.scrollbarXWidth),e.scrollbarYTop>=e.railYHeight-e.scrollbarYHeight&&(e.scrollbarYTop=e.railYHeight-e.scrollbarYHeight),function(e,t){var n={width:t.railXWidth},r=Math.floor(e.scrollTop);t.isRtl?n.left=t.negativeScrollAdjustment+e.scrollLeft+t.containerWidth-t.contentWidth:n.left=e.scrollLeft;t.isScrollbarXUsingBottom?n.bottom=t.scrollbarXBottom-r:n.top=t.scrollbarXTop+r;pr(t.scrollbarXRail,n);var o={top:r,height:t.railYHeight};t.isScrollbarYUsingRight?t.isRtl?o.right=t.contentWidth-(t.negativeScrollAdjustment+e.scrollLeft)-t.scrollbarYRight-t.scrollbarYOuterWidth:o.right=t.scrollbarYRight-e.scrollLeft:t.isRtl?o.left=t.negativeScrollAdjustment+e.scrollLeft+2*t.containerWidth-t.contentWidth-t.scrollbarYLeft-t.scrollbarYOuterWidth:o.left=t.scrollbarYLeft+e.scrollLeft;pr(t.scrollbarYRail,o),pr(t.scrollbarX,{left:t.scrollbarXLeft,width:t.scrollbarXWidth-t.railBorderXWidth}),pr(t.scrollbarY,{top:t.scrollbarYTop,height:t.scrollbarYHeight-t.railBorderYWidth})}(t,e),e.scrollbarXActive?t.classList.add(yr.state.active(\"x\")):(t.classList.remove(yr.state.active(\"x\")),e.scrollbarXWidth=0,e.scrollbarXLeft=0,t.scrollLeft=0),e.scrollbarYActive?t.classList.add(yr.state.active(\"y\")):(t.classList.remove(yr.state.active(\"y\")),e.scrollbarYHeight=0,e.scrollbarYTop=0,t.scrollTop=0)};function jr(e,t){return e.settings.minScrollbarLength&&(t=Math.max(t,e.settings.minScrollbarLength)),e.settings.maxScrollbarLength&&(t=Math.min(t,e.settings.maxScrollbarLength)),t}function Ar(e,t){var n=t[0],r=t[1],o=t[2],i=t[3],a=t[4],s=t[5],l=t[6],c=t[7],u=t[8],p=e.element,f=null,d=null,h=null;function m(t){p[l]=f+h*(t[o]-d),br(e,c),Tr(e),t.stopPropagation(),t.preventDefault()}function g(){wr(e,c),e[u].classList.remove(yr.state.clicking),e.event.unbind(e.ownerDocument,\"mousemove\",m)}e.event.bind(e[a],\"mousedown\",function(t){f=p[l],d=t[o],h=(e[r]-e[n])/(e[i]-e[s]),e.event.bind(e.ownerDocument,\"mousemove\",m),e.event.once(e.ownerDocument,\"mouseup\",g),e[u].classList.add(yr.state.clicking),t.stopPropagation(),t.preventDefault()})}var Ir={\"click-rail\":function(e){e.event.bind(e.scrollbarY,\"mousedown\",function(e){return e.stopPropagation()}),e.event.bind(e.scrollbarYRail,\"mousedown\",function(t){var n=t.pageY-window.pageYOffset-e.scrollbarYRail.getBoundingClientRect().top>e.scrollbarYTop?1:-1;e.element.scrollTop+=n*e.containerHeight,Tr(e),t.stopPropagation()}),e.event.bind(e.scrollbarX,\"mousedown\",function(e){return e.stopPropagation()}),e.event.bind(e.scrollbarXRail,\"mousedown\",function(t){var n=t.pageX-window.pageXOffset-e.scrollbarXRail.getBoundingClientRect().left>e.scrollbarXLeft?1:-1;e.element.scrollLeft+=n*e.containerWidth,Tr(e),t.stopPropagation()})},\"drag-thumb\":function(e){Ar(e,[\"containerWidth\",\"contentWidth\",\"pageX\",\"railXWidth\",\"scrollbarX\",\"scrollbarXWidth\",\"scrollLeft\",\"x\",\"scrollbarXRail\"]),Ar(e,[\"containerHeight\",\"contentHeight\",\"pageY\",\"railYHeight\",\"scrollbarY\",\"scrollbarYHeight\",\"scrollTop\",\"y\",\"scrollbarYRail\"])},keyboard:function(e){var t=e.element;e.event.bind(e.ownerDocument,\"keydown\",function(n){if(!(n.isDefaultPrevented&&n.isDefaultPrevented()||n.defaultPrevented)&&(hr(t,\":hover\")||hr(e.scrollbarX,\":focus\")||hr(e.scrollbarY,\":focus\"))){var r,o=document.activeElement?document.activeElement:e.ownerDocument.activeElement;if(o){if(\"IFRAME\"===o.tagName)o=o.contentDocument.activeElement;else for(;o.shadowRoot;)o=o.shadowRoot.activeElement;if(hr(r=o,\"input,[contenteditable]\")||hr(r,\"select,[contenteditable]\")||hr(r,\"textarea,[contenteditable]\")||hr(r,\"button,[contenteditable]\"))return}var i=0,a=0;switch(n.which){case 37:i=n.metaKey?-e.contentWidth:n.altKey?-e.containerWidth:-30;break;case 38:a=n.metaKey?e.contentHeight:n.altKey?e.containerHeight:30;break;case 39:i=n.metaKey?e.contentWidth:n.altKey?e.containerWidth:30;break;case 40:a=n.metaKey?-e.contentHeight:n.altKey?-e.containerHeight:-30;break;case 32:a=n.shiftKey?e.containerHeight:-e.containerHeight;break;case 33:a=e.containerHeight;break;case 34:a=-e.containerHeight;break;case 36:a=e.contentHeight;break;case 35:a=-e.contentHeight;break;default:return}e.settings.suppressScrollX&&0!==i||e.settings.suppressScrollY&&0!==a||(t.scrollTop-=a,t.scrollLeft+=i,Tr(e),function(n,r){var o=Math.floor(t.scrollTop);if(0===n){if(!e.scrollbarYActive)return!1;if(0===o&&r>0||o>=e.contentHeight-e.containerHeight&&r<0)return!e.settings.wheelPropagation}var i=t.scrollLeft;if(0===r){if(!e.scrollbarXActive)return!1;if(0===i&&n<0||i>=e.contentWidth-e.containerWidth&&n>0)return!e.settings.wheelPropagation}return!0}(i,a)&&n.preventDefault())}})},wheel:function(e){var t=e.element;function n(n){var r=function(e){var t=e.deltaX,n=-1*e.deltaY;return void 0!==t&&void 0!==n||(t=-1*e.wheelDeltaX/6,n=e.wheelDeltaY/6),e.deltaMode&&1===e.deltaMode&&(t*=10,n*=10),t!=t&&n!=n&&(t=0,n=e.wheelDelta),e.shiftKey?[-n,-t]:[t,n]}(n),o=r[0],i=r[1];if(!function(e,n,r){if(!Cr.isWebKit&&t.querySelector(\"select:focus\"))return!0;if(!t.contains(e))return!1;for(var o=e;o&&o!==t;){if(o.classList.contains(yr.element.consuming))return!0;var i=ur(o);if([i.overflow,i.overflowX,i.overflowY].join(\"\").match(/(scroll|auto)/)){var a=o.scrollHeight-o.clientHeight;if(a>0&&!(0===o.scrollTop&&r>0||o.scrollTop===a&&r<0))return!0;var s=o.scrollWidth-o.clientWidth;if(s>0&&!(0===o.scrollLeft&&n<0||o.scrollLeft===s&&n>0))return!0}o=o.parentNode}return!1}(n.target,o,i)){var a=!1;e.settings.useBothWheelAxes?e.scrollbarYActive&&!e.scrollbarXActive?(i?t.scrollTop-=i*e.settings.wheelSpeed:t.scrollTop+=o*e.settings.wheelSpeed,a=!0):e.scrollbarXActive&&!e.scrollbarYActive&&(o?t.scrollLeft+=o*e.settings.wheelSpeed:t.scrollLeft-=i*e.settings.wheelSpeed,a=!0):(t.scrollTop-=i*e.settings.wheelSpeed,t.scrollLeft+=o*e.settings.wheelSpeed),Tr(e),(a=a||function(n,r){var o=Math.floor(t.scrollTop),i=0===t.scrollTop,a=o+t.offsetHeight===t.scrollHeight,s=0===t.scrollLeft,l=t.scrollLeft+t.offsetWidth===t.scrollWidth;return!(Math.abs(r)>Math.abs(n)?i||a:s||l)||!e.settings.wheelPropagation}(o,i))&&!n.ctrlKey&&(n.stopPropagation(),n.preventDefault())}}void 0!==window.onwheel?e.event.bind(t,\"wheel\",n):void 0!==window.onmousewheel&&e.event.bind(t,\"mousewheel\",n)},touch:function(e){if(Cr.supportsTouch||Cr.supportsIePointer){var t=e.element,n={},r=0,o={},i=null;Cr.supportsTouch?(e.event.bind(t,\"touchstart\",c),e.event.bind(t,\"touchmove\",u),e.event.bind(t,\"touchend\",p)):Cr.supportsIePointer&&(window.PointerEvent?(e.event.bind(t,\"pointerdown\",c),e.event.bind(t,\"pointermove\",u),e.event.bind(t,\"pointerup\",p)):window.MSPointerEvent&&(e.event.bind(t,\"MSPointerDown\",c),e.event.bind(t,\"MSPointerMove\",u),e.event.bind(t,\"MSPointerUp\",p)))}function a(n,r){t.scrollTop-=r,t.scrollLeft-=n,Tr(e)}function s(e){return e.targetTouches?e.targetTouches[0]:e}function l(e){return!(e.pointerType&&\"pen\"===e.pointerType&&0===e.buttons||(!e.targetTouches||1!==e.targetTouches.length)&&(!e.pointerType||\"mouse\"===e.pointerType||e.pointerType===e.MSPOINTER_TYPE_MOUSE))}function c(e){if(l(e)){var t=s(e);n.pageX=t.pageX,n.pageY=t.pageY,r=(new Date).getTime(),null!==i&&clearInterval(i)}}function u(i){if(l(i)){var c=s(i),u={pageX:c.pageX,pageY:c.pageY},p=u.pageX-n.pageX,f=u.pageY-n.pageY;if(function(e,n,r){if(!t.contains(e))return!1;for(var o=e;o&&o!==t;){if(o.classList.contains(yr.element.consuming))return!0;var i=ur(o);if([i.overflow,i.overflowX,i.overflowY].join(\"\").match(/(scroll|auto)/)){var a=o.scrollHeight-o.clientHeight;if(a>0&&!(0===o.scrollTop&&r>0||o.scrollTop===a&&r<0))return!0;var s=o.scrollLeft-o.clientWidth;if(s>0&&!(0===o.scrollLeft&&n<0||o.scrollLeft===s&&n>0))return!0}o=o.parentNode}return!1}(i.target,p,f))return;a(p,f),n=u;var d=(new Date).getTime(),h=d-r;h>0&&(o.x=p/h,o.y=f/h,r=d),function(n,r){var o=Math.floor(t.scrollTop),i=t.scrollLeft,a=Math.abs(n),s=Math.abs(r);if(s>a){if(r<0&&o===e.contentHeight-e.containerHeight||r>0&&0===o)return 0===window.scrollY&&r>0&&Cr.isChrome}else if(a>s&&(n<0&&i===e.contentWidth-e.containerWidth||n>0&&0===i))return!0;return!0}(p,f)&&i.preventDefault()}}function p(){e.settings.swipeEasing&&(clearInterval(i),i=setInterval(function(){e.isInitialized?clearInterval(i):o.x||o.y?Math.abs(o.x)<.01&&Math.abs(o.y)<.01?clearInterval(i):(a(30*o.x,30*o.y),o.x*=.8,o.y*=.8):clearInterval(i)},10))}}},Pr=function(e,t){var n=this;if(void 0===t&&(t={}),\"string\"==typeof e&&(e=document.querySelector(e)),!e||!e.nodeName)throw new Error(\"no element is specified to initialize PerfectScrollbar\");for(var r in this.element=e,e.classList.add(yr.main),this.settings={handlers:[\"click-rail\",\"drag-thumb\",\"keyboard\",\"wheel\",\"touch\"],maxScrollbarLength:null,minScrollbarLength:null,scrollingThreshold:1e3,scrollXMarginOffset:0,scrollYMarginOffset:0,suppressScrollX:!1,suppressScrollY:!1,swipeEasing:!0,useBothWheelAxes:!1,wheelPropagation:!0,wheelSpeed:1},t)n.settings[r]=t[r];this.containerWidth=null,this.containerHeight=null,this.contentWidth=null,this.contentHeight=null;var o,i,a=function(){return e.classList.add(yr.state.focus)},s=function(){return e.classList.remove(yr.state.focus)};this.isRtl=\"rtl\"===ur(e).direction,this.isNegativeScroll=(i=e.scrollLeft,e.scrollLeft=-1,o=e.scrollLeft<0,e.scrollLeft=i,o),this.negativeScrollAdjustment=this.isNegativeScroll?e.scrollWidth-e.clientWidth:0,this.event=new Er,this.ownerDocument=e.ownerDocument||document,this.scrollbarXRail=fr(yr.element.rail(\"x\")),e.appendChild(this.scrollbarXRail),this.scrollbarX=fr(yr.element.thumb(\"x\")),this.scrollbarXRail.appendChild(this.scrollbarX),this.scrollbarX.setAttribute(\"tabindex\",0),this.event.bind(this.scrollbarX,\"focus\",a),this.event.bind(this.scrollbarX,\"blur\",s),this.scrollbarXActive=null,this.scrollbarXWidth=null,this.scrollbarXLeft=null;var l=ur(this.scrollbarXRail);this.scrollbarXBottom=parseInt(l.bottom,10),isNaN(this.scrollbarXBottom)?(this.isScrollbarXUsingBottom=!1,this.scrollbarXTop=Or(l.top)):this.isScrollbarXUsingBottom=!0,this.railBorderXWidth=Or(l.borderLeftWidth)+Or(l.borderRightWidth),pr(this.scrollbarXRail,{display:\"block\"}),this.railXMarginWidth=Or(l.marginLeft)+Or(l.marginRight),pr(this.scrollbarXRail,{display:\"\"}),this.railXWidth=null,this.railXRatio=null,this.scrollbarYRail=fr(yr.element.rail(\"y\")),e.appendChild(this.scrollbarYRail),this.scrollbarY=fr(yr.element.thumb(\"y\")),this.scrollbarYRail.appendChild(this.scrollbarY),this.scrollbarY.setAttribute(\"tabindex\",0),this.event.bind(this.scrollbarY,\"focus\",a),this.event.bind(this.scrollbarY,\"blur\",s),this.scrollbarYActive=null,this.scrollbarYHeight=null,this.scrollbarYTop=null;var c=ur(this.scrollbarYRail);this.scrollbarYRight=parseInt(c.right,10),isNaN(this.scrollbarYRight)?(this.isScrollbarYUsingRight=!1,this.scrollbarYLeft=Or(c.left)):this.isScrollbarYUsingRight=!0,this.scrollbarYOuterWidth=this.isRtl?function(e){var t=ur(e);return Or(t.width)+Or(t.paddingLeft)+Or(t.paddingRight)+Or(t.borderLeftWidth)+Or(t.borderRightWidth)}(this.scrollbarY):null,this.railBorderYWidth=Or(c.borderTopWidth)+Or(c.borderBottomWidth),pr(this.scrollbarYRail,{display:\"block\"}),this.railYMarginHeight=Or(c.marginTop)+Or(c.marginBottom),pr(this.scrollbarYRail,{display:\"\"}),this.railYHeight=null,this.railYRatio=null,this.reach={x:e.scrollLeft<=0?\"start\":e.scrollLeft>=this.contentWidth-this.containerWidth?\"end\":null,y:e.scrollTop<=0?\"start\":e.scrollTop>=this.contentHeight-this.containerHeight?\"end\":null},this.isAlive=!0,this.settings.handlers.forEach(function(e){return Ir[e](n)}),this.lastScrollTop=Math.floor(e.scrollTop),this.lastScrollLeft=e.scrollLeft,this.event.bind(this.element,\"scroll\",function(e){return n.onScroll(e)}),Tr(this)};Pr.prototype.update=function(){this.isAlive&&(this.negativeScrollAdjustment=this.isNegativeScroll?this.element.scrollWidth-this.element.clientWidth:0,pr(this.scrollbarXRail,{display:\"block\"}),pr(this.scrollbarYRail,{display:\"block\"}),this.railXMarginWidth=Or(ur(this.scrollbarXRail).marginLeft)+Or(ur(this.scrollbarXRail).marginRight),this.railYMarginHeight=Or(ur(this.scrollbarYRail).marginTop)+Or(ur(this.scrollbarYRail).marginBottom),pr(this.scrollbarXRail,{display:\"none\"}),pr(this.scrollbarYRail,{display:\"none\"}),Tr(this),_r(this,\"top\",0,!1,!0),_r(this,\"left\",0,!1,!0),pr(this.scrollbarXRail,{display:\"\"}),pr(this.scrollbarYRail,{display:\"\"}))},Pr.prototype.onScroll=function(e){this.isAlive&&(Tr(this),_r(this,\"top\",this.element.scrollTop-this.lastScrollTop),_r(this,\"left\",this.element.scrollLeft-this.lastScrollLeft),this.lastScrollTop=Math.floor(this.element.scrollTop),this.lastScrollLeft=this.element.scrollLeft)},Pr.prototype.destroy=function(){this.isAlive&&(this.event.unbindAll(),mr(this.scrollbarX),mr(this.scrollbarY),mr(this.scrollbarXRail),mr(this.scrollbarYRail),this.removePsClasses(),this.element=null,this.scrollbarX=null,this.scrollbarY=null,this.scrollbarXRail=null,this.scrollbarYRail=null,this.isAlive=!1)},Pr.prototype.removePsClasses=function(){this.element.className=this.element.className.split(\" \").filter(function(e){return!e.match(/^ps([-_].+|)$/)}).join(\" \")};var Rr,Nr=Pr,Lr=n(81),Mr=n.n(Lr),Dr=Nr||r,Fr=be(Rr||(Rr=u([\"\",\"\"],[\"\",\"\"])),Mr.a&&Mr.a.toString()),Ur=Ee.div.withConfig({componentId:\"i2xdng-0\"})([\"position:relative;\"]),Br=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.handleRef=function(e){t._container=e},t}return i(t,e),t.prototype.componentDidMount=function(){var e=this._container.parentElement&&this._container.parentElement.scrollTop||0;this.inst=new Dr(this._container,this.props.options||{}),this._container.scrollTo&&this._container.scrollTo(0,e)},t.prototype.componentDidUpdate=function(){this.inst.update()},t.prototype.componentWillUnmount=function(){this.inst.destroy()},t.prototype.render=function(){var e=this.props,t=e.children,n=e.className,r=e.updateFn;return r&&r(this.componentDidUpdate.bind(this)),p.createElement(p.Fragment,null,p.createElement(Fr,null),p.createElement(Ur,{className:\"scrollbar-container \"+n,ref:this.handleRef},t))},t}(p.Component);function zr(e){return p.createElement(Ie.Consumer,null,function(t){return t.nativeScrollbars?p.createElement(\"div\",{style:{overflow:\"auto\",msOverflowStyle:\"-ms-autohiding-scrollbar\"}},e.children):p.createElement(Br,a({},e),e.children)})}var $r=n(132),Wr=Ee.div.withConfig({componentId:\"sc-107yc6q-0\"})([\"code[class*='language-'],pre[class*='language-']{text-shadow:0 -0.1em 0.2em black;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;}@media print{code[class*='language-'],pre[class*='language-']{text-shadow:none;}}pre[class*='language-']{padding:1em;margin:0.5em 0;overflow:auto;}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:hsl(30,20%,50%);}.token.punctuation{opacity:0.7;}.namespace{opacity:0.7;}.token.property,.token.tag,.token.number,.token.constant,.token.symbol{color:#4a8bb3;}.token.boolean{color:firebrick;}.token.selector,.token.attr-name,.token.string,.token.char,.token.builtin,.token.inserted{color:#a0fbaa;& + a,& + a:visited{color:#4ed2ba;text-decoration:underline;}}.token.operator,.token.entity,.token.url,.token.variable{color:hsl(40,90%,60%);}.token.atrule,.token.attr-value,.token.keyword{color:hsl(350,40%,70%);}.token.regex,.token.important{color:#e90;}.token.important,.token.bold{font-weight:bold;}.token.italic{font-style:italic;}.token.entity{cursor:help;}.token.deleted{color:red;}\",\";\"],Se(\"Prism\")),qr=ve([\"a{text-decoration:none;color:\",\";&:visited{color:\",\";}&:hover{color:\",\";}}\"],function(e){return e.theme.typography.links.color},function(e){return e.theme.typography.links.visited},function(e){return e.theme.typography.links.hover}),Hr=Ee(Wr).withConfig({componentId:\"sc-1m0b31p-0\"})([\"font-family:\",\";font-weight:\",\";line-height:\",\";p{&:last-child{margin-bottom:0;}}\",\" \",\" h1{\",\";color:\",\";margin-top:0;}h2{\",\";color:\",\";}code{color:\",\";background-color:\",\";font-family:\",\";border-radius:2px;border:1px solid rgba(38,50,56,0.1);padding:0 \",\"px;font-size:\",\";font-weight:\",\";word-break:break-word;}pre{font-family:\",\";white-space:\",\";background-color:#263238;color:white;padding:12px 14px 15px 14px;overflow-x:auto;line-height:normal;border-radius:0px border:1px solid rgba(38,50,56,0.1);code{background-color:transparent;color:white;padding:0;&:before,&:after{content:none;}}}blockquote{margin:0;margin-bottom:1em;padding:0 15px;color:#777;border-left:4px solid #ddd;}img{max-width:100%;box-sizing:content-box;}ul,ol{padding-left:2em;margin:0;margin-bottom:1em;ul,ol{margin-bottom:0;margin-top:0;}}table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;border-collapse:collapse;border-spacing:0;margin-top:1.5em;margin-bottom:1.5em;}table tr{background-color:#fff;border-top:1px solid #ccc;&:nth-child(2n){background-color:\",\";}}table th,table td{padding:6px 13px;border:1px solid #ddd;}table th{text-align:left;font-weight:bold;}\",\";\",\" \",\";\"],function(e){return e.theme.typography.fontFamily},function(e){return e.theme.typography.fontWeightRegular},function(e){return e.theme.typography.lineHeight},function(e){return e.compact&&\"\\n    p:first-child {\\n      margin-top: 0;\\n    }\\n    p:last-child {\\n      margin-bottom: 0;\\n    }\\n  \"},function(e){return e.inline&&\" p {\\n    display: inline-block;\\n  }\"},en(1),function(e){return e.theme.colors.primary.main},en(2),function(e){return e.theme.colors.text.primary},function(e){return e.theme.typography.code.color},function(e){return e.theme.typography.code.backgroundColor},function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.spacing.unit},function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.typography.code.fontWeight},function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.typography.code.wrap?\"pre-wrap\":\"pre\"},function(e){return e.theme.schema.nestedBackground},pn(\".share-link\"),qr,Se(\"Markdown\")),Yr=Hr.withComponent(\"span\"),Vr=function(e,t){return e?$r.sanitize(t):t};function Qr(e){var t=e.inline?Yr:Hr;return p.createElement(Re,null,function(n){return p.createElement(t,a({className:\"redoc-markdown \"+(e.className||\"\"),dangerouslySetInnerHTML:{__html:Vr(n.untrustedSpec,e.html)}},e))})}var Gr,Xr=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.source,n=e.inline,r=e.compact,o=e.className,i=new vt;return p.createElement(Qr,{html:i.renderMd(t),inline:n,compact:r,className:o})},t}(p.Component),Kr={oauth2:\"OAuth2\",apiKey:\"API Key\",http:\"HTTP\",openIdConnect:\"Open ID Connect\"},Jr=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.type,n=e.flow;return p.createElement(\"tr\",null,p.createElement(\"th\",null,\" \",t,\" OAuth Flow \"),p.createElement(\"td\",null,\"implicit\"===t||\"authorizationCode\"===t?p.createElement(\"div\",null,p.createElement(\"strong\",null,\" Authorization URL: \"),n.authorizationUrl):null,\"password\"===t||\"clientCredentials\"===t||\"authorizationCode\"===t?p.createElement(\"div\",null,p.createElement(\"strong\",null,\" Token URL: \"),n.tokenUrl):null,n.refreshUrl&&p.createElement(\"div\",null,p.createElement(\"strong\",null,\" Refresh URL: \"),n.refreshUrl),p.createElement(\"div\",null,p.createElement(\"strong\",null,\" Scopes: \")),p.createElement(\"ul\",null,Object.keys(n.scopes).map(function(e){return p.createElement(\"li\",{key:e},p.createElement(\"code\",null,e),\" - \",p.createElement(Xr,{inline:!0,source:n.scopes[e]||\"\"}))}))))},t}(p.PureComponent),Zr=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return this.props.securitySchemes.schemes.map(function(e){return p.createElement(Gt,{id:e.sectionId,key:e.id},p.createElement(Jt,null,p.createElement(Qt,null,p.createElement(nn,null,p.createElement(mn,{to:e.sectionId}),e.id),p.createElement(Xr,{source:e.description||\"\"}),p.createElement(Hr,null,p.createElement(\"table\",{className:\"security-details\"},p.createElement(\"tbody\",null,p.createElement(\"tr\",null,p.createElement(\"th\",null,\" Security scheme type: \"),p.createElement(\"td\",null,\" \",Kr[e.type]||e.type,\" \")),e.apiKey?p.createElement(\"tr\",null,p.createElement(\"th\",null,\" \",e.apiKey.in,\" parameter name:\"),p.createElement(\"td\",null,\" \",e.apiKey.name,\" \")):e.http?[p.createElement(\"tr\",{key:\"scheme\"},p.createElement(\"th\",null,\" HTTP Authorization Scheme \"),p.createElement(\"td\",null,\" \",e.http.scheme,\" \")),\"bearer\"===e.http.scheme&&e.http.bearerFormat&&p.createElement(\"tr\",{key:\"bearer\"},p.createElement(\"th\",null,\" Bearer format \"),p.createElement(\"td\",null,' \"',e.http.bearerFormat,'\" '))]:e.openId?p.createElement(\"tr\",null,p.createElement(\"th\",null,\" Connect URL \"),p.createElement(\"td\",null,p.createElement(\"a\",{target:\"_blank\",href:e.openId.connectUrl},e.openId.connectUrl))):e.flows?Object.keys(e.flows).map(function(t){return p.createElement(Jr,{key:t,type:t,flow:e.flows[t]})}):null))))))})},t}(p.PureComponent);var eo=function(){function e(e,t,n,r){void 0===n&&(n={}),void 0===r&&(r=!0);var o=this;this.marker=new ht,this.disposer=null,this.rawOptions=n,this.options=new me(n,to),this.scroll=new $t(this.options),zt.updateOnHistory(ft.currentId,this.scroll),this.spec=new _t(e,t,this.options),this.menu=new zt(this.spec,this.scroll,ft),this.options.disableSearch||(this.search=new Vt,r&&this.search.indexItems(this.menu.items),this.disposer=Object(Ne.m)(this.menu,\"activeItemIdx\",function(e){o.updateMarkOnMenu(e.newValue)}))}return e.fromJS=function(t){var n=new e(t.spec.data,t.spec.url,t.options,!1);return n.menu.activeItemIdx=t.menu.activeItemIdx||0,n.menu.activate(n.menu.flatItems[n.menu.activeItemIdx]),n.options.disableSearch||n.search.load(t.searchIndex),n},e.prototype.onDidMount=function(){this.menu.updateOnHistory(),this.updateMarkOnMenu(this.menu.activeItemIdx)},e.prototype.dispose=function(){this.scroll.dispose(),this.menu.dispose(),null!=this.disposer&&this.disposer()},e.prototype.toJS=function(){return l(this,void 0,void 0,function(){var e,t;return c(this,function(n){switch(n.label){case 0:return e={menu:{activeItemIdx:this.menu.activeItemIdx},spec:{url:this.spec.parser.specUrl,data:this.spec.parser.spec}},this.search?[4,this.search.toJS()]:[3,2];case 1:return t=n.sent(),[3,3];case 2:t=void 0,n.label=3;case 3:return[2,(e.searchIndex=t,e.options=this.rawOptions,e)]}})})},e.prototype.updateMarkOnMenu=function(e){for(var t=Math.max(0,e),n=Math.min(this.menu.flatItems.length,t+5),r=[],o=t;o<n;o++){var i=this.menu.getElementAt(o);i&&(\"section\"===this.menu.flatItems[o].type&&(i=i.parentElement.parentElement),i&&r.push(i))}this.marker.addOnly(r),this.marker.mark()},e}(),to={allowedMdComponents:(Gr={},Gr[\"security-definitions\"]={component:Zr,propsSelector:function(e){return{securitySchemes:e.spec.securitySchemes}}},Gr)},no=\"undefined\"!=typeof document&&document.queryCommandSupported&&document.queryCommandSupported(\"copy\"),ro=function(){function e(){}return e.isSupported=function(){return no},e.selectElement=function(e){var t,n;document.body.createTextRange?((t=document.body.createTextRange()).moveToElementText(e),t.select()):document.createRange&&window.getSelection&&(n=window.getSelection(),(t=document.createRange()).selectNodeContents(e),n.removeAllRanges(),n.addRange(t))},e.deselect=function(){document.selection?document.selection.empty():window.getSelection&&window.getSelection().removeAllRanges()},e.copySelected=function(){var e;try{e=document.execCommand(\"copy\")}catch(t){e=!1}return e},e.copyElement=function(t){e.selectElement(t);var n=e.copySelected();return n&&e.deselect(),n},e.copyCustom=function(t){var n=document.createElement(\"textarea\");n.style.position=\"fixed\",n.style.top=\"0\",n.style.left=\"0\",n.style.width=\"2em\",n.style.height=\"2em\",n.style.padding=\"0\",n.style.border=\"none\",n.style.outline=\"none\",n.style.boxShadow=\"none\",n.style.background=\"transparent\",n.value=t,document.body.appendChild(n),n.select();var r=e.copySelected();return document.body.removeChild(n),r},e}();function oo(e){return(oo=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e})(e)}function io(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function ao(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function so(e,t,n){return t&&ao(e.prototype,t),n&&ao(e,n),e}function lo(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function co(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function\");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&po(e,t)}function uo(e){return(uo=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function po(e,t){return(po=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function fo(e,t){return!t||\"object\"!=typeof t&&\"function\"!=typeof t?function(e){if(void 0===e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return e}(e):t}function ho(e,t){return e(t={exports:{}},t.exports),t.exports}var mo,go=ho(function(e,t){Object.defineProperty(t,\"__esModule\",{value:!0});var n=\"function\"==typeof Symbol&&Symbol.for,r=n?Symbol.for(\"react.element\"):60103,o=n?Symbol.for(\"react.portal\"):60106,i=n?Symbol.for(\"react.fragment\"):60107,a=n?Symbol.for(\"react.strict_mode\"):60108,s=n?Symbol.for(\"react.profiler\"):60114,l=n?Symbol.for(\"react.provider\"):60109,c=n?Symbol.for(\"react.context\"):60110,u=n?Symbol.for(\"react.async_mode\"):60111,p=n?Symbol.for(\"react.forward_ref\"):60112,f=n?Symbol.for(\"react.placeholder\"):60113;function d(e){if(\"object\"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case u:case i:case s:case a:return e;default:switch(e=e&&e.$$typeof){case c:case p:case l:return e;default:return t}}case o:return t}}}t.typeOf=d,t.AsyncMode=u,t.ContextConsumer=c,t.ContextProvider=l,t.Element=r,t.ForwardRef=p,t.Fragment=i,t.Profiler=s,t.Portal=o,t.StrictMode=a,t.isValidElementType=function(e){return\"string\"==typeof e||\"function\"==typeof e||e===i||e===u||e===s||e===a||e===f||\"object\"==typeof e&&null!==e&&(\"function\"==typeof e.then||e.$$typeof===l||e.$$typeof===c||e.$$typeof===p)},t.isAsyncMode=function(e){return d(e)===u},t.isContextConsumer=function(e){return d(e)===c},t.isContextProvider=function(e){return d(e)===l},t.isElement=function(e){return\"object\"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return d(e)===p},t.isFragment=function(e){return d(e)===i},t.isProfiler=function(e){return d(e)===s},t.isPortal=function(e){return d(e)===o},t.isStrictMode=function(e){return d(e)===a}});(mo=go)&&mo.__esModule&&Object.prototype.hasOwnProperty.call(mo,\"default\")&&mo.default;go.typeOf,go.AsyncMode,go.ContextConsumer,go.ContextProvider,go.Element,go.ForwardRef,go.Fragment,go.Profiler,go.Portal,go.StrictMode,go.isValidElementType,go.isAsyncMode,go.isContextConsumer,go.isContextProvider,go.isElement,go.isForwardRef,go.isFragment,go.isProfiler,go.isPortal,go.isStrictMode;var yo,vo=ho(function(e){e.exports=go});function bo(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var wo={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},xo={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},ko=bo({},vo.ForwardRef,(bo(yo={},\"$$typeof\",!0),bo(yo,\"render\",!0),yo)),Eo=Object.defineProperty,So=Object.getOwnPropertyNames,_o=Object.getOwnPropertySymbols,Oo=Object.getOwnPropertyDescriptor,Co=Object.getPrototypeOf,To=Object.prototype;var jo=function e(t,n,r){if(\"string\"!=typeof n){if(To){var o=Co(n);o&&o!==To&&e(t,o,r)}var i=So(n);_o&&(i=i.concat(_o(n)));for(var a=ko[t.$$typeof]||wo,s=ko[n.$$typeof]||wo,l=0;l<i.length;++l){var c=i[l];if(!(xo[c]||r&&r[c]||s&&s[c]||a&&a[c])){var u=Oo(n,c);try{Eo(t,c,u)}catch(e){}}}return t}return t},Ao=function(){function e(){io(this,e),this.listeners=[]}return so(e,[{key:\"on\",value:function(e){var t=this;return this.listeners.push(e),function(){var n=t.listeners.indexOf(e);-1!==n&&t.listeners.splice(n,1)}}},{key:\"emit\",value:function(e){this.listeners.forEach(function(t){return t(e)})}}]),e}();function Io(e){function t(t,n,r,o,i,a){for(var s=arguments.length,l=new Array(s>6?s-6:0),c=6;c<s;c++)l[c-6]=arguments[c];return Object(Ne.o)(function(){if(o=o||\"<<anonymous>>\",a=a||r,null==n[r]){if(t){var s=null===n[r]?\"null\":\"undefined\";return new Error(\"The \"+i+\" `\"+a+\"` is marked as required in `\"+o+\"`, but its value is `\"+s+\"`.\")}return null}return e.apply(void 0,[n,r,o,i,a].concat(l))})}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function Po(e){var t=oo(e);return Array.isArray(e)?\"array\":e instanceof RegExp?\"object\":function(e,t){return\"symbol\"===e||\"Symbol\"===t[\"@@toStringTag\"]||\"function\"==typeof Symbol&&t instanceof Symbol}(t,e)?\"symbol\":t}function Ro(e,t){return Io(function(n,r,o,i,a){return Object(Ne.o)(function(){if(e&&Po(n[r])===t.toLowerCase())return null;var i;switch(t){case\"Array\":i=Ne.i;break;case\"Object\":i=Ne.k;break;case\"Map\":i=Ne.j;break;default:throw new Error(\"Unexpected mobxType: \".concat(t))}var s=n[r];if(!i(s)){var l=function(e){var t=Po(e);if(\"object\"===t){if(e instanceof Date)return\"date\";if(e instanceof RegExp)return\"regexp\"}return t}(s),c=e?\" or javascript `\"+t.toLowerCase()+\"`\":\"\";return new Error(\"Invalid prop `\"+a+\"` of type `\"+l+\"` supplied to `\"+o+\"`, expected `mobx.Observable\"+t+\"`\"+c+\".\")}return null})})}function No(e,t){return Io(function(n,r,o,i,a){for(var s=arguments.length,l=new Array(s>5?s-5:0),c=5;c<s;c++)l[c-5]=arguments[c];return Object(Ne.o)(function(){if(\"function\"!=typeof t)return new Error(\"Property `\"+a+\"` of component `\"+o+\"` has invalid PropType notation.\");var s=Ro(e,\"Array\")(n,r,o);if(s instanceof Error)return s;for(var c=n[r],u=0;u<c.length;u++)if((s=t.apply(void 0,[c,u,o,i,a+\"[\"+u+\"]\"].concat(l)))instanceof Error)return s;return null})})}Ro(!1,\"Array\"),No.bind(null,!1),Ro(!1,\"Map\"),Ro(!1,\"Object\"),Ro(!0,\"Array\"),No.bind(null,!0);var Lo=Ro(!0,\"Object\");var Mo=0;function Do(e){if(\"function\"==typeof Symbol)return Symbol(e);var t=\"__$mobx-react \".concat(e,\" (\").concat(Mo,\")\");return Mo++,t}var Fo=Do(\"patchMixins\"),Uo=Do(\"patchedDefinition\");function Bo(e,t){for(var n=this,r=arguments.length,o=new Array(r>2?r-2:0),i=2;i<r;i++)o[i-2]=arguments[i];t.locks++;try{var a;return null!=e&&(a=e.apply(this,o)),a}finally{t.locks--,0===t.locks&&t.methods.forEach(function(e){e.apply(n,o)})}}function zo(e,t){return function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];Bo.call.apply(Bo,[this,e,t].concat(r))}}function $o(e,t){for(var n=function(e,t){var n=e[Fo]=e[Fo]||{},r=n[t]=n[t]||{};return r.locks=r.locks||0,r.methods=r.methods||[],r}(e,t),r=arguments.length,o=new Array(r>2?r-2:0),i=2;i<r;i++)o[i-2]=arguments[i];for(var a=0;a<o.length;a++){var s=o[a];n.methods.indexOf(s)<0&&n.methods.push(s)}var l=Object.getOwnPropertyDescriptor(e,t);if(!l||!l[Uo]){var c=e[t],u=function e(t,n,r,o,i){var a;var s=zo(i,o);return a={},lo(a,Uo,!0),lo(a,\"get\",function(){return s}),lo(a,\"set\",function(i){if(this===t)s=zo(i,o);else{var a=e(this,n,r,o,i);Object.defineProperty(this,n,a)}}),lo(a,\"configurable\",!0),lo(a,\"enumerable\",r),a}(e,t,l?l.enumerable:void 0,n,c);Object.defineProperty(e,t,u)}}var Wo={mobxStores:Lo};Object.seal(Wo);var qo={contextTypes:{get:function(){return Wo},set:function(e){console.warn(\"Mobx Injector: you are trying to attach `contextTypes` on an component decorated with `inject` (or `observer`) HOC. Please specify the contextTypes on the wrapped component instead. It is accessible through the `wrappedComponent`\")},configurable:!0,enumerable:!1},isMobxInjector:{value:!0,writable:!0,configurable:!0,enumerable:!0}};function Ho(e,t,n){var r=\"inject-\"+(t.displayName||t.name||t.constructor&&t.constructor.name||\"Unknown\");n&&(r+=\"-with-\"+n);var o=function(n){function r(){var e,t;io(this,r);for(var n=arguments.length,o=new Array(n),i=0;i<n;i++)o[i]=arguments[i];return(t=fo(this,(e=uo(r)).call.apply(e,[this].concat(o)))).storeRef=function(e){t.wrappedInstance=e},t}return co(r,p[\"Component\"]),so(r,[{key:\"render\",value:function(){var n={};for(var r in this.props)this.props.hasOwnProperty(r)&&(n[r]=this.props[r]);var o=e(this.context.mobxStores||{},n,this.context)||{};for(var i in o)n[i]=o[i];return function(e){return!(e.prototype&&e.prototype.render)}(t)||(n.ref=this.storeRef),Object(p.createElement)(t,n)}}]),r}();return o.displayName=r,jo(o,t),o.wrappedComponent=t,Object.defineProperties(o,qo),o}function Yo(){var e;if(\"function\"==typeof arguments[0])return e=arguments[0],function(t){var n=Ho(e,t);return n.isMobxInjector=!1,(n=pi(n)).isMobxInjector=!0,n};for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return e=function(e){return function(t,n){return e.forEach(function(e){if(!(e in n)){if(!(e in t))throw new Error(\"MobX injector: Store '\"+e+\"' is not available! Make sure it is provided by some Provider\");n[e]=t[e]}}),n}}(t),function(n){return Ho(e,n,t.join(\"-\"))}}var Vo=Ne.a||\"$mobx\",Qo=Do(\"isUnmounted\"),Go=!1,Xo=!1,Ko=!1,Jo=\"undefined\"!=typeof WeakMap?new WeakMap:void 0,Zo=new Ao,ei=Do(\"skipRender\"),ti=Do(\"isForcingUpdate\"),ni=\"function\"==typeof p.forwardRef&&Object(p.forwardRef)(function(e,t){}).$$typeof;function ri(e,t,n){Object.hasOwnProperty.call(e,t)?e[t]=n:Object.defineProperty(e,t,{enumerable:!1,configurable:!0,writable:!0,value:n})}function oi(e){if(d.findDOMNode)try{return Object(d.findDOMNode)(e)}catch(e){return null}return null}function ii(e){var t=oi(e);t&&Jo&&Jo.set(t,e),Zo.emit({event:\"render\",renderTime:e.__$mobRenderEnd-e.__$mobRenderStart,totalTime:Date.now()-e.__$mobRenderStart,component:e,node:t})}var ai=new Ao;function si(e,t){if(li(e,t))return!0;if(\"object\"!==oo(e)||null===e||\"object\"!==oo(t)||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(var o=0;o<n.length;o++)if(!hasOwnProperty.call(t,n[o])||!li(e[n[o]],t[n[o]]))return!1;return!0}function li(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}var ci={componentWillUnmount:function(){if(!0!==Xo&&(this.render[Vo]&&this.render[Vo].dispose(),this[Qo]=!0,Go)){var e=oi(this);e&&Jo&&Jo.delete(e),Zo.emit({event:\"destroy\",component:this,node:e})}},componentDidMount:function(){Go&&ii(this)},componentDidUpdate:function(){Go&&ii(this)},shouldComponentUpdate:function(e,t){return Xo&&console.warn(\"[mobx-react] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side.\"),this.state!==t||!si(this.props,e)}};function ui(e,t){var n=Do(\"reactProp_\".concat(t,\"_valueHolder\")),r=Do(\"reactProp_\".concat(t,\"_atomHolder\"));function o(){return this[r]||ri(this,r,Object(Ne.g)(\"reactive \"+t)),this[r]}Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return o.call(this).reportObserved(),this[n]},set:function(e){this[ti]||si(this[n],e)?ri(this,n,e):(ri(this,n,e),ri(this,ei,!0),o.call(this).reportChanged(),ri(this,ei,!1))}})}function pi(e,t){if(\"string\"==typeof e)throw new Error(\"Store names should be provided as array\");if(Array.isArray(e))return Ko||(Ko=!0,console.warn('Mobx observer: Using observer to inject stores is deprecated since 4.0. Use `@inject(\"store1\", \"store2\") @observer ComponentClass` or `inject(\"store1\", \"store2\")(observer(componentClass))` instead of `@observer([\"store1\", \"store2\"]) ComponentClass`')),t?Yo.apply(null,e)(pi(t)):function(t){return pi(e,t)};var n=e;if(!0===n.isMobxInjector&&console.warn(\"Mobx observer: You are trying to use 'observer' on a component that already has 'inject'. Please apply 'observer' before applying 'inject'\"),n.__proto__===p.PureComponent&&console.warn(\"Mobx observer: You are using 'observer' on React.PureComponent. These two achieve two opposite goals and should not be used together\"),ni&&n.$$typeof===ni){var r=n.render;if(\"function\"!=typeof r)throw new Error(\"render property of ForwardRef was not a function\");return function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);\"function\"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){lo(e,t,n[t])})}return e}({},n,{render:function(){var e=arguments;return f.a.createElement(fi,null,function(){return r.apply(void 0,e)})}})}if(!(\"function\"!=typeof n||n.prototype&&n.prototype.render||n.isReactClass||p.Component.isPrototypeOf(n))){var o,i,a=pi((i=o=function(e){function t(){return io(this,t),fo(this,uo(t).apply(this,arguments))}return co(t,p[\"Component\"]),so(t,[{key:\"render\",value:function(){return n.call(this,this.props,this.context)}}]),t}(),o.displayName=n.displayName||n.name,o.contextTypes=n.contextTypes,o.propTypes=n.propTypes,o.defaultProps=n.defaultProps,i));return jo(a,n),a}if(!n)throw new Error(\"Please pass a valid component to 'observer'\");var s=n.prototype||n;!function(e){[\"componentDidMount\",\"componentWillUnmount\",\"componentDidUpdate\"].forEach(function(t){!function(e,t){$o(e,t,ci[t])}(e,t)}),e.shouldComponentUpdate?e.shouldComponentUpdate!==ci.shouldComponentUpdate&&console.warn(\"Use `shouldComponentUpdate` in an `observer` based component breaks the behavior of `observer` and might lead to unexpected results. Manually implementing `sCU` should not be needed when using mobx-react.\"):e.shouldComponentUpdate=ci.shouldComponentUpdate}(s),n.isMobXReactObserver=!0,ui(s,\"props\"),ui(s,\"state\");var l=s.render;return s.render=function(){return function(e){var t=this;if(!0===Xo)return e.call(this);function n(){var e=this;a=!1;var t=void 0,n=void 0;if(s.track(function(){Go&&(e.__$mobRenderStart=Date.now());try{n=Object(Ne.c)(!1,i)}catch(e){t=e}Go&&(e.__$mobRenderEnd=Date.now())}),t)throw ai.emit(t),t;return n}var r=this.displayName||this.name||this.constructor&&(this.constructor.displayName||this.constructor.name)||\"<component>\",o=this._reactInternalInstance&&this._reactInternalInstance._rootNodeID||this._reactInternalInstance&&this._reactInternalInstance._debugID||this._reactInternalFiber&&this._reactInternalFiber._debugID;ri(this,ei,!1),ri(this,ti,!1);var i=e.bind(this),a=!1,s=new Ne.b(\"\".concat(r,\"#\").concat(o,\".render()\"),function(){if(!a&&(a=!0,\"function\"==typeof t.componentWillReact&&t.componentWillReact(),!0!==t[Qo])){var e=!0;try{ri(t,ti,!0),t[ei]||p.Component.prototype.forceUpdate.call(t),e=!1}finally{ri(t,ti,!1),e&&s.dispose()}}});return s.reactComponent=this,n[Vo]=s,this.render=n,n.call(this)}.call(this,l)},n}var fi=pi(function(e){var t=e.children,n=e.inject,r=e.render,o=t||r;if(void 0===o)return null;if(!n)return o();console.warn(\"<Observer inject=.../> is no longer supported. Please use inject on the enclosing component instead\");var i=Yo(n)(o);return f.a.createElement(i,null)});fi.displayName=\"Observer\";var di=function(e,t,n,r,o){var i=\"children\"===t?\"render\":\"children\";return\"function\"==typeof e[t]&&\"function\"==typeof e[i]?new Error(\"Invalid prop,do not use children and render in the same time in`\"+n):\"function\"!=typeof e[t]&&\"function\"!=typeof e[i]?new Error(\"Invalid prop `\"+o+\"` of type `\"+oo(e[t])+\"` supplied to `\"+n+\"`, expected `function`.\"):void 0};function hi(){var e=this.constructor.getDerivedStateFromProps(this.props,this.state);null!=e&&this.setState(e)}function mi(e){this.setState(function(t){var n=this.constructor.getDerivedStateFromProps(e,t);return null!=n?n:null}.bind(this))}function gi(e,t){try{var n=this.props,r=this.state;this.props=e,this.state=t,this.__reactInternalSnapshotFlag=!0,this.__reactInternalSnapshot=this.getSnapshotBeforeUpdate(n,r)}finally{this.props=n,this.state=r}}fi.propTypes={render:di,children:di},hi.__suppressDeprecationWarning=!0,mi.__suppressDeprecationWarning=!0,gi.__suppressDeprecationWarning=!0;var yi={children:!0,key:!0,ref:!0},vi=function(e){function t(e,n){var r;return io(this,t),(r=fo(this,uo(t).call(this,e,n))).state={},bi(e,r.state),r}return co(t,p[\"Component\"]),so(t,[{key:\"render\",value:function(){return p.Children.only(this.props.children)}},{key:\"getChildContext\",value:function(){var e={};return bi(this.context.mobxStores,e),bi(this.props,e),{mobxStores:e}}}],[{key:\"getDerivedStateFromProps\",value:function(e,t){if(!e)return null;if(!t)return e;if(Object.keys(e).filter(wi).length!==Object.keys(t).filter(wi).length&&console.warn(\"MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children\"),!e.suppressChangedStoreWarning)for(var n in e)wi(n)&&t[n]!==e[n]&&console.warn(\"MobX Provider: Provided store '\"+n+\"' has changed. Please avoid replacing stores as the change might not propagate to all children\");return e}}]),t}();function bi(e,t){if(e)for(var n in e)wi(n)&&(t[n]=e[n])}function wi(e){return!yi[e]&&\"suppressChangedStoreWarning\"!==e}vi.contextTypes={mobxStores:Lo},vi.childContextTypes={mobxStores:Lo.isRequired},function(e){var t=e.prototype;if(!t||!t.isReactComponent)throw new Error(\"Can only polyfill class components\");if(\"function\"!=typeof e.getDerivedStateFromProps&&\"function\"!=typeof t.getSnapshotBeforeUpdate)return e;var n=null,r=null,o=null;if(\"function\"==typeof t.componentWillMount?n=\"componentWillMount\":\"function\"==typeof t.UNSAFE_componentWillMount&&(n=\"UNSAFE_componentWillMount\"),\"function\"==typeof t.componentWillReceiveProps?r=\"componentWillReceiveProps\":\"function\"==typeof t.UNSAFE_componentWillReceiveProps&&(r=\"UNSAFE_componentWillReceiveProps\"),\"function\"==typeof t.componentWillUpdate?o=\"componentWillUpdate\":\"function\"==typeof t.UNSAFE_componentWillUpdate&&(o=\"UNSAFE_componentWillUpdate\"),null!==n||null!==r||null!==o){var i=e.displayName||e.name,a=\"function\"==typeof e.getDerivedStateFromProps?\"getDerivedStateFromProps()\":\"getSnapshotBeforeUpdate()\";throw Error(\"Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n\"+i+\" uses \"+a+\" but also contains the following legacy lifecycles:\"+(null!==n?\"\\n  \"+n:\"\")+(null!==r?\"\\n  \"+r:\"\")+(null!==o?\"\\n  \"+o:\"\")+\"\\n\\nThe above lifecycles should be removed. Learn more about this warning here:\\nhttps://fb.me/react-async-component-lifecycle-hooks\")}if(\"function\"==typeof e.getDerivedStateFromProps&&(t.componentWillMount=hi,t.componentWillReceiveProps=mi),\"function\"==typeof t.getSnapshotBeforeUpdate){if(\"function\"!=typeof t.componentDidUpdate)throw new Error(\"Cannot polyfill getSnapshotBeforeUpdate() for components that do not define componentDidUpdate() on the prototype\");t.componentWillUpdate=gi;var s=t.componentDidUpdate;t.componentDidUpdate=function(e,t,n){var r=this.__reactInternalSnapshotFlag?this.__reactInternalSnapshot:n;s.call(this,e,t,r)}}}(vi);Do(\"disposeOnUnmount\");if(!p.Component)throw new Error(\"mobx-react requires React to be available\");if(!Ne.n)throw new Error(\"mobx-react requires mobx to be available\");\"function\"==typeof d.unstable_batchedUpdates&&Object(Ne.f)({reactionScheduler:d.unstable_batchedUpdates});if(\"object\"===(\"undefined\"==typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__?\"undefined\":oo(__MOBX_DEVTOOLS_GLOBAL_HOOK__))){var xi={spy:Ne.n,extras:{getDebugName:Ne.h}},ki={renderReporter:Zo,componentByNodeRegistry:Jo,componentByNodeRegistery:Jo,trackComponents:function(){if(\"undefined\"==typeof WeakMap)throw new Error(\"[mobx-react] tracking components is not supported in this browser.\");Go||(Go=!0)}};__MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobxReact(ki,xi)}var Ei=Ee.div.withConfig({componentId:\"sc-1whyat8-0\"})([\"\",\";\",\"\"],qr,function(e){return e.compact?\"\":\"margin: 1em 0\"}),Si=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.externalDocs;return e&&e.url?p.createElement(Ei,{compact:this.props.compact},p.createElement(\"a\",{href:e.url},e.description||e.url)):null},t=s([pi],t)}(p.Component),_i=Ee(tn).withConfig({componentId:\"sc-1mcjnf5-0\"})([\"margin-top:0;margin-bottom:0.5em;\",\";\"],Se(\"ApiHeader\")),Oi=Ee.a.withConfig({componentId:\"sc-1mcjnf5-1\"})([\"border:1px solid \",\";color:\",\";font-weight:normal;margin-left:0.5em;padding:4px 8px 4px;display:inline-block;text-decoration:none;cursor:pointer;\",\";\"],function(e){return e.theme.colors.primary.main},function(e){return e.theme.colors.primary.main},Se(\"DownloadButton\")),Ci=Ee.span.withConfig({componentId:\"sc-1mcjnf5-2\"})([\"&::before{content:'|';display:inline-block;opacity:0.5;width:\",\"px;text-align:center;}&:last-child::after{display:none;}\"],15),Ti=Ee.div.withConfig({componentId:\"sc-1mcjnf5-3\"})([\"overflow:hidden;\"]),ji=Ee.div.withConfig({componentId:\"sc-1mcjnf5-4\"})([\"display:flex;flex-wrap:wrap;margin-left:-\",\"px;\"],15),Ai=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.handleDownloadClick=function(e){e.target.href||(e.target.href=t.props.store.spec.info.downloadLink)},t}return i(t,e),t.prototype.render=function(){var e=this.props.store,t=e.spec,n=t.info,r=t.externalDocs,o=e.options.hideDownloadButton,i=n.downloadFileName,a=n.downloadLink,s=n.license&&p.createElement(Ci,null,\"License: \",p.createElement(\"a\",{href:n.license.url},n.license.name))||null,l=n.contact&&n.contact.url&&p.createElement(Ci,null,\"URL: \",p.createElement(\"a\",{href:n.contact.url},n.contact.url))||null,c=n.contact&&n.contact.email&&p.createElement(Ci,null,n.contact.name||\"E-mail\",\":\",\" \",p.createElement(\"a\",{href:\"mailto:\"+n.contact.email},n.contact.email))||null,u=n.termsOfService&&p.createElement(Ci,null,p.createElement(\"a\",{href:n.termsOfService},\"Terms of Service\"))||null;return p.createElement(Gt,null,p.createElement(Jt,null,p.createElement(Qt,{className:\"api-info\"},p.createElement(_i,null,n.title,\" \",p.createElement(\"span\",null,\"(\",n.version,\")\")),!o&&p.createElement(\"p\",null,\"Download OpenAPI specification:\",p.createElement(Oi,{download:i,target:\"_blank\",href:a,onClick:this.handleDownloadClick},\"Download\")),p.createElement(Hr,null,(n.license||n.contact||n.termsOfService)&&p.createElement(Ti,null,p.createElement(ji,null,c,\" \",l,\" \",s,\" \",u))||null),p.createElement(Xr,{source:e.spec.info.description}),r&&p.createElement(Si,{externalDocs:r}))))},t=s([pi],t)}(p.Component),Ii=Ee.img.withConfig({componentId:\"sc-1ypz5kk-0\"})([\"max-height:\",\";max-width:\",\";width:100%;display:block;\"],function(e){return e.theme.logo.maxHeight},function(e){return e.theme.logo.maxWidth}),Pi=Ee.div.withConfig({componentId:\"sc-1ypz5kk-1\"})([\"text-align:center;\"]),Ri=Ee.a.withConfig({componentId:\"sc-1ypz5kk-2\"})([\"display:inline-block;\"]),Ni=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.info,t=e[\"x-logo\"];if(!t||!t.url)return null;var n,r=t.href||e.contact&&e.contact.url,o=t.altText?t.altText:\"logo\",i=p.createElement(Ii,{src:t.url,style:{backgroundColor:t.backgroundColor},alt:o});return p.createElement(Pi,null,r?(n=r,function(e){return p.createElement(Ri,{href:n},e)})(i):i)},t=s([pi],t)}(p.Component),Li=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this;return p.createElement(Re,null,function(t){return p.createElement(cn,null,function(n){return e.renderWithOptionsAndStore(t,n)})})},t.prototype.renderWithOptionsAndStore=function(e,t){var n=this.props,r=n.source,o=n.htmlWrap,i=void 0===o?function(e){return e}:o;if(!t)throw new Error(\"When using componentes in markdown, store prop must be provided\");var s=new vt(e).renderMdWithComponents(r);return s.length?s.map(function(e,n){return\"string\"==typeof e?p.cloneElement(i(p.createElement(Qr,{html:e,inline:!1,compact:!1})),{key:n}):p.createElement(e.component,a({key:n},a({},e.props,e.propsSelector(t))))}):null},t}(p.Component),Mi=Ee.code.withConfig({componentId:\"zmmjx2-0\"})([\"font-size:\",\";font-family:\",\";border:1px solid \",\";margin:0 3px;padding:0.2em;display:inline-block;line-height:1;&:after{content:',';}&:last-child:after{content:none;}\"],function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.colors.border.dark}),Di=Ee.span.withConfig({componentId:\"zmmjx2-1\"})([\"&:after{content:' AND ';font-weight:bold;}&:last-child:after{content:none;}\",\";\"],qr),Fi=Ee.span.withConfig({componentId:\"zmmjx2-2\"})([\"&:before{content:'( ';font-weight:bold;}&:after{content:' ) OR ';font-weight:bold;}&:last-child:after{content:' )';}&:only-child:before,&:only-child:after{content:none;}\",\";\"],qr),Ui=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.security;return p.createElement(Fi,null,e.schemes.map(function(e){return p.createElement(Di,{key:e.id},p.createElement(dn,{to:e.sectionId},e.id),e.scopes.length>0&&\" (\",e.scopes.map(function(e){return p.createElement(Mi,{key:e},e)}),e.scopes.length>0&&\") \")}))},t}(p.PureComponent),Bi=Ee.div.withConfig({componentId:\"zmmjx2-3\"})([\"flex:1;\"]),zi=Ee.div.withConfig({componentId:\"zmmjx2-4\"})([\"width:\",\";\"],function(e){return e.theme.schema.defaultDetailsWidth}),$i=Ee(on).withConfig({componentId:\"zmmjx2-5\"})([\"display:inline-block;margin:0;\"]),Wi=Ee.div.withConfig({componentId:\"zmmjx2-6\"})([\"width:100%;display:flex;margin:1em 0;\"]),qi=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.securities;return e.length?p.createElement(Wi,null,p.createElement(Bi,null,p.createElement($i,null,\"Authorizations: \")),p.createElement(zi,null,e.map(function(e,t){return p.createElement(Ui,{key:t,security:e})}))):null},t}(p.PureComponent),Hi=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.handleClick=function(){ro.selectElement(t.child)},t}return i(t,e),t.prototype.render=function(){var e=this,t=this.props.children;return p.createElement(\"div\",{ref:function(t){return e.child=t},onClick:this.handleClick},t)},t}(p.PureComponent),Yi=Ee.div.withConfig({componentId:\"nrhuz6-0\"})([\"cursor:pointer;position:relative;margin-bottom:5px;\"]),Vi=Ee.span.withConfig({componentId:\"nrhuz6-1\"})([\"font-family:\",\";margin-left:10px;flex:1;overflow-x:hidden;text-overflow:ellipsis;\"],function(e){return e.theme.typography.headings.fontFamily}),Qi=Ee.div.withConfig({componentId:\"nrhuz6-2\"})([\"padding:10px 30px 10px \",\";border-radius:\",\";background-color:\",\";display:flex;white-space:nowrap;align-items:center;border:\",\";border-bottom:\",\";transition:border-color 0.25s ease;\",\" .\",\"{color:\",\"}\"],function(e){return e.inverted?\"10px\":\"20px\"},function(e){return e.inverted?\"0\":\"4px 4px 0 0\"},function(e){return e.inverted?\"transparent\":e.theme.codeSample.backgroundColor},function(e){return e.inverted?\"0\":\"1px solid transparent\"},function(e){return e.inverted?\"1px solid #ccc\":\"0\"},function(e){return e.expanded&&!e.inverted&&\"border-color: \"+e.theme.colors.border.dark+\";\"||\"\"},Vi,function(e){return e.inverted?e.theme.colors.text.primary:\"#ffffff\"}),Gi=Ee.span.attrs(function(e){return{className:\"http-verb \"+e.type}}).withConfig({componentId:\"nrhuz6-3\"})([\"font-size:0.929em;line-height:20px;background-color:\",\";color:#ffffff;padding:3px 10px;text-transform:uppercase;font-family:\",\";margin:0;\"],function(e){return e.theme.colors.http[e.type]||\"#999999\"},function(e){return e.theme.typography.headings.fontFamily}),Xi=Ee.div.withConfig({componentId:\"nrhuz6-4\"})([\"position:absolute;width:100%;z-index:100;background:#fafafa;color:#263238;box-sizing:border-box;box-shadow:0px 0px 6px rgba(0,0,0,0.33);overflow:hidden;border-bottom-left-radius:4px;border-bottom-right-radius:4px;transition:all 0.25s ease;\",\"\"],function(e){return e.expanded?\"\":\"transform: translateY(-50%) scaleY(0);\"}),Ki=Ee.div.withConfig({componentId:\"nrhuz6-5\"})([\"padding:10px;\"]),Ji=Ee.div.withConfig({componentId:\"nrhuz6-6\"})([\"padding:5px;border:1px solid #ccc;background:#fff;word-break:break-all;color:\",\";> span{color:\",\";}\"],function(e){return e.theme.colors.primary.main},function(e){return e.theme.colors.text.primary}),Zi=function(e){function t(t){var n=e.call(this,t)||this;return n.toggle=function(){n.setState({expanded:!n.state.expanded})},n.state={expanded:!1},n}return i(t,e),t.prototype.render=function(){var e=this,t=this.props,n=t.operation,r=t.inverted,o=t.hideHostname,i=this.state.expanded;return p.createElement(Ie.Consumer,null,function(t){return p.createElement(Yi,null,p.createElement(Qi,{onClick:e.toggle,expanded:i,inverted:r},p.createElement(Gi,{type:n.httpVerb},\" \",n.httpVerb),\" \",p.createElement(Vi,null,n.path),p.createElement(yn,{float:\"right\",color:r?\"black\":\"white\",size:\"20px\",direction:i?\"up\":\"down\",style:{marginRight:\"-25px\"}})),p.createElement(Xi,{expanded:i},n.servers.map(function(e){return p.createElement(Ki,{key:e.url},p.createElement(Xr,{source:e.description||\"\",compact:!0}),p.createElement(Hi,null,p.createElement(Ji,null,p.createElement(\"span\",null,o||t.hideHostname?(r=e.url,new URL(r).pathname):e.url),n.path)));var r})))})},t}(p.Component);function ea(e){var t=e.Label,n=void 0===t?Mn:t,r=e.Dropdown,o=void 0===r?Ln:r;return 1===e.options.length?p.createElement(n,null,e.options[0].label):p.createElement(o,a({},e))}var ta=Ee(En).withConfig({componentId:\"sc-1noysbl-0\"})([\"cursor:pointer;\",\"{height:\",\";width:\",\";polygon{fill:\",\";}}\"],yn,function(e){return e.theme.schema.arrow.size},function(e){return e.theme.schema.arrow.size},function(e){return e.theme.schema.arrow.color}),na=Ee.span.withConfig({componentId:\"sc-1noysbl-1\"})([\"vertical-align:middle;font-size:\",\";line-height:20px;\"],function(e){return e.theme.typography.code.fontSize}),ra=Ee(na).withConfig({componentId:\"sc-1noysbl-2\"})([\"color:\",\";\"],function(e){return ee(.2,e.theme.schema.typeNameColor)}),oa=Ee(na).withConfig({componentId:\"sc-1noysbl-3\"})([\"color:\",\";\"],function(e){return e.theme.schema.typeNameColor}),ia=Ee(na).withConfig({componentId:\"sc-1noysbl-4\"})([\"color:\",\";\"],function(e){return e.theme.schema.typeTitleColor}),aa=oa,sa=Ee(na.withComponent(\"div\")).withConfig({componentId:\"sc-1noysbl-5\"})([\"color:\",\";font-size:\",\";font-weight:normal;margin-left:20px;line-height:1;\"],function(e){return e.theme.schema.requireLabelColor},function(e){return e.theme.schema.labelsTextSize}),la=Ee(na).withConfig({componentId:\"sc-1noysbl-6\"})([\"color:\",\";font-size:13px;\"],function(e){return e.theme.colors.warning.main}),ca=Ee(na).withConfig({componentId:\"sc-1noysbl-7\"})([\"color:#3195a6;font-size:13px;\"]),ua=Ee(na).withConfig({componentId:\"sc-1noysbl-8\"})([\"color:#3195a6;&::before,&::after{font-weight:bold;}&::before{content:' /';}&::after{content:'/ ';}\"]),pa=Ee(na).withConfig({componentId:\"sc-1noysbl-9\"})([\"border-radius:2px;\",\";& + &{margin-left:0;}\",\";\"],function(e){var t=e.theme;return\"\\n    background-color: \"+ee(.95,t.colors.text.primary)+\";\\n    color: \"+ee(.1,t.colors.text.primary)+\";\\n\\n    margin: \"+t.spacing.unit+\"px;\\n    padding: 0 \"+t.spacing.unit+\"px;\\n    border: 1px solid \"+ee(.9,t.colors.text.primary)+\";\\n    font-family: \"+t.typography.code.fontFamily+\";\\n    color: \"+t.typography.code.color+\";\\n}\"},Se(\"ExampleValue\")),fa=Ee(na).withConfig({componentId:\"sc-1noysbl-10\"})([\"border-radius:2px;\",\";& + &{margin-left:0;}\",\";\"],function(e){var t=e.theme;return\"\\n    background-color: \"+ee(.95,t.colors.primary.light)+\";\\n    color: \"+ee(.1,t.colors.primary.main)+\";\\n\\n    margin: 0 \"+t.spacing.unit+\"px;\\n    padding: 0 \"+t.spacing.unit+\"px;\\n    border: 1px solid \"+ee(.9,t.colors.primary.main)+\";\\n}\"},Se(\"ConstraintItem\")),da=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.values,n=e.type;return t.length?p.createElement(\"div\",null,p.createElement(na,null,\"array\"===n?\"Items\":\"\",\" \",1===t.length?\"Value\":\"Enum\",\":\"),t.map(function(e,t){return p.createElement(pa,{key:t},JSON.stringify(e),\" \")})):null},t}(p.PureComponent),ha=Ee(Hr).withConfig({componentId:\"sc-12fpph1-0\"})([\"opacity:0.9;margin:2px 0;\"]),ma=Ee.span.withConfig({componentId:\"sc-12fpph1-1\"})([\"font-style:italic;\"]),ga=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this;return p.createElement(Ie.Consumer,null,function(t){return p.createElement(p.Fragment,null,t.showExtensions&&Object.keys(e.props.extensions).map(function(t){return p.createElement(ha,{key:t},p.createElement(ma,null,t),\":\",\" \",p.createElement(\"code\",null,JSON.stringify(e.props.extensions[t])))}))})},t}(p.PureComponent),ya=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return 0===this.props.constraints.length?null:p.createElement(\"span\",null,\" \",this.props.constraints.map(function(e){return p.createElement(fa,{key:e},\" \",e,\" \")}))},t}(p.PureComponent),va=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return void 0===this.props.value?null:p.createElement(\"div\",null,p.createElement(na,null,\" \",this.props.label,\" \"),\" \",p.createElement(pa,null,\" \",JSON.stringify(this.props.value),\" \"))},t}(p.PureComponent),ba=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.showExamples,n=e.field,r=e.renderDiscriminatorSwitch,o=n.schema,i=n.description,s=n.example,l=n.deprecated;return p.createElement(\"div\",null,p.createElement(\"div\",null,p.createElement(ra,null,o.typePrefix),p.createElement(oa,null,o.displayType),o.displayFormat&&p.createElement(aa,null,\" \",\"<\",o.displayFormat,\">\",\" \"),o.title&&p.createElement(ia,null,\" (\",o.title,\") \"),p.createElement(ya,{constraints:o.constraints}),o.nullable&&p.createElement(ca,null,\" Nullable \"),o.pattern&&p.createElement(ua,null,o.pattern),o.isCircular&&p.createElement(la,null,\" Recursive \")),l&&p.createElement(\"div\",null,p.createElement(vn,{type:\"warning\"},\" Deprecated \")),p.createElement(va,{label:\"Default:\",value:o.default}),!r&&p.createElement(da,{type:o.type,values:o.enum}),\" \",t&&p.createElement(va,{label:\"Example:\",value:s}),p.createElement(ga,{extensions:a({},n.extensions,o.extensions)}),p.createElement(\"div\",null,p.createElement(Xr,{compact:!0,source:i})),o.externalDocs&&p.createElement(Si,{externalDocs:o.externalDocs,compact:!0}),r&&r(this.props)||null)},t}(p.PureComponent),wa=Ee.div.withConfig({componentId:\"sc-71zhzb-0\"})([\"padding-left:\",\"px;\"],function(e){return 2*e.theme.spacing.unit}),xa=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.schema.items;return p.createElement(\"div\",null,p.createElement(In,null,\" Array \"),p.createElement(wa,null,p.createElement(Oa,a({},this.props,{schema:e}))),p.createElement(Pn,null))},t}(p.PureComponent),ka=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.changeActiveChild=function(e){var n=e.value,r=parseInt(n,10);t.props.parent.activateOneOf(r)},t}return i(t,e),t.prototype.sortOptions=function(e,t){if(0!==t.length){var n={};t.forEach(function(e,t){n[e]=t}),e.sort(function(e,t){return n[e.label]>n[t.label]?1:-1})}},t.prototype.render=function(){var e=this.props,t=e.parent,n=e.enumValues;if(void 0===t.oneOf)return null;var r=t.oneOf.map(function(e,t){return{value:t.toString(),label:e.title}}),o=r[t.activeOneOf];return this.sortOptions(r,n),p.createElement(Nn,{value:o,options:r,onChange:this.changeActiveChild})},t=s([pi],t)}(p.Component),Ea=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),Object.defineProperty(t.prototype,\"parentSchema\",{get:function(){return this.props.discriminator.parentSchema},enumerable:!0,configurable:!0}),t.prototype.render=function(){var e=this,t=this.props,n=t.schema.fields,r=void 0===n?[]:n,o=t.showTitle,i=t.discriminator,a=this.props.skipReadOnly||this.props.skipWriteOnly?r.filter(function(t){return e.props.skipReadOnly&&!t.schema.readOnly||e.props.skipWriteOnly&&!t.schema.writeOnly}):r;return p.createElement(Cn,null,o&&p.createElement(wn,null,this.props.schema.title),p.createElement(\"tbody\",null,se(a,function(t,n){return p.createElement(Ca,{key:t.name,isLast:n,field:t,renderDiscriminatorSwitch:i&&i.fieldName===t.name&&function(){return p.createElement(ka,{parent:e.parentSchema,enumValues:t.schema.enum})}||void 0,className:t.expanded?\"expanded\":void 0,showExamples:!1,skipReadOnly:e.props.skipReadOnly,skipWriteOnly:e.props.skipWriteOnly,showTitle:e.props.showTitle})})))},t=s([pi],t)}(p.Component),Sa=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.activateOneOf=function(){t.props.schema.activateOneOf(t.props.idx)},t}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.idx,n=e.schema,r=e.subSchema;return p.createElement(An,{active:t===n.activeOneOf,onClick:this.activateOneOf},r.title||r.typePrefix+r.displayType)},t=s([pi],t)}(p.Component),_a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.schema.oneOf,n=e.schema;return void 0===t?null:p.createElement(\"div\",null,p.createElement(jn,null,\" \",n.oneOfType,\" \"),p.createElement(Tn,null,t.map(function(e,t){return p.createElement(Sa,{key:e.pointer,schema:n,subSchema:e,idx:t})})),p.createElement(Oa,a({},this.props,{schema:t[n.activeOneOf]})))},t=s([pi],t)}(p.Component),Oa=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.schema;if(!e)return p.createElement(\"em\",null,\" Schema not provided \");var t=e.type,n=e.oneOf,r=e.discriminatorProp;if(e.isCircular)return p.createElement(\"div\",null,p.createElement(oa,null,e.displayType),e.title&&p.createElement(ia,null,\" \",e.title,\" \"),p.createElement(la,null,\" Recursive \"));if(void 0!==r){if(!n||!n.length)throw new Error(\"Looks like you are using discriminator wrong: you don't have any definition inherited from the \"+e.title);return p.createElement(Ea,a({},a({},this.props,{schema:n[e.activeOneOf]}),{discriminator:{fieldName:r,parentSchema:e}}))}if(void 0!==n)return p.createElement(_a,a({schema:e},this.props));switch(t){case\"object\":return p.createElement(Ea,a({},this.props));case\"array\":return p.createElement(xa,a({},this.props))}var o={schema:e,name:\"\",required:!1,description:e.description,externalDocs:e.externalDocs,deprecated:!1,toggle:function(){return null},expanded:!1};return p.createElement(\"div\",null,p.createElement(ba,{field:o}))},t=s([pi],t)}(p.Component),Ca=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.toggle=function(){t.props.field.toggle()},t}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.className,n=e.field,r=e.isLast,o=n.name,i=n.expanded,s=n.deprecated,l=n.required,c=n.kind,u=!n.schema.isPrimitive&&!n.schema.isCircular,f=u?p.createElement(ta,{onClick:this.toggle,className:s?\"deprecated\":\"\",kind:c,title:o},p.createElement(_n,null),o,p.createElement(yn,{direction:i?\"down\":\"right\"}),l&&p.createElement(sa,null,\" required \")):p.createElement(En,{className:s?\"deprecated\":void 0,kind:c,title:o},p.createElement(_n,null),o,l&&p.createElement(sa,null,\" required \"));return p.createElement(p.Fragment,null,p.createElement(\"tr\",{className:r?\"last \"+t:t},f,p.createElement(Sn,null,p.createElement(ba,a({},this.props)))),n.expanded&&u&&p.createElement(\"tr\",{key:n.name+\"inner\"},p.createElement(kn,{colSpan:2},p.createElement(On,null,p.createElement(Oa,{schema:n.schema,skipReadOnly:this.props.skipReadOnly,skipWriteOnly:this.props.skipWriteOnly,showTitle:this.props.showTitle})))))},t=s([pi],t)}(p.Component),Ta=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.place,n=e.parameters;return n&&n.length?p.createElement(\"div\",{key:t},p.createElement(on,null,t,\" Parameters\"),p.createElement(Cn,null,p.createElement(\"tbody\",null,se(n,function(e,t){return p.createElement(Ca,{key:e.name,isLast:t,field:e,showExamples:!0})})))):null},t}(p.PureComponent),ja=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.switchMedia=function(e){var n=e.value;t.props.content&&t.props.content.activate(parseInt(n,10))},t}return i(t,e),t.prototype.render=function(){var e=this.props.content;if(!e||!e.mediaTypes||!e.mediaTypes.length)return null;var t=e.activeMimeIdx,n=e.mediaTypes.map(function(e,t){return{label:e.name,value:t.toString()}});return p.createElement(p.Fragment,null,this.props.renderDropdown({value:n[t],options:n,onChange:this.switchMedia}),this.props.children(e.active))},t=s([pi],t)}(p.Component);var Aa=[\"path\",\"query\",\"cookie\",\"header\"],Ia=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.orderParams=function(e){var t={};return e.forEach(function(e){var n,r,o;n=t,r=e.in,o=e,n[r]||(n[r]=[]),n[r].push(o)}),t},t.prototype.render=function(){var e=this.props,t=e.body,n=e.parameters,r=void 0===n?[]:n;if(void 0===t&&void 0===r)return null;var o=this.orderParams(r),i=r.length>0?Aa:[],a=t&&t.content;return p.createElement(\"div\",null,i.map(function(e){return p.createElement(Ta,{key:e,place:e,parameters:o[e]})}),a&&p.createElement(Ra,{content:a}))},t}(p.PureComponent);function Pa(e){return p.createElement(on,{key:\"header\"},\"Request Body schema: \",p.createElement(ea,a({},e)))}function Ra(e){var t=e.content;return p.createElement(ja,{content:t,renderDropdown:Pa},function(e){var t=e.schema;return p.createElement(Oa,{skipReadOnly:!0,key:\"schema\",schema:t})})}var Na=Ee.div.withConfig({componentId:\"t0v3fg-0\"})([\"position:relative;\"]),La=Ee.div.withConfig({componentId:\"t0v3fg-1\"})([\"position:absolute;min-width:80px;max-width:500px;background:#fff;bottom:100%;left:50%;margin-bottom:10px;transform:translateX(-50%);border-radius:4px;padding:0.3em 0.6em;text-align:center;box-shadow:0px 0px 5px 0px rgba(204,204,204,1);\"]),Ma=Ee.div.withConfig({componentId:\"t0v3fg-2\"})([\"background:#fff;color:#000;display:inline;font-size:0.85em;white-space:nowrap;\"]),Da=Ee.div.withConfig({componentId:\"t0v3fg-3\"})([\"position:absolute;width:0;height:0;bottom:-5px;left:50%;margin-left:-5px;border-left:solid transparent 5px;border-right:solid transparent 5px;border-top:solid #fff 5px;\"]),Fa=Ee.div.withConfig({componentId:\"t0v3fg-4\"})([\"position:absolute;width:100%;height:20px;bottom:-20px;\"]),Ua=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.open,n=e.title,r=e.children;return p.createElement(Na,null,r,t&&p.createElement(La,null,p.createElement(Ma,null,n),p.createElement(Da,null),p.createElement(Fa,null)))},t}(p.Component),Ba=function(e){function t(t){var n=e.call(this,t)||this;return n.copy=function(){var e=\"string\"==typeof n.props.data?n.props.data:JSON.stringify(n.props.data,null,2);ro.copyCustom(e),n.showTooltip()},n.renderCopyButton=function(){return p.createElement(\"span\",{onClick:n.copy},p.createElement(Ua,{title:ro.isSupported()?\"Copied\":\"Not supported in your browser\",open:n.state.tooltipShown},\"Copy\"))},n.state={tooltipShown:!1},n}return i(t,e),t.prototype.render=function(){return this.props.children({renderCopyButton:this.renderCopyButton})},t.prototype.showTooltip=function(){var e=this;this.setState({tooltipShown:!0}),setTimeout(function(){e.setState({tooltipShown:!1})},1500)},t}(p.PureComponent),za=1,$a=2;function Wa(e){return void 0!==e?e.toString().replace(/&/g,\"&amp;\").replace(/\"/g,\"&quot;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\"):\"\"}function qa(e,t){return'<span class=\"'+t+'\">'+Wa(e)+\"</span>\"}function Ha(e){return'<span class=\"token punctuation\">'+e+\"</span>\"}function Ya(e){var t=typeof e,n=\"\";return null==e?n+=qa(\"null\",\"token keyword\"):e&&e.constructor===Array?(za++,n+=function(e){for(var t=za>$a?\"collapsed\":\"\",n='<div class=\"collapser\"></div>'+Ha(\"[\")+'<span class=\"ellipsis\"></span><ul class=\"array collapsible\">',r=!1,o=e.length,i=0;i<o;i++)r=!0,n+='<li><div class=\"hoverable '+t+'\">',n+=Ya(e[i]),i<o-1&&(n+=\",\"),n+=\"</div></li>\";n+=\"</ul>\"+Ha(\"]\"),r||(n=Ha(\"[ ]\"));return n}(e),za--):e&&e.constructor===Date?n+=qa('\"'+e.toISOString()+'\"',\"token string\"):\"object\"===t?(za++,n+=function(e){for(var t=za>$a?\"collapsed\":\"\",n=Object.keys(e),r=n.length,o='<div class=\"collapser\"></div>'+Ha(\"{\")+'<span class=\"ellipsis\"></span><ul class=\"obj collapsible\">',i=!1,a=0;a<r;a++){var s=n[a];i=!0,o+='<li><div class=\"hoverable '+t+'\">',o+='<span class=\"property token string\">\"'+Wa(s)+'\"</span>: ',o+=Ya(e[s]),a<r-1&&(o+=Ha(\",\")),o+=\"</div></li>\"}o+=\"</ul>\"+Ha(\"}\"),i||(o=Ha(\"{ }\"));return o}(e),za--):\"number\"===t?n+=qa(e,\"token number\"):\"string\"===t?/^(http|https):\\/\\/[^\\s]+$/.test(e)?n+=qa('\"',\"token string\")+'<a href=\"'+e+'\">'+Wa(e)+\"</a>\"+qa('\"',\"token string\"):n+=qa('\"'+e+'\"',\"token string\"):\"boolean\"===t&&(n+=qa(e,\"token boolean\")),n}var Va=ve([\".redoc-json > .collapser{display:none;}font-family:\",\";font-size:\",\";white-space:\",\";contain:content;overflow-x:auto;.callback-function{color:gray;}.collapser:after{content:'-';cursor:pointer;}.collapsed > .collapser:after{content:'+';cursor:pointer;}.ellipsis:after{content:' … ';}.collapsible{margin-left:2em;}.hoverable{padding-top:1px;padding-bottom:1px;padding-left:2px;padding-right:2px;border-radius:2px;}.hovered{background-color:rgba(235,238,249,1);}.collapser{padding-right:6px;padding-left:6px;}ul{list-style-type:none;padding:0px;margin:0px 0px 0px 26px;}li{position:relative;display:block;}.hoverable{display:inline-block;}.selected{outline-style:solid;outline-width:1px;outline-style:dotted;}.collapsed > .collapsible{display:none;}.ellipsis{display:none;}.collapsed > .ellipsis{display:inherit;}.collapser{position:absolute;top:1px;left:-1.5em;cursor:default;user-select:none;-webkit-user-select:none;}\"],function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.typography.code.wrap?\"pre-wrap\":\"pre\"}),Qa=Ee.div.withConfig({componentId:\"sc-1d3n1g3-0\"})([\"&:hover > \",\"{opacity:1;}\"],lr),Ga=Ee(function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.renderInner=function(e){var n=e.renderCopyButton;return p.createElement(Qa,null,p.createElement(lr,null,n(),p.createElement(\"span\",{onClick:t.expandAll},\" Expand all \"),p.createElement(\"span\",{onClick:t.collapseAll},\" Collapse all \")),p.createElement(Wr,{className:t.props.className,ref:function(e){return t.node=e},dangerouslySetInnerHTML:{__html:function(e){za=1;var t=\"\";return t+='<div class=\"redoc-json\">',t+=Ya(e),t+=\"</div>\"}(t.props.data)}}))},t.expandAll=function(){for(var e=t.node.getElementsByClassName(\"collapsible\"),n=0,r=Array.prototype.slice.call(e);n<r.length;n++){r[n].parentNode.classList.remove(\"collapsed\")}},t.collapseAll=function(){for(var e=t.node.getElementsByClassName(\"collapsible\"),n=0,r=Array.prototype.slice.call(e);n<r.length;n++){var o=r[n];o.parentNode.classList.contains(\"redoc-json\")||o.parentNode.classList.add(\"collapsed\")}},t.clickListener=function(e){var t,n=e.target;\"collapser\"===n.className&&((t=n.parentElement.getElementsByClassName(\"collapsible\")[0]).parentElement.classList.contains(\"collapsed\")?t.parentElement.classList.remove(\"collapsed\"):t.parentElement.classList.add(\"collapsed\"))},t}return i(t,e),t.prototype.render=function(){return p.createElement(Ba,{data:this.props.data},this.renderInner)},t.prototype.componentDidMount=function(){this.node.addEventListener(\"click\",this.clickListener)},t.prototype.componentWillUnmount=function(){this.node.removeEventListener(\"click\",this.clickListener)},t}(p.PureComponent)).withConfig({componentId:\"sc-1d3n1g3-1\"})([\"\",\";\"],Va),Xa=Ee(Wr.withComponent(\"pre\")).withConfig({componentId:\"sc-166mz29-0\"})([\"font-family:\",\";font-size:\",\";overflow-x:auto;margin:0;white-space:\",\";\"],function(e){return e.theme.typography.code.fontFamily},function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.typography.code.wrap?\"pre-wrap\":\"pre\"}),Ka=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.source,n=e.lang;return p.createElement(Xa,{dangerouslySetInnerHTML:{__html:it(t,n)}})},t}(p.PureComponent),Ja=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this;return p.createElement(Ba,{data:this.props.source},function(t){var n=t.renderCopyButton;return p.createElement(cr,null,p.createElement(lr,null,n()),p.createElement(Ka,{lang:e.props.lang,source:e.props.source}))})},t}(p.PureComponent),Za=Ee.div.withConfig({componentId:\"futasu-0\"})([\"border-bottom:1px solid rgba(255,255,255,0.9);margin:0 0 10px 0;display:block;color:rgba(255,255,255,0.8);\"]),es=Ee(Nn).withConfig({componentId:\"futasu-1\"})([\"margin-left:10px;text-transform:none;font-size:0.929em;border-bottom:1px solid \",\";margin:0 0 10px 0;display:block;.Dropdown-control,.Dropdown-control:hover{font-size:1em;border:none;padding:0 1.2em 0 0;background:transparent;color:\",\";box-shadow:none;.Dropdown-arrow{border-top-color:\",\";}}.Dropdown-menu{margin:0;}\"],function(e){return e.theme.rightPanel.textColor},function(e){return e.theme.rightPanel.textColor},function(e){return e.theme.rightPanel.textColor}),ts=Ee.div.withConfig({componentId:\"futasu-2\"})([\"font-family:\",\";font-size:12px;color:#ee807f;\"],function(e){return e.theme.typography.code.fontFamily}),ns=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.mediaType.examples||{},t=this.props.mediaType.name,n=p.createElement(ts,null,\"No sample\"),r=Ge(t)?function(e){return p.createElement(Ga,{data:e})}:function(e){return void 0!==e&&p.createElement(Ja,{lang:(r=t,-1!==r.search(/xml/i)?\"xml\":\"clike\"),source:e})||n;var r},o=Object.keys(e);if(0===o.length)return n;if(o.length>1)return p.createElement(sr,{defaultIndex:0},p.createElement(tr,null,o.map(function(t){return p.createElement(rr,{key:t},\" \",e[t].summary||t,\" \")})),o.map(function(t){return p.createElement(ir,{key:t},r(e[t].value))}));var i=o[0];return p.createElement(\"div\",null,r(e[i].value))},t}(p.Component),rs=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.renderDropdown=function(e){return p.createElement(ea,a({Label:Za,Dropdown:es},e))},t}return i(t,e),t.prototype.render=function(){var e=this.props.content;return void 0===e?null:p.createElement(ja,{content:e,renderDropdown:this.renderDropdown},function(e){return p.createElement(ns,{key:\"samples\",mediaType:e})})},t=s([pi],t)}(p.Component),os=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.operation,t=e.requestBody&&e.requestBody.content,n=t&&t.hasSample,r=e.codeSamples;return(n||r.length>0)&&p.createElement(\"div\",null,p.createElement(rn,null,\" Request samples \"),p.createElement(ar,{defaultIndex:0},p.createElement(tr,null,n&&p.createElement(rr,{key:\"payload\"},\" Payload \"),r.map(function(e){return p.createElement(rr,{key:e.lang},void 0!==e.label?e.label:e.lang)})),n&&p.createElement(ir,{key:\"payload\"},p.createElement(\"div\",null,p.createElement(rs,{content:t}))),r.map(function(e){return p.createElement(ir,{key:e.lang},p.createElement(Ja,{lang:e.lang,source:e.source}))})))||null},t=s([pi],t)}(p.Component),is=Ee(function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.title,n=e.type,r=e.empty,o=e.code,i=e.opened,a=e.className,s=e.onClick;return p.createElement(\"div\",{className:a,onClick:!r&&s||void 0},!r&&p.createElement(yn,{size:\"1.5em\",color:n,direction:i?\"up\":\"down\",float:\"left\"}),p.createElement(\"strong\",null,o,\" \"),p.createElement(Xr,{compact:!0,inline:!0,source:t}))},t}(p.PureComponent)).withConfig({componentId:\"sc-1kbihq-0\"})([\"padding:10px;border-radius:2px;margin-bottom:4px;line-height:1.5em;background-color:#f2f2f2;cursor:pointer;color:\",\";background-color:\",\";\",\";\"],function(e){return e.theme.colors.responses[e.type].color},function(e){return e.theme.colors.responses[e.type].backgroundColor},function(e){return e.empty?'\\ncursor: default;\\n&::before {\\n  content: \"—\";\\n  font-weight: bold;\\n  width: 1.5em;\\n  text-align: center;\\n  display: inline-block;\\n}\\n':\"\"}),as=Ee.div.withConfig({componentId:\"sc-1kbihq-1\"})([\"padding:10px;\"]),ss=Ee(on.withComponent(\"caption\")).withConfig({componentId:\"sc-1kbihq-2\"})([\"text-align:left;margin-top:1em;caption-side:top;\"]),ls=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.headers;return void 0===e||0===e.length?null:p.createElement(Cn,null,p.createElement(ss,null,\" Response Headers \"),p.createElement(\"tbody\",null,se(e,function(e,t){return p.createElement(Ca,{isLast:t,key:e.name,field:e,showExamples:!0})})))},t}(p.PureComponent),cs=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.renderDropdown=function(e){return p.createElement(on,{key:\"header\"},\"Response Schema: \",p.createElement(ea,a({},e)))},t}return i(t,e),t.prototype.render=function(){var e=this.props.response,t=e.description,n=e.headers,r=e.content;return p.createElement(p.Fragment,null,t&&p.createElement(Xr,{source:t}),p.createElement(ls,{headers:n}),p.createElement(ja,{content:r,renderDropdown:this.renderDropdown},function(e){var t=e.schema;return p.createElement(Oa,{skipWriteOnly:!0,key:\"schema\",schema:t})}))},t}(p.PureComponent),us=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.toggle=function(){t.props.response.toggle()},t}return i(t,e),t.prototype.render=function(){var e=this.props.response,t=e.headers,n=e.type,r=e.summary,o=e.description,i=e.code,a=e.expanded,s=e.content,l=void 0===s?[]:s.mediaTypes.filter(function(e){return void 0!==e.schema}),c=0===t.length&&0===l.length&&!o;return p.createElement(\"div\",null,p.createElement(is,{onClick:this.toggle,type:n,empty:c,title:r||\"\",code:i,opened:a}),a&&!c&&p.createElement(as,null,p.createElement(cs,{response:this.props.response})))},t=s([pi],t)}(p.Component),ps=Ee.h3.withConfig({componentId:\"zr04gj-0\"})([\"font-size:18px;padding:0.2em 0;margin:3em 0 1.1em;color:#253137;font-weight:normal;\"]),fs=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.responses;return e&&0!==e.length?p.createElement(\"div\",null,p.createElement(ps,null,\" Responses \"),e.map(function(e){return p.createElement(us,{key:e.code,response:e})})):null},t}(p.PureComponent),ds=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.operation.responses.filter(function(e){return e.content&&e.content.hasSample});return e.length>0&&p.createElement(\"div\",null,p.createElement(rn,null,\" Response samples \"),p.createElement(ar,{defaultIndex:0},p.createElement(tr,null,e.map(function(e){return p.createElement(rr,{className:\"tab-\"+e.type,key:e.code},e.code)})),e.map(function(e){return p.createElement(ir,{key:e.code},p.createElement(\"div\",null,p.createElement(rs,{content:e.content})))})))||null},t=s([pi],t)}(p.Component),hs=Ee(Jt).withConfig({componentId:\"bf7xj3-0\"})([\"backface-visibility:hidden;contain:content;overflow:hidden;\"]),ms=Ee.div.withConfig({componentId:\"bf7xj3-1\"})([\"margin-bottom:\",\"px;\"],function(e){return 6*e.theme.spacing.unit}),gs=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.operation,t=e.name,n=e.description,r=e.deprecated,o=e.externalDocs,i=!(!n&&!o);return p.createElement(Ie.Consumer,null,function(a){return p.createElement(hs,null,p.createElement(Qt,null,p.createElement(nn,null,p.createElement(mn,{to:e.id}),t,\" \",r&&p.createElement(vn,{type:\"warning\"},\" Deprecated \")),a.pathInMiddlePanel&&p.createElement(Zi,{operation:e,inverted:!0}),i&&p.createElement(ms,null,void 0!==n&&p.createElement(Xr,{source:n}),o&&p.createElement(Si,{externalDocs:o})),p.createElement(ga,{extensions:e.extensions}),p.createElement(qi,{securities:e.security}),p.createElement(Ia,{parameters:e.parameters,body:e.requestBody}),p.createElement(fs,{responses:e.responses})),p.createElement(Kt,null,!a.pathInMiddlePanel&&p.createElement(Zi,{operation:e}),p.createElement(os,{operation:e}),p.createElement(ds,{operation:e})))})},t=s([pi],t)}(p.Component),ys=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.items;return 0===e.length?null:e.map(function(e){return p.createElement(vs,{item:e,key:e.id})})},t=s([pi],t)}(p.Component),vs=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e,t=this.props.item;switch(t.type){case\"group\":e=null;break;case\"tag\":case\"section\":e=p.createElement(ws,a({},this.props));break;case\"operation\":e=p.createElement(xs,{item:t});break;default:e=p.createElement(ws,a({},this.props))}return p.createElement(p.Fragment,null,e&&p.createElement(Gt,{id:t.id,underlined:\"operation\"===t.type},e),t.items&&p.createElement(ys,{items:t.items}))},t=s([pi],t)}(p.Component),bs=function(e){return p.createElement(Qt,null,e)},ws=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props.item,t=e.name,n=e.description,r=e.externalDocs,o=2===e.level?nn:tn;return p.createElement(p.Fragment,null,p.createElement(Jt,null,p.createElement(Qt,null,p.createElement(o,null,p.createElement(mn,{to:this.props.item.id}),t))),p.createElement(Li,{source:n||\"\",htmlWrap:bs}),r&&p.createElement(Jt,null,p.createElement(Qt,null,p.createElement(Si,{externalDocs:r}))))},t=s([pi],t)}(p.Component),xs=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){return p.createElement(gs,{operation:this.props.item})},t=s([pi],t)}(p.Component),ks=Ee.span.attrs(function(e){return{className:\"operation-type \"+e.type}}).withConfig({componentId:\"sc-10atcbm-0\"})([\"width:32px;display:inline-block;height:\",\";line-height:\",\";background-color:#333;border-radius:3px;background-repeat:no-repeat;background-position:6px 4px;font-size:7px;font-family:Verdana;color:white;text-transform:uppercase;text-align:center;font-weight:bold;vertical-align:middle;margin-right:6px;margin-top:2px;&.get{background-color:\",\";}&.post{background-color:\",\";}&.put{background-color:\",\";}&.options{background-color:\",\";}&.patch{background-color:\",\";}&.delete{background-color:\",\";}&.basic{background-color:\",\";}&.link{background-color:\",\";}&.head{background-color:\",\";}\"],function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.typography.code.fontSize},function(e){return e.theme.colors.http.get},function(e){return e.theme.colors.http.post},function(e){return e.theme.colors.http.put},function(e){return e.theme.colors.http.options},function(e){return e.theme.colors.http.patch},function(e){return e.theme.colors.http.delete},function(e){return e.theme.colors.http.basic},function(e){return e.theme.colors.http.link},function(e){return e.theme.colors.http.head});function Es(e,t){var n=t.theme;return e>1?Y(.1,n.menu.backgroundColor):1===e?Y(.05,n.menu.backgroundColor):\"\"}var Ss,_s=Ee.ul.withConfig({componentId:\"sc-10atcbm-1\"})([\"margin:0;padding:0;& &{font-size:0.929em;}\",\";\"],function(e){return e.expanded?\"\":\"display: none;\"}),Os=Ee.li.withConfig({componentId:\"sc-10atcbm-2\"})([\"list-style:none inside none;overflow:hidden;text-overflow:ellipsis;padding:0;\",\";\"],function(e){return 0===e.depth?\"margin-top: 15px\":\"\"}),Cs={0:ve([\"opacity:0.7;text-transform:\",\";font-size:0.8em;padding-bottom:0;cursor:default;color:\",\";\"],function(e){return e.theme.menu.groupItems.textTransform},function(e){return e.theme.menu.textColor}),1:ve([\"font-size:0.929em;text-transform:\",\";&:hover{color:\",\";}\"],function(e){return e.theme.menu.level1Items.textTransform},function(e){return e.theme.colors.primary.main}),2:ve([\"color:\",\";\"],function(e){return e.theme.menu.textColor})},Ts=Ee.label.attrs(function(e){return{role:\"menuitem\",className:qn(\"-depth\"+e.depth,{active:e.active})}}).withConfig({componentId:\"sc-10atcbm-3\"})([\"cursor:pointer;color:\",\";margin:0;padding:12.5px \",\"px;\",\" display:flex;justify-content:space-between;font-family:\",\";\",\";background-color:\",\";\",\";&:hover{background-color:\",\";}\",\"{height:\",\";width:\",\";polygon{fill:\",\";}}\"],function(e){return e.active?e.theme.colors.primary.main:e.theme.menu.textColor},function(e){return 4*e.theme.spacing.unit},function(e){var t=e.depth,n=e.type,r=e.theme;return\"section\"===n&&t>1&&\"padding-left: \"+8*r.spacing.unit+\"px;\"||\"\"},function(e){return e.theme.typography.headings.fontFamily},function(e){return Cs[e.depth]},function(e){return e.active?Es(e.depth,e):\"\"},function(e){return e.deprecated&&bn||\"\"},function(e){return Es(e.depth,e)},yn,function(e){return e.theme.menu.arrow.size},function(e){return e.theme.menu.arrow.size},function(e){return e.theme.menu.arrow.color}),js=Ee.span.withConfig({componentId:\"sc-10atcbm-4\"})([\"display:inline-block;vertical-align:middle;width:\",\";overflow:hidden;text-overflow:ellipsis;\"],function(e){return e.width?e.width:\"auto\"}),As=Ee.div.withConfig({componentId:\"sc-10atcbm-5\"})([\"\",\";\"],function(e){var t=e.theme;return\"\\n  font-size: 0.8em;\\n  margin-top: \"+2*t.spacing.unit+\"px;\\n  padding: 0 \"+4*t.spacing.unit+\"px;\\n  text-align: left;\\n\\n  opacity: 0.7;\\n\\n  a,\\n  a:visited,\\n  a:hover {\\n    color: \"+t.menu.textColor+\" !important;\\n    border-top: 1px solid \"+Y(.1,t.menu.backgroundColor)+\";\\n    padding: \"+t.spacing.unit+\"px 0;\\n    display: block;\\n  }\\n\"}),Is=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.activate=function(e){t.props.onActivate(t.props.item),e.stopPropagation()},t.saveRef=function(e){t.ref=e},t}return i(t,e),t.prototype.componentDidMount=function(){this.scrollIntoViewIfActive()},t.prototype.componentDidUpdate=function(){this.scrollIntoViewIfActive()},t.prototype.scrollIntoViewIfActive=function(){this.props.item.active&&this.ref&&this.ref.scrollIntoViewIfNeeded()},t.prototype.render=function(){var e=this.props,t=e.item,n=e.withoutChildren;return p.createElement(Os,{onClick:this.activate,depth:t.depth,ref:this.saveRef,\"data-item-id\":t.id},\"operation\"===t.type?p.createElement(Ps,a({},this.props,{item:t})):p.createElement(Ts,{depth:t.depth,active:t.active,type:t.type},p.createElement(js,{title:t.name},t.name,this.props.children),t.depth>0&&t.items.length>0&&p.createElement(yn,{float:\"right\",direction:t.expanded?\"down\":\"right\"})||null),!n&&t.items&&t.items.length>0&&p.createElement(Rs,{expanded:t.expanded,items:t.items,onActivate:this.props.onActivate}))},t=s([pi],t)}(p.Component),Ps=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e,t=this.props.item;return p.createElement(Ts,{depth:t.depth,active:t.active,deprecated:t.deprecated},p.createElement(ks,{type:t.httpVerb},{delete:\"del\",options:\"opts\"}[e=t.httpVerb]||e),p.createElement(js,{width:\"calc(100% - 38px)\"},t.name,this.props.children))},t=s([pi],t)}(p.Component),Rs=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this,t=this.props,n=t.items,r=t.root,o=t.className,i=null==this.props.expanded||this.props.expanded;return p.createElement(_s,a({className:o,style:this.props.style,expanded:i},r?{role:\"navigation\"}:{}),n.map(function(t,n){return p.createElement(Is,{key:n,item:t,onActivate:e.props.onActivate})}))},t=s([pi],t)}(p.Component),Ns=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.activate=function(e){t.props.menu.activateAndScroll(e,!0),setTimeout(function(){t._updateScroll&&t._updateScroll()})},t.saveScrollUpdate=function(e){t._updateScroll=e},t}return i(t,e),t.prototype.render=function(){var e=this.props.menu;return p.createElement(zr,{updateFn:this.saveScrollUpdate,className:this.props.className,options:{wheelPropagation:!1}},p.createElement(Rs,{items:e.items,onActivate:this.activate,root:!0}),p.createElement(As,null,p.createElement(\"a\",{target:\"_blank\",href:\"https://github.com/Rebilly/ReDoc\"},\"Documentation Powered by ReDoc\")))},t=s([pi],t)}(p.Component),Ls=function(e){var t=e.open?8:-4;return p.createElement(Ds,null,p.createElement(Ms,{size:15,style:{transform:\"translate(2px, \"+t+\"px) rotate(180deg)\",transition:\"transform 0.2s ease\"}}),p.createElement(Ms,{size:15,style:{transform:\"translate(2px, \"+(0-t)+\"px)\",transition:\"transform 0.2s ease\"}}))},Ms=function(e){var t=e.size,n=void 0===t?10:t,r=e.className,o=void 0===r?\"\":r,i=e.style;return p.createElement(\"svg\",{className:o,style:i||{},viewBox:\"0 0 926.23699 573.74994\",version:\"1.1\",x:\"0px\",y:\"0px\",width:n,height:n},p.createElement(\"g\",{transform:\"translate(904.92214,-879.1482)\"},p.createElement(\"path\",{d:\"\\n          m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,\\n          -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894,\\n          0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892,\\n          -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696,\\n          -174.68583 0.6895,0 26.281,25.03215 56.8701,\\n          55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864\\n          -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,\\n          -104.0616 -231.873,-231.248 z\\n        \",fill:\"currentColor\"})))},Ds=Ee.div.withConfig({componentId:\"sc-1qaepcz-0\"})([\"user-select:none;width:20px;height:20px;align-self:center;display:flex;flex-direction:column;color:\",\";\"],function(e){return e.theme.colors.primary.main});ne&&(Ss=n(269));var Fs,Us,Bs,zs,$s=Ss&&Ss(),Ws=Ee.div.withConfig({componentId:\"sc-1sch5l7-0\"})([\"width:\",\";background-color:\",\";overflow:hidden;display:flex;flex-direction:column;backface-visibility:hidden;contain:strict;height:100vh;position:sticky;position:-webkit-sticky;top:0;\",\";@media print{display:none;}\"],function(e){return e.theme.menu.width},function(e){return e.theme.menu.backgroundColor},ke(\"small\")(Fs||(Fs=u([\"\\n    position: fixed;\\n    z-index: 20;\\n    width: 100%;\\n    background: #ffffff;\\n    display: \",\";\\n  \"],[\"\\n    position: fixed;\\n    z-index: 20;\\n    width: 100%;\\n    background: #ffffff;\\n    display: \",\";\\n  \"])),function(e){return e.open?\"flex\":\"none\"})),qs=Ee.div.withConfig({componentId:\"sc-1sch5l7-1\"})([\"outline:none;user-select:none;background-color:#f2f2f2;color:\",\";display:none;cursor:pointer;position:fixed;right:20px;z-index:100;border-radius:50%;box-shadow:0 0 20px rgba(0,0,0,0.3);\",\";bottom:44px;width:60px;height:60px;padding:0 20px;@media print{display:none;}\"],function(e){return e.theme.colors.primary.main},ke(\"small\")(Us||(Us=u([\"\\n    display: flex;\\n  \"],[\"\\n    display: flex;\\n  \"])))),Hs=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.toggleNavMenu=function(){t.props.menu.toggleSidebar()},t}return i(t,e),t.prototype.componentDidMount=function(){$s&&$s.add(this.stickyElement)},t.prototype.componentWillUnmount=function(){$s&&$s.remove(this.stickyElement)},t.prototype.getScrollYOffset=function(e){return(void 0!==this.props.scrollYOffset?me.normalizeScrollYOffset(this.props.scrollYOffset)():e.scrollYOffset())+\"px\"},t.prototype.render=function(){var e=this,t=this.props.menu.sideBarOpened;return p.createElement(Ie.Consumer,null,function(n){return p.createElement(p.Fragment,null,p.createElement(Ws,{open:t,className:e.props.className,style:function(t){var n=e.getScrollYOffset(t);return{top:n,height:\"calc(100vh - \"+n+\")\"}}(n),ref:function(t){e.stickyElement=t}},e.props.children),p.createElement(qs,{onClick:e.toggleNavMenu},p.createElement(Ls,{open:t})))})},t=s([pi],t)}(p.Component),Ys=Ee.div.withConfig({componentId:\"sc-13p9gjn-0\"})([\"\",\";\"],function(e){var t=e.theme;return\"\\n  font-family: \"+t.typography.fontFamily+\";\\n  font-size: \"+t.typography.fontSize+\";\\n  font-weight: \"+t.typography.fontWeightRegular+\";\\n  line-height: \"+t.typography.lineHeight+\";\\n  color: \"+t.colors.text.primary+\";\\n  display: flex;\\n  position: relative;\\n  text-align: left;\\n\\n  -webkit-font-smoothing: \"+t.typography.smoothing+\";\\n  font-smoothing: \"+t.typography.smoothing+\";\\n  \"+(t.typography.optimizeSpeed?\"text-rendering: optimizeSpeed !important\":\"\")+\";\\n\\n  tap-highlight-color: rgba(0, 0, 0, 0);\\n  text-size-adjust: 100%;\\n\\n  * {\\n    box-sizing: border-box;\\n    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);\\n  }\\n\"}),Vs=Ee.div.withConfig({componentId:\"sc-13p9gjn-1\"})([\"z-index:1;position:relative;overflow:hidden;width:calc(100% - \",\");\",\";contain:layout;\"],function(e){return e.theme.menu.width},ke(\"small\",!0)(Bs||(Bs=u([\"\\n    width: 100%;\\n  \"],[\"\\n    width: 100%;\\n  \"])))),Qs=Ee.div.withConfig({componentId:\"sc-13p9gjn-2\"})([\"background:\",\";position:absolute;top:0;bottom:0;right:0;width:\",\";\",\";\"],function(e){return e.theme.rightPanel.backgroundColor},function(e){var t=e.theme;if(t.rightPanel.width.endsWith(\"%\")){var n=parseInt(t.rightPanel.width,10);return\"calc((100% - \"+t.menu.width+\") * \"+n/100+\")\"}return t.rightPanel.width},ke(\"medium\",!0)(zs||(zs=u([\"\\n    display: none;\\n  \"],[\"\\n    display: none;\\n  \"])))),Gs=Ee.div.withConfig({componentId:\"k4h4y9-0\"})([\"padding:5px 0;\"]),Xs=Ee.input.attrs(function(){return{className:\"search-input\"}}).withConfig({componentId:\"k4h4y9-1\"})([\"width:calc(100% - \",\"px);box-sizing:border-box;margin:0 \",\"px;padding:5px \",\"px 5px \",\"px;border:0;border-bottom:1px solid \",\";font-family:\",\";font-weight:bold;font-size:13px;color:\",\";background-color:transparent;outline:none;\"],function(e){return 8*e.theme.spacing.unit},function(e){return 4*e.theme.spacing.unit},function(e){return 2*e.theme.spacing.unit},function(e){return 4*e.theme.spacing.unit},function(e){var t=e.theme;return Y(.1,t.menu.backgroundColor)},function(e){return e.theme.typography.fontFamily},function(e){return e.theme.menu.textColor}),Ks=Ee(function(e){return p.createElement(\"svg\",{className:e.className,version:\"1.1\",viewBox:\"0 0 1000 1000\",x:\"0px\",xmlns:\"http://www.w3.org/2000/svg\",y:\"0px\"},p.createElement(\"path\",{d:\"M968.2,849.4L667.3,549c83.9-136.5,66.7-317.4-51.7-435.6C477.1-25,252.5-25,113.9,113.4c-138.5,138.3-138.5,362.6,0,501C219.2,730.1,413.2,743,547.6,666.5l301.9,301.4c43.6,43.6,76.9,14.9,104.2-12.4C981,928.3,1011.8,893,968.2,849.4z M524.5,522c-88.9,88.7-233,88.7-321.8,0c-88.9-88.7-88.9-232.6,0-321.3c88.9-88.7,233-88.7,321.8,0C613.4,289.4,613.4,433.3,524.5,522z\"}))}).attrs({className:\"search-icon\"}).withConfig({componentId:\"k4h4y9-2\"})([\"position:absolute;left:\",\"px;height:1.8em;width:0.9em;path{fill:\",\";}\"],function(e){return 4*e.theme.spacing.unit},function(e){return e.theme.menu.textColor}),Js=Ee.div.withConfig({componentId:\"k4h4y9-3\"})([\"padding:\",\"px 0;background-color:#ededed;min-height:150px;max-height:250px;border-top:1px solid #e1e1e1;border-bottom:1px solid #e1e1e1;margin-top:10px;line-height:1.4;font-size:0.9em;\",\"{padding-top:6px;padding-bottom:6px;&:hover{background-color:#e1e1e1;}> svg{display:none;}&.active{background-color:#e1e1e1;}}\"],function(e){return e.theme.spacing.unit},Ts),Zs=Ee.i.withConfig({componentId:\"k4h4y9-4\"})([\"position:absolute;display:inline-block;width:\",\"px;text-align:center;right:\",\"px;line-height:2em;vertical-align:middle;margin-right:2px;cursor:pointer;font-style:normal;color:'#666';\"],function(e){return 2*e.theme.spacing.unit},function(e){return 4*e.theme.spacing.unit}),el=function(e){function t(t){var n=e.call(this,t)||this;return n.activeItemRef=null,n.clear=function(){n.setState({results:[],term:\"\",activeItemIdx:-1}),n.props.marker.unmark()},n.handleKeyDown=function(e){if(27===e.keyCode&&n.clear(),40===e.keyCode&&(n.setState({activeItemIdx:Math.min(n.state.activeItemIdx+1,n.state.results.length-1)}),e.preventDefault()),38===e.keyCode&&(n.setState({activeItemIdx:Math.max(0,n.state.activeItemIdx-1)}),e.preventDefault()),13===e.keyCode){var t=n.state.results[n.state.activeItemIdx];if(t){var r=n.props.getItemById(t.meta);r&&n.props.onActivate(r)}}},n.search=function(e){var t=e.target.value;t.length<3?n.clearResults(t):(n.setState({term:t}),n.props.search.search(e.target.value).then(function(e){n.setResults(e,t)}))},n.state={results:[],term:\"\",activeItemIdx:-1},n}return i(t,e),t.prototype.clearResults=function(e){this.setState({results:[],term:e}),this.props.marker.unmark()},t.prototype.setResults=function(e,t){this.setState({results:e,term:t}),this.props.marker.mark(t)},t.prototype.render=function(){var e=this,t=this.state.activeItemIdx,n=this.state.results.map(function(t){return{item:e.props.getItemById(t.meta),score:t.score}});return n.sort(function(e,t){return t.score-e.score}),p.createElement(Gs,{role:\"search\"},this.state.term&&p.createElement(Zs,{onClick:this.clear},\"×\"),p.createElement(Ks,null),p.createElement(Xs,{value:this.state.term,onKeyDown:this.handleKeyDown,placeholder:\"Search...\",type:\"text\",onChange:this.search}),n.length>0&&p.createElement(zr,{options:{wheelPropagation:!1}},p.createElement(Js,{\"data-role\":\"search:results\"},n.map(function(n,r){return p.createElement(Is,{item:Object.create(n.item,{active:{value:r===t}}),onActivate:e.props.onActivate,withoutChildren:!0,key:n.item.id,\"data-role\":\"search:result\"})}))))},t}(p.PureComponent),tl=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.componentDidMount=function(){this.props.store.onDidMount()},t.prototype.componentWillUnmount=function(){this.props.store.dispose()},t.prototype.render=function(){var e=this.props.store,t=e.spec,n=e.menu,r=e.options,o=e.search,i=e.marker,a=this.props.store;return p.createElement(xe,{theme:r.theme},p.createElement(ln,{value:this.props.store},p.createElement(Pe,{value:r},p.createElement(Ys,{className:\"redoc-wrap\"},p.createElement(Hs,{menu:n,className:\"menu-content\"},p.createElement(Ni,{info:t.info}),!r.disableSearch&&p.createElement(el,{search:o,marker:i,getItemById:n.getItemById,onActivate:n.activateAndScroll})||null,p.createElement(Ns,{menu:n})),p.createElement(Vs,{className:\"api-content\"},p.createElement(Ai,{store:a}),p.createElement(ys,{items:n.items})),p.createElement(Qs,null)))))},t.propTypes={store:h.instanceOf(eo).isRequired},t}(p.Component),nl=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),t.prototype.render=function(){var e=this.props,t=e.spec,n=e.specUrl,r=e.options,o=void 0===r?{}:r,i=e.onLoaded,a=void 0!==o.hideLoading,s=new me(o);return p.createElement(Oe,null,p.createElement(un,{spec:t,specUrl:n,options:o,onLoaded:i},function(e){var t=e.loading,n=e.store;return t?a?null:p.createElement(Ae,{color:s.theme.colors.primary.main}):p.createElement(tl,{store:n})}))},t.propTypes={spec:function(e,t,n){return e.spec||e.specUrl?null:new Error(\"One of props 'spec' or 'specUrl' was not specified in '\"+n+\"'.\")},specUrl:function(e,t,n){return e.spec||e.specUrl?null:new Error(\"One of props 'spec' or 'specUrl' was not specified in '\"+n+\"'.\")},options:h.any,onLoaded:h.any},t}(p.PureComponent);n.d(t,\"version\",function(){return rl}),n.d(t,\"revision\",function(){return ol}),n.d(t,\"init\",function(){return il}),n.d(t,\"hydrate\",function(){return al}),n.d(t,\"Redoc\",function(){return tl}),n.d(t,\"AppStore\",function(){return eo});var rl=\"2.0.0-rc.1\",ol=\"c16d3d5\";function il(e,t,n,r){if(void 0===t&&(t={}),void 0===n&&(n=re(\"redoc\")),null===n)throw new Error('\"element\" argument is not provided and <redoc> tag is not found on the page');var o,i;\"string\"==typeof e?o=e:\"object\"==typeof e&&(i=e),Object(d.render)(p.createElement(nl,{spec:i,onLoaded:r,specUrl:o,options:a({},t,function(e){var t=function(e){for(var t={},n=e.attributes,r=0;r<n.length;r++){var o=n[r];t[o.name]=o.value}return t}(e),n={};for(var r in t)n[r.replace(/-(.)/g,function(e,t){return t.toUpperCase()})]=t[r];return n}(n))},[\"Loading...\"]),n)}function al(e,t,n){void 0===t&&(t=re(\"redoc\")),st();var r=eo.fromJS(e);lt(),setTimeout(function(){st(),Object(d.hydrate)(p.createElement(tl,{store:r}),t,n),lt()},0)}!function(){var e=re(\"redoc\");if(e){var t=e.getAttribute(\"spec-url\");t&&il(t,{},e)}}()}])});\n//# sourceMappingURL=redoc.standalone.js.map</script><style data-styled=\"hvnOJY ebXbwy hsnYXF hVCzEQ kkiuWB  gakpRU cpIzTj iOvGuS fSEbYg djJpRG jWFgPR bZzFwo ixfdRO ecqFVy fgqOex hkGyhI gtRsjv fevDVT gtvzhS kmvDqY cublZ jtdytL iAMmDn kmipUx ghcciP bRFgPh diqfaT kVweLN eoxkJU javeGx bRDwMm gtqIqk kvqXYL fAUnug IavJd dltiCp kTspdE huVGWs jAGbXb fyEFuw kJdFmc gLzrjW iYGBSY ehjTDN jwaijW jXDsIv iWnyBt hYZGfb Hidzy jKmdQj kXBEML jtbdMW lnSenT iJUwRU kmORFN jmkkdP klEXcZ gnKpxH eYuvls hKgcyu kjYYZz iuqUuR dlDeJR jBYmRf wbaPa cMGcAP iwRsmX dAOSNf cUzSHk kVzLlf iyEGWY eOMNXV lbvhxb egwcPy\" data-styled-version=\"4.1.3\">\n/* sc-component-id: sc-6itmo6-0 */\n.diqfaT{width:calc(100% - 40%);padding:0 40px;} @media print,screen and (max-width:85rem){.diqfaT{width:100%;padding:40px 40px;}}\n/* sc-component-id: sc-6itmo6-1 */\n.kmipUx{padding:40px 0;} @media print,screen and (max-width:85rem){.kmipUx{padding:0;}}.ghcciP{padding:40px 0;position:relative;} @media print,screen and (max-width:85rem){.ghcciP{padding:0;}} .ghcciP:not(:last-of-type):after{position:absolute;bottom:0;width:100%;display:block;content:'';border-bottom:1px solid rgba(0,0,0,0.2);}\n/* sc-component-id: sc-6itmo6-3 */\n.iJUwRU{width:40%;color:#ffffff;background-color:#263238;padding:0 40px;background-color:#263238;} @media print,screen and (max-width:85rem){.iJUwRU{width:100%;padding:40px 40px;}}\n/* sc-component-id: sc-6itmo6-4 */\n.bRFgPh{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0;} @media print,screen and (max-width:85rem){.bRFgPh{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}\n/* sc-component-id: shv3r-0 */\n.gtqIqk{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.85714em;color:#32329f;}\n/* sc-component-id: shv3r-1 */\n.fAUnug{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.57143em;color:black;}\n/* sc-component-id: shv3r-3 */\n.dlDeJR{color:#ffffff;}\n/* sc-component-id: shv3r-4 */\n.gLzrjW{border-bottom:1px solid rgba(38,50,56,0.3);margin:1em 0 1em 0;color:rgba(38,50,56,0.5);font-weight:normal;text-transform:uppercase;font-size:0.929em;line-height:20px;}\n/* sc-component-id: eb0njo-0 */\n.kvqXYL{cursor:pointer;margin-left:-20px;padding:0;line-height:1;width:20px;display:inline-block;} .kvqXYL:before{content:'';width:15px;height:15px;background-size:contain;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSIjMDEwMTAxIiBkPSJNNDU5LjcgMjMzLjRsLTkwLjUgOTAuNWMtNTAgNTAtMTMxIDUwLTE4MSAwIC03LjktNy44LTE0LTE2LjctMTkuNC0yNS44bDQyLjEtNDIuMWMyLTIgNC41LTMuMiA2LjgtNC41IDIuOSA5LjkgOCAxOS4zIDE1LjggMjcuMiAyNSAyNSA2NS42IDI0LjkgOTAuNSAwbDkwLjUtOTAuNWMyNS0yNSAyNS02NS42IDAtOTAuNSAtMjQuOS0yNS02NS41LTI1LTkwLjUgMGwtMzIuMiAzMi4yYy0yNi4xLTEwLjItNTQuMi0xMi45LTgxLjYtOC45bDY4LjYtNjguNmM1MC01MCAxMzEtNTAgMTgxIDBDNTA5LjYgMTAyLjMgNTA5LjYgMTgzLjQgNDU5LjcgMjMzLjR6TTIyMC4zIDM4Mi4ybC0zMi4yIDMyLjJjLTI1IDI0LjktNjUuNiAyNC45LTkwLjUgMCAtMjUtMjUtMjUtNjUuNiAwLTkwLjVsOTAuNS05MC41YzI1LTI1IDY1LjUtMjUgOTAuNSAwIDcuOCA3LjggMTIuOSAxNy4yIDE1LjggMjcuMSAyLjQtMS40IDQuOC0yLjUgNi44LTQuNWw0Mi4xLTQyYy01LjQtOS4yLTExLjYtMTgtMTkuNC0yNS44IC01MC01MC0xMzEtNTAtMTgxIDBsLTkwLjUgOTAuNWMtNTAgNTAtNTAgMTMxIDAgMTgxIDUwIDUwIDEzMSA1MCAxODEgMGw2OC42LTY4LjZDMjc0LjYgMzk1LjEgMjQ2LjQgMzkyLjMgMjIwLjMgMzgyLjJ6Ii8+PC9zdmc+Cg==');opacity:0.5;visibility:hidden;display:inline-block;vertical-align:middle;} h1:hover > .kvqXYL::before,h2:hover > .kvqXYL::before,.kvqXYL:hover::before{visibility:visible;}\n/* sc-component-id: sc-1g5rdgs-0 */\n.ecqFVy{height:18px;width:18px;vertical-align:middle;float:right;-webkit-transition:-webkit-transform 0.2s ease-out;-webkit-transition:transform 0.2s ease-out;transition:transform 0.2s ease-out;-webkit-transform:rotateZ(-90deg);-ms-transform:rotateZ(-90deg);transform:rotateZ(-90deg);}.fgqOex{height:1.5em;width:1.5em;vertical-align:middle;float:left;-webkit-transition:-webkit-transform 0.2s ease-out;-webkit-transition:transform 0.2s ease-out;transition:transform 0.2s ease-out;-webkit-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);} .fgqOex polygon{fill:#00aa13;}.hkGyhI{height:1.5em;width:1.5em;vertical-align:middle;float:left;-webkit-transition:-webkit-transform 0.2s ease-out;-webkit-transition:transform 0.2s ease-out;transition:transform 0.2s ease-out;-webkit-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);} .hkGyhI polygon{fill:#e53935;}.gtRsjv{height:20px;width:20px;vertical-align:middle;float:right;-webkit-transition:-webkit-transform 0.2s ease-out;-webkit-transition:transform 0.2s ease-out;transition:transform 0.2s ease-out;-webkit-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);} .gtRsjv polygon{fill:white;}.fevDVT{height:18px;width:18px;vertical-align:middle;-webkit-transition:-webkit-transform 0.2s ease-out;-webkit-transition:transform 0.2s ease-out;transition:transform 0.2s ease-out;-webkit-transform:rotateZ(-90deg);-ms-transform:rotateZ(-90deg);transform:rotateZ(-90deg);}\n/* sc-component-id: dz44d2-3 */\n.ehjTDN{border-left:1px solid #a4a4c6;box-sizing:border-box;position:relative;padding:10px 10px 10px 0;vertical-align:top;line-height:20px;white-space:nowrap;font-size:0.929em;font-family:Montserrat,sans-serif;} tr:first-of-type > .ehjTDN,tr.last > .ehjTDN{border-left-width:0;background-position:top left;background-repeat:no-repeat;background-size:1px 100%;} tr:first-of-type > .ehjTDN{background-image:linear-gradient( to bottom,transparent 0%,transparent 22px,#a4a4c6 22px,#a4a4c6 100% );} tr.last > .ehjTDN{background-image:linear-gradient( to bottom,#a4a4c6 0%,#a4a4c6 22px,transparent 22px,transparent 100% );} tr.last + tr > .ehjTDN{border-left-color:transparent;} tr.last:first-child > .ehjTDN{background:none;border-left-color:transparent;} .ehjTDN.deprecated{-webkit-text-decoration:line-through;text-decoration:line-through;color:#bdccd3;}\n/* sc-component-id: dz44d2-4 */\n.iWnyBt{border-bottom:1px solid #9fb4be;padding:10px 0;width:75%;box-sizing:border-box;} tr.expanded .iWnyBt{border-bottom:none;}\n/* sc-component-id: dz44d2-5 */\n.jwaijW{color:#a4a4c6;font-family:Courier,monospace;margin-right:10px;} .jwaijW::before{content:'';display:inline-block;vertical-align:middle;width:10px;height:1px;background:#a4a4c6;} .jwaijW::after{content:'';display:inline-block;vertical-align:middle;width:1px;background:#a4a4c6;height:7px;}\n/* sc-component-id: dz44d2-7 */\n.iYGBSY{border-collapse:separate;border-radius:3px;font-size:14px;border-spacing:0;width:100%;} .iYGBSY > tr{vertical-align:middle;} .iYGBSY .dz44d2-6,.iYGBSY .dz44d2-6 .dz44d2-6 .dz44d2-6,.iYGBSY .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6{margin:1em;margin-right:0;background:#fafafa;} .iYGBSY .dz44d2-6 .dz44d2-6,.iYGBSY .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6,.iYGBSY .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6 .dz44d2-6{background:#ffffff;}\n/* sc-component-id: sc-1c2fwzw-2 */\n.iyEGWY{margin-left:10px;text-transform:none;font-size:0.929em;color:black;}\n/* sc-component-id: sc-1vrf7wa-0 */\n.jBYmRf > ul{list-style:none;padding:0;margin:0;margin:0 -5px;} .jBYmRf > ul > li{padding:5px 10px;display:inline-block;background-color:#1c2429;border-bottom:1px solid rgba(0,0,0,0.5);cursor:pointer;text-align:center;outline:none;color:#b3b3b3;margin:5px;border:1px solid #11171a;border-radius:5px;min-width:60px;font-size:0.9em;font-weight:bold;} .jBYmRf > ul > li.react-tabs__tab--selected{color:#333333;background:#ffffff;} .jBYmRf > ul > li:only-child{-webkit-flex:none;-ms-flex:none;flex:none;min-width:100px;} .jBYmRf > ul > li.tab-success{color:#00aa13;} .jBYmRf > ul > li.tab-redirect{color:#ffa500;} .jBYmRf > ul > li.tab-info{color:#87ceeb;} .jBYmRf > ul > li.tab-error{color:#e53935;} .jBYmRf > .react-tabs__tab-panel{background:#11171a;} .jBYmRf > .react-tabs__tab-panel > div,.jBYmRf > .react-tabs__tab-panel > pre{padding:20px;margin:0;}\n/* sc-component-id: sc-1rd7dj7-0 */\n.dAOSNf{opacity:0.4;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease;text-align:right;} .dAOSNf > span{display:inline-block;padding:2px 10px;cursor:pointer;} .dAOSNf > span:hover{background:rgba(255,255,255,0.1);}\n/* sc-component-id: sc-global-2362490997 */\n.ps{overflow:hidden !important;overflow-anchor:none;-ms-overflow-style:none;touch-action:auto;-ms-touch-action:auto;} .ps__rail-x{display:none;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;height:15px;bottom:0px;position:absolute;} .ps__rail-y{display:none;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;width:15px;right:0;position:absolute;} .ps--active-x > .ps__rail-x,.ps--active-y > .ps__rail-y{display:block;background-color:transparent;} .ps:hover > .ps__rail-x,.ps:hover > .ps__rail-y,.ps--focus > .ps__rail-x,.ps--focus > .ps__rail-y,.ps--scrolling-x > .ps__rail-x,.ps--scrolling-y > .ps__rail-y{opacity:0.6;} .ps .ps__rail-x:hover,.ps .ps__rail-y:hover,.ps .ps__rail-x:focus,.ps .ps__rail-y:focus,.ps .ps__rail-x.ps--clicking,.ps .ps__rail-y.ps--clicking{background-color:#eee;opacity:0.9;} .ps__thumb-x{background-color:#aaa;border-radius:6px;-webkit-transition:background-color .2s linear,height .2s ease-in-out;transition:background-color .2s linear,height .2s ease-in-out;-webkit-transition:background-color .2s linear,height .2s ease-in-out;height:6px;bottom:2px;position:absolute;} .ps__thumb-y{background-color:#aaa;border-radius:6px;-webkit-transition:background-color .2s linear,width .2s ease-in-out;transition:background-color .2s linear,width .2s ease-in-out;-webkit-transition:background-color .2s linear,width .2s ease-in-out;width:6px;right:2px;position:absolute;} .ps__rail-x:hover > .ps__thumb-x,.ps__rail-x:focus > .ps__thumb-x,.ps__rail-x.ps--clicking .ps__thumb-x{background-color:#999;height:11px;} .ps__rail-y:hover > .ps__thumb-y,.ps__rail-y:focus > .ps__thumb-y,.ps__rail-y.ps--clicking .ps__thumb-y{background-color:#999;width:11px;} @supports (-ms-overflow-style:none){.ps{overflow:auto !important;}} @media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.ps{overflow:auto !important;}}\n/* sc-component-id: i2xdng-0 */\n.gakpRU{position:relative;}\n/* sc-component-id: sc-107yc6q-0 */\n.kVzLlf code[class*='language-'],.kVzLlf pre[class*='language-']{text-shadow:0 -0.1em 0.2em black;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;} @media print{.kVzLlf code[class*='language-'],.kVzLlf pre[class*='language-']{text-shadow:none;}} .kVzLlf pre[class*='language-']{padding:1em;margin:0.5em 0;overflow:auto;} .kVzLlf .token.comment,.kVzLlf .token.prolog,.kVzLlf .token.doctype,.kVzLlf .token.cdata{color:hsl(30,20%,50%);} .kVzLlf .token.punctuation{opacity:0.7;} .kVzLlf .namespace{opacity:0.7;} .kVzLlf .token.property,.kVzLlf .token.tag,.kVzLlf .token.number,.kVzLlf .token.constant,.kVzLlf .token.symbol{color:#4a8bb3;} .kVzLlf .token.boolean{color:firebrick;} .kVzLlf .token.selector,.kVzLlf .token.attr-name,.kVzLlf .token.string,.kVzLlf .token.char,.kVzLlf .token.builtin,.kVzLlf .token.inserted{color:#a0fbaa;} .kVzLlf .token.selector + a,.kVzLlf .token.attr-name + a,.kVzLlf .token.string + a,.kVzLlf .token.char + a,.kVzLlf .token.builtin + a,.kVzLlf .token.inserted + a,.kVzLlf .token.selector + a:visited,.kVzLlf .token.attr-name + a:visited,.kVzLlf .token.string + a:visited,.kVzLlf .token.char + a:visited,.kVzLlf .token.builtin + a:visited,.kVzLlf .token.inserted + a:visited{color:#4ed2ba;-webkit-text-decoration:underline;text-decoration:underline;} .kVzLlf .token.operator,.kVzLlf .token.entity,.kVzLlf .token.url,.kVzLlf .token.variable{color:hsl(40,90%,60%);} .kVzLlf .token.atrule,.kVzLlf .token.attr-value,.kVzLlf .token.keyword{color:hsl(350,40%,70%);} .kVzLlf .token.regex,.kVzLlf .token.important{color:#e90;} .kVzLlf .token.important,.kVzLlf .token.bold{font-weight:bold;} .kVzLlf .token.italic{font-style:italic;} .kVzLlf .token.entity{cursor:help;} .kVzLlf .token.deleted{color:red;}\n/* sc-component-id: sc-1m0b31p-0 */\n.javeGx{font-family:Roboto,sans-serif;font-weight:400;line-height:1.5em;} .javeGx code[class*='language-'],.javeGx pre[class*='language-']{text-shadow:0 -0.1em 0.2em black;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;} @media print{.javeGx code[class*='language-'],.javeGx pre[class*='language-']{text-shadow:none;}} .javeGx pre[class*='language-']{padding:1em;margin:0.5em 0;overflow:auto;} .javeGx .token.comment,.javeGx .token.prolog,.javeGx .token.doctype,.javeGx .token.cdata{color:hsl(30,20%,50%);} .javeGx .token.punctuation{opacity:0.7;} .javeGx .namespace{opacity:0.7;} .javeGx .token.property,.javeGx .token.tag,.javeGx .token.number,.javeGx .token.constant,.javeGx .token.symbol{color:#4a8bb3;} .javeGx .token.boolean{color:firebrick;} .javeGx .token.selector,.javeGx .token.attr-name,.javeGx .token.string,.javeGx .token.char,.javeGx .token.builtin,.javeGx .token.inserted{color:#a0fbaa;} .javeGx .token.selector + a,.javeGx .token.attr-name + a,.javeGx .token.string + a,.javeGx .token.char + a,.javeGx .token.builtin + a,.javeGx .token.inserted + a,.javeGx .token.selector + a:visited,.javeGx .token.attr-name + a:visited,.javeGx .token.string + a:visited,.javeGx .token.char + a:visited,.javeGx .token.builtin + a:visited,.javeGx .token.inserted + a:visited{color:#4ed2ba;-webkit-text-decoration:underline;text-decoration:underline;} .javeGx .token.operator,.javeGx .token.entity,.javeGx .token.url,.javeGx .token.variable{color:hsl(40,90%,60%);} .javeGx .token.atrule,.javeGx .token.attr-value,.javeGx .token.keyword{color:hsl(350,40%,70%);} .javeGx .token.regex,.javeGx .token.important{color:#e90;} .javeGx .token.important,.javeGx .token.bold{font-weight:bold;} .javeGx .token.italic{font-style:italic;} .javeGx .token.entity{cursor:help;} .javeGx .token.deleted{color:red;} .javeGx p:last-child{margin-bottom:0;} .javeGx h1{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.85714em;color:#32329f;margin-top:0;} .javeGx h2{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.57143em;color:#333333;} .javeGx code{color:#e53935;background-color:rgba(38,50,56,0.05);font-family:Courier,monospace;border-radius:2px;border:1px solid rgba(38,50,56,0.1);padding:0 5px;font-size:13px;font-weight:400;word-break:break-word;} .javeGx pre{font-family:Courier,monospace;white-space:pre;background-color:#263238;color:white;padding:12px 14px 15px 14px;overflow-x:auto;line-height:normal;border-radius:0px border:1px solid rgba(38,50,56,0.1);} .javeGx pre code{background-color:transparent;color:white;padding:0;} .javeGx pre code:before,.javeGx pre code:after{content:none;} .javeGx blockquote{margin:0;margin-bottom:1em;padding:0 15px;color:#777;border-left:4px solid #ddd;} .javeGx img{max-width:100%;box-sizing:content-box;} .javeGx ul,.javeGx ol{padding-left:2em;margin:0;margin-bottom:1em;} .javeGx ul ul,.javeGx ol ul,.javeGx ul ol,.javeGx ol ol{margin-bottom:0;margin-top:0;} .javeGx table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;border-collapse:collapse;border-spacing:0;margin-top:1.5em;margin-bottom:1.5em;} .javeGx table tr{background-color:#fff;border-top:1px solid #ccc;} .javeGx table tr:nth-child(2n){background-color:#fafafa;} .javeGx table th,.javeGx table td{padding:6px 13px;border:1px solid #ddd;} .javeGx table th{text-align:left;font-weight:bold;} .javeGx .share-link{cursor:pointer;margin-left:-20px;padding:0;line-height:1;width:20px;display:inline-block;} .javeGx .share-link:before{content:'';width:15px;height:15px;background-size:contain;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSIjMDEwMTAxIiBkPSJNNDU5LjcgMjMzLjRsLTkwLjUgOTAuNWMtNTAgNTAtMTMxIDUwLTE4MSAwIC03LjktNy44LTE0LTE2LjctMTkuNC0yNS44bDQyLjEtNDIuMWMyLTIgNC41LTMuMiA2LjgtNC41IDIuOSA5LjkgOCAxOS4zIDE1LjggMjcuMiAyNSAyNSA2NS42IDI0LjkgOTAuNSAwbDkwLjUtOTAuNWMyNS0yNSAyNS02NS42IDAtOTAuNSAtMjQuOS0yNS02NS41LTI1LTkwLjUgMGwtMzIuMiAzMi4yYy0yNi4xLTEwLjItNTQuMi0xMi45LTgxLjYtOC45bDY4LjYtNjguNmM1MC01MCAxMzEtNTAgMTgxIDBDNTA5LjYgMTAyLjMgNTA5LjYgMTgzLjQgNDU5LjcgMjMzLjR6TTIyMC4zIDM4Mi4ybC0zMi4yIDMyLjJjLTI1IDI0LjktNjUuNiAyNC45LTkwLjUgMCAtMjUtMjUtMjUtNjUuNiAwLTkwLjVsOTAuNS05MC41YzI1LTI1IDY1LjUtMjUgOTAuNSAwIDcuOCA3LjggMTIuOSAxNy4yIDE1LjggMjcuMSAyLjQtMS40IDQuOC0yLjUgNi44LTQuNWw0Mi4xLTQyYy01LjQtOS4yLTExLjYtMTgtMTkuNC0yNS44IC01MC01MC0xMzEtNTAtMTgxIDBsLTkwLjUgOTAuNWMtNTAgNTAtNTAgMTMxIDAgMTgxIDUwIDUwIDEzMSA1MCAxODEgMGw2OC42LTY4LjZDMjc0LjYgMzk1LjEgMjQ2LjQgMzkyLjMgMjIwLjMgMzgyLjJ6Ii8+PC9zdmc+Cg==');opacity:0.5;visibility:hidden;display:inline-block;vertical-align:middle;} .javeGx h1:hover > .share-link::before,.javeGx h2:hover > .share-link::before,.javeGx .share-link:hover::before{visibility:visible;} .javeGx a{-webkit-text-decoration:none;text-decoration:none;color:#32329f;} .javeGx a:visited{color:#32329f;} .javeGx a:hover{color:#6868cf;}.bRDwMm{font-family:Roboto,sans-serif;font-weight:400;line-height:1.5em;} .bRDwMm code[class*='language-'],.bRDwMm pre[class*='language-']{text-shadow:0 -0.1em 0.2em black;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;} @media print{.bRDwMm code[class*='language-'],.bRDwMm pre[class*='language-']{text-shadow:none;}} .bRDwMm pre[class*='language-']{padding:1em;margin:0.5em 0;overflow:auto;} .bRDwMm .token.comment,.bRDwMm .token.prolog,.bRDwMm .token.doctype,.bRDwMm .token.cdata{color:hsl(30,20%,50%);} .bRDwMm .token.punctuation{opacity:0.7;} .bRDwMm .namespace{opacity:0.7;} .bRDwMm .token.property,.bRDwMm .token.tag,.bRDwMm .token.number,.bRDwMm .token.constant,.bRDwMm .token.symbol{color:#4a8bb3;} .bRDwMm .token.boolean{color:firebrick;} .bRDwMm .token.selector,.bRDwMm .token.attr-name,.bRDwMm .token.string,.bRDwMm .token.char,.bRDwMm .token.builtin,.bRDwMm .token.inserted{color:#a0fbaa;} .bRDwMm .token.selector + a,.bRDwMm .token.attr-name + a,.bRDwMm .token.string + a,.bRDwMm .token.char + a,.bRDwMm .token.builtin + a,.bRDwMm .token.inserted + a,.bRDwMm .token.selector + a:visited,.bRDwMm .token.attr-name + a:visited,.bRDwMm .token.string + a:visited,.bRDwMm .token.char + a:visited,.bRDwMm .token.builtin + a:visited,.bRDwMm .token.inserted + a:visited{color:#4ed2ba;-webkit-text-decoration:underline;text-decoration:underline;} .bRDwMm .token.operator,.bRDwMm .token.entity,.bRDwMm .token.url,.bRDwMm .token.variable{color:hsl(40,90%,60%);} .bRDwMm .token.atrule,.bRDwMm .token.attr-value,.bRDwMm .token.keyword{color:hsl(350,40%,70%);} .bRDwMm .token.regex,.bRDwMm .token.important{color:#e90;} .bRDwMm .token.important,.bRDwMm .token.bold{font-weight:bold;} .bRDwMm .token.italic{font-style:italic;} .bRDwMm .token.entity{cursor:help;} .bRDwMm .token.deleted{color:red;} .bRDwMm p:last-child{margin-bottom:0;} .bRDwMm p:first-child{margin-top:0;} .bRDwMm p:last-child{margin-bottom:0;} .bRDwMm h1{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.85714em;color:#32329f;margin-top:0;} .bRDwMm h2{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.57143em;color:#333333;} .bRDwMm code{color:#e53935;background-color:rgba(38,50,56,0.05);font-family:Courier,monospace;border-radius:2px;border:1px solid rgba(38,50,56,0.1);padding:0 5px;font-size:13px;font-weight:400;word-break:break-word;} .bRDwMm pre{font-family:Courier,monospace;white-space:pre;background-color:#263238;color:white;padding:12px 14px 15px 14px;overflow-x:auto;line-height:normal;border-radius:0px border:1px solid rgba(38,50,56,0.1);} .bRDwMm pre code{background-color:transparent;color:white;padding:0;} .bRDwMm pre code:before,.bRDwMm pre code:after{content:none;} .bRDwMm blockquote{margin:0;margin-bottom:1em;padding:0 15px;color:#777;border-left:4px solid #ddd;} .bRDwMm img{max-width:100%;box-sizing:content-box;} .bRDwMm ul,.bRDwMm ol{padding-left:2em;margin:0;margin-bottom:1em;} .bRDwMm ul ul,.bRDwMm ol ul,.bRDwMm ul ol,.bRDwMm ol ol{margin-bottom:0;margin-top:0;} .bRDwMm table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;border-collapse:collapse;border-spacing:0;margin-top:1.5em;margin-bottom:1.5em;} .bRDwMm table tr{background-color:#fff;border-top:1px solid #ccc;} .bRDwMm table tr:nth-child(2n){background-color:#fafafa;} .bRDwMm table th,.bRDwMm table td{padding:6px 13px;border:1px solid #ddd;} .bRDwMm table th{text-align:left;font-weight:bold;} .bRDwMm .share-link{cursor:pointer;margin-left:-20px;padding:0;line-height:1;width:20px;display:inline-block;} .bRDwMm .share-link:before{content:'';width:15px;height:15px;background-size:contain;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSIjMDEwMTAxIiBkPSJNNDU5LjcgMjMzLjRsLTkwLjUgOTAuNWMtNTAgNTAtMTMxIDUwLTE4MSAwIC03LjktNy44LTE0LTE2LjctMTkuNC0yNS44bDQyLjEtNDIuMWMyLTIgNC41LTMuMiA2LjgtNC41IDIuOSA5LjkgOCAxOS4zIDE1LjggMjcuMiAyNSAyNSA2NS42IDI0LjkgOTAuNSAwbDkwLjUtOTAuNWMyNS0yNSAyNS02NS42IDAtOTAuNSAtMjQuOS0yNS02NS41LTI1LTkwLjUgMGwtMzIuMiAzMi4yYy0yNi4xLTEwLjItNTQuMi0xMi45LTgxLjYtOC45bDY4LjYtNjguNmM1MC01MCAxMzEtNTAgMTgxIDBDNTA5LjYgMTAyLjMgNTA5LjYgMTgzLjQgNDU5LjcgMjMzLjR6TTIyMC4zIDM4Mi4ybC0zMi4yIDMyLjJjLTI1IDI0LjktNjUuNiAyNC45LTkwLjUgMCAtMjUtMjUtMjUtNjUuNiAwLTkwLjVsOTAuNS05MC41YzI1LTI1IDY1LjUtMjUgOTAuNSAwIDcuOCA3LjggMTIuOSAxNy4yIDE1LjggMjcuMSAyLjQtMS40IDQuOC0yLjUgNi44LTQuNWw0Mi4xLTQyYy01LjQtOS4yLTExLjYtMTgtMTkuNC0yNS44IC01MC01MC0xMzEtNTAtMTgxIDBsLTkwLjUgOTAuNWMtNTAgNTAtNTAgMTMxIDAgMTgxIDUwIDUwIDEzMSA1MCAxODEgMGw2OC42LTY4LjZDMjc0LjYgMzk1LjEgMjQ2LjQgMzkyLjMgMjIwLjMgMzgyLjJ6Ii8+PC9zdmc+Cg==');opacity:0.5;visibility:hidden;display:inline-block;vertical-align:middle;} .bRDwMm h1:hover > .share-link::before,.bRDwMm h2:hover > .share-link::before,.bRDwMm .share-link:hover::before{visibility:visible;} .bRDwMm a{-webkit-text-decoration:none;text-decoration:none;color:#32329f;} .bRDwMm a:visited{color:#32329f;} .bRDwMm a:hover{color:#6868cf;}\n/* sc-component-id: sc-1m0b31p-0-span */\n.lnSenT{font-family:Roboto,sans-serif;font-weight:400;line-height:1.5em;} .lnSenT p:last-child{margin-bottom:0;} .lnSenT p:first-child{margin-top:0;} .lnSenT p:last-child{margin-bottom:0;} .lnSenT p{display:inline-block;} .lnSenT h1{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.85714em;color:#32329f;margin-top:0;} .lnSenT h2{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.57143em;color:#333333;} .lnSenT code{color:#e53935;background-color:rgba(38,50,56,0.05);font-family:Courier,monospace;border-radius:2px;border:1px solid rgba(38,50,56,0.1);padding:0 5px;font-size:13px;font-weight:400;word-break:break-word;} .lnSenT pre{font-family:Courier,monospace;white-space:pre;background-color:#263238;color:white;padding:12px 14px 15px 14px;overflow-x:auto;line-height:normal;border-radius:0px border:1px solid rgba(38,50,56,0.1);} .lnSenT pre code{background-color:transparent;color:white;padding:0;} .lnSenT pre code:before,.lnSenT pre code:after{content:none;} .lnSenT blockquote{margin:0;margin-bottom:1em;padding:0 15px;color:#777;border-left:4px solid #ddd;} .lnSenT img{max-width:100%;box-sizing:content-box;} .lnSenT ul,.lnSenT ol{padding-left:2em;margin:0;margin-bottom:1em;} .lnSenT ul ul,.lnSenT ol ul,.lnSenT ul ol,.lnSenT ol ol{margin-bottom:0;margin-top:0;} .lnSenT table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;border-collapse:collapse;border-spacing:0;margin-top:1.5em;margin-bottom:1.5em;} .lnSenT table tr{background-color:#fff;border-top:1px solid #ccc;} .lnSenT table tr:nth-child(2n){background-color:#fafafa;} .lnSenT table th,.lnSenT table td{padding:6px 13px;border:1px solid #ddd;} .lnSenT table th{text-align:left;font-weight:bold;} .lnSenT .share-link{cursor:pointer;margin-left:-20px;padding:0;line-height:1;width:20px;display:inline-block;} .lnSenT .share-link:before{content:'';width:15px;height:15px;background-size:contain;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSIjMDEwMTAxIiBkPSJNNDU5LjcgMjMzLjRsLTkwLjUgOTAuNWMtNTAgNTAtMTMxIDUwLTE4MSAwIC03LjktNy44LTE0LTE2LjctMTkuNC0yNS44bDQyLjEtNDIuMWMyLTIgNC41LTMuMiA2LjgtNC41IDIuOSA5LjkgOCAxOS4zIDE1LjggMjcuMiAyNSAyNSA2NS42IDI0LjkgOTAuNSAwbDkwLjUtOTAuNWMyNS0yNSAyNS02NS42IDAtOTAuNSAtMjQuOS0yNS02NS41LTI1LTkwLjUgMGwtMzIuMiAzMi4yYy0yNi4xLTEwLjItNTQuMi0xMi45LTgxLjYtOC45bDY4LjYtNjguNmM1MC01MCAxMzEtNTAgMTgxIDBDNTA5LjYgMTAyLjMgNTA5LjYgMTgzLjQgNDU5LjcgMjMzLjR6TTIyMC4zIDM4Mi4ybC0zMi4yIDMyLjJjLTI1IDI0LjktNjUuNiAyNC45LTkwLjUgMCAtMjUtMjUtMjUtNjUuNiAwLTkwLjVsOTAuNS05MC41YzI1LTI1IDY1LjUtMjUgOTAuNSAwIDcuOCA3LjggMTIuOSAxNy4yIDE1LjggMjcuMSAyLjQtMS40IDQuOC0yLjUgNi44LTQuNWw0Mi4xLTQyYy01LjQtOS4yLTExLjYtMTgtMTkuNC0yNS44IC01MC01MC0xMzEtNTAtMTgxIDBsLTkwLjUgOTAuNWMtNTAgNTAtNTAgMTMxIDAgMTgxIDUwIDUwIDEzMSA1MCAxODEgMGw2OC42LTY4LjZDMjc0LjYgMzk1LjEgMjQ2LjQgMzkyLjMgMjIwLjMgMzgyLjJ6Ii8+PC9zdmc+Cg==');opacity:0.5;visibility:hidden;display:inline-block;vertical-align:middle;} .lnSenT h1:hover > .share-link::before,.lnSenT h2:hover > .share-link::before,.lnSenT .share-link:hover::before{visibility:visible;} .lnSenT a{-webkit-text-decoration:none;text-decoration:none;color:#32329f;} .lnSenT a:visited{color:#32329f;} .lnSenT a:hover{color:#6868cf;}\n/* sc-component-id: sc-1mcjnf5-0 */\n.kVweLN{font-family:Montserrat,sans-serif;font-weight:400;font-size:1.85714em;color:#32329f;margin-top:0;margin-bottom:0.5em;}\n/* sc-component-id: sc-1mcjnf5-1 */\n.eoxkJU{border:1px solid #32329f;color:#32329f;font-weight:normal;margin-left:0.5em;padding:4px 8px 4px;display:inline-block;-webkit-text-decoration:none;text-decoration:none;cursor:pointer;}\n/* sc-component-id: zmmjx2-1 */\n.kJdFmc:after{content:' AND ';font-weight:bold;} .kJdFmc:last-child:after{content:none;} .kJdFmc a{-webkit-text-decoration:none;text-decoration:none;color:#32329f;} .kJdFmc a:visited{color:#32329f;} .kJdFmc a:hover{color:#6868cf;}\n/* sc-component-id: zmmjx2-2 */\n.fyEFuw:before{content:'( ';font-weight:bold;} .fyEFuw:after{content:' ) OR ';font-weight:bold;} .fyEFuw:last-child:after{content:' )';} .fyEFuw:only-child:before,.fyEFuw:only-child:after{content:none;} .fyEFuw a{-webkit-text-decoration:none;text-decoration:none;color:#32329f;} .fyEFuw a:visited{color:#32329f;} .fyEFuw a:hover{color:#6868cf;}\n/* sc-component-id: zmmjx2-3 */\n.kTspdE{-webkit-flex:1;-ms-flex:1;flex:1;}\n/* sc-component-id: zmmjx2-4 */\n.jAGbXb{width:75%;}\n/* sc-component-id: zmmjx2-5 */\n.huVGWs{border-bottom:1px solid rgba(38,50,56,0.3);margin:1em 0 1em 0;color:rgba(38,50,56,0.5);font-weight:normal;text-transform:uppercase;font-size:0.929em;line-height:20px;display:inline-block;margin:0;}\n/* sc-component-id: zmmjx2-6 */\n.dltiCp{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:1em 0;}\n/* sc-component-id: nrhuz6-0 */\n.kmORFN{cursor:pointer;position:relative;margin-bottom:5px;}\n/* sc-component-id: nrhuz6-1 */\n.eYuvls{font-family:Montserrat,sans-serif;margin-left:10px;-webkit-flex:1;-ms-flex:1;flex:1;overflow-x:hidden;text-overflow:ellipsis;}\n/* sc-component-id: nrhuz6-2 */\n.jmkkdP{padding:10px 30px 10px 20px;border-radius:4px 4px 0 0;background-color:#11171a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;white-space:nowrap;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-bottom:0;-webkit-transition:border-color 0.25s ease;transition:border-color 0.25s ease;} .jmkkdP ..nrhuz6-1{color:#ffffff;}\n/* sc-component-id: nrhuz6-3 */\n.klEXcZ{font-size:0.929em;line-height:20px;background-color:#6bbd5b;color:#ffffff;padding:3px 10px;text-transform:uppercase;font-family:Montserrat,sans-serif;margin:0;}.gnKpxH{font-size:0.929em;line-height:20px;background-color:#248fb2;color:#ffffff;padding:3px 10px;text-transform:uppercase;font-family:Montserrat,sans-serif;margin:0;}\n/* sc-component-id: nrhuz6-4 */\n.hKgcyu{position:absolute;width:100%;z-index:100;background:#fafafa;color:#263238;box-sizing:border-box;box-shadow:0px 0px 6px rgba(0,0,0,0.33);overflow:hidden;border-bottom-left-radius:4px;border-bottom-right-radius:4px;-webkit-transition:all 0.25s ease;transition:all 0.25s ease;-webkit-transform:translateY(-50%) scaleY(0);-ms-transform:translateY(-50%) scaleY(0);transform:translateY(-50%) scaleY(0);}\n/* sc-component-id: nrhuz6-5 */\n.kjYYZz{padding:10px;}\n/* sc-component-id: nrhuz6-6 */\n.iuqUuR{padding:5px;border:1px solid #ccc;background:#fff;word-break:break-all;color:#32329f;} .iuqUuR > span{color:#333333;}\n/* sc-component-id: sc-1noysbl-0 */\n.eOMNXV{border-left:1px solid #a4a4c6;box-sizing:border-box;position:relative;padding:10px 10px 10px 0;vertical-align:top;line-height:20px;white-space:nowrap;font-size:0.929em;font-family:Montserrat,sans-serif;cursor:pointer;} tr:first-of-type > .eOMNXV,tr.last > .eOMNXV{border-left-width:0;background-position:top left;background-repeat:no-repeat;background-size:1px 100%;} tr:first-of-type > .eOMNXV{background-image:linear-gradient( to bottom,transparent 0%,transparent 22px,#a4a4c6 22px,#a4a4c6 100% );} tr.last > .eOMNXV{background-image:linear-gradient( to bottom,#a4a4c6 0%,#a4a4c6 22px,transparent 22px,transparent 100% );} tr.last + tr > .eOMNXV{border-left-color:transparent;} tr.last:first-child > .eOMNXV{background:none;border-left-color:transparent;} .eOMNXV.deprecated{-webkit-text-decoration:line-through;text-decoration:line-through;color:#bdccd3;} .eOMNXV .sc-1g5rdgs-0{height:1.1em;width:1.1em;} .eOMNXV .sc-1g5rdgs-0 polygon{fill:#808080;}\n/* sc-component-id: sc-1noysbl-2 */\n.hYZGfb{vertical-align:middle;font-size:13px;line-height:20px;color:rgba(128,128,128,0.8);}\n/* sc-component-id: sc-1noysbl-3 */\n.Hidzy{vertical-align:middle;font-size:13px;line-height:20px;color:#808080;}\n/* sc-component-id: sc-1noysbl-4 */\n.lbvhxb{vertical-align:middle;font-size:13px;line-height:20px;color:#808080;}\n/* sc-component-id: sc-1noysbl-5 */\n.jXDsIv{vertical-align:middle;font-size:13px;line-height:20px;color:#e53935;font-size:0.9em;font-weight:normal;margin-left:20px;line-height:1;}\n/* sc-component-id: t0v3fg-0 */\n.cUzSHk{position:relative;}\n/* sc-component-id: sc-1d3n1g3-0 */\n.iwRsmX:hover > .sc-1rd7dj7-0{opacity:1;}\n/* sc-component-id: sc-1d3n1g3-1 */\n.cMGcAP{font-family:Courier,monospace;font-size:13px;white-space:pre;contain:content;overflow-x:auto;} .cMGcAP .redoc-json > .collapser{display:none;} .cMGcAP .callback-function{color:gray;} .cMGcAP .collapser:after{content:'-';cursor:pointer;} .cMGcAP .collapsed > .collapser:after{content:'+';cursor:pointer;} .cMGcAP .ellipsis:after{content:' … ';} .cMGcAP .collapsible{margin-left:2em;} .cMGcAP .hoverable{padding-top:1px;padding-bottom:1px;padding-left:2px;padding-right:2px;border-radius:2px;} .cMGcAP .hovered{background-color:rgba(235,238,249,1);} .cMGcAP .collapser{padding-right:6px;padding-left:6px;} .cMGcAP ul{list-style-type:none;padding:0px;margin:0px 0px 0px 26px;} .cMGcAP li{position:relative;display:block;} .cMGcAP .hoverable{display:inline-block;} .cMGcAP .selected{outline-style:solid;outline-width:1px;outline-style:dotted;} .cMGcAP .collapsed > .collapsible{display:none;} .cMGcAP .ellipsis{display:none;} .cMGcAP .collapsed > .ellipsis{display:inherit;} .cMGcAP .collapser{position:absolute;top:1px;left:-1.5em;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none;}\n/* sc-component-id: futasu-0 */\n.wbaPa{border-bottom:1px solid rgba(255,255,255,0.9);margin:0 0 10px 0;display:block;color:rgba(255,255,255,0.8);}\n/* sc-component-id: sc-1kbihq-0 */\n.kXBEML{padding:10px;border-radius:2px;margin-bottom:4px;line-height:1.5em;background-color:#f2f2f2;cursor:pointer;color:#00aa13;background-color:rgba(0,170,19,0.1);}.jtbdMW{padding:10px;border-radius:2px;margin-bottom:4px;line-height:1.5em;background-color:#f2f2f2;cursor:pointer;color:#e53935;background-color:rgba(229,57,53,0.1);}\n/* sc-component-id: zr04gj-0 */\n.jKmdQj{font-size:18px;padding:0.2em 0;margin:3em 0 1.1em;color:#253137;font-weight:normal;}\n/* sc-component-id: bf7xj3-0 */\n.IavJd{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0;-webkit-backface-visibility:hidden;backface-visibility:hidden;contain:content;overflow:hidden;} @media print,screen and (max-width:85rem){.IavJd{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}\n/* sc-component-id: sc-10atcbm-0 */\n.gtvzhS{width:32px;display:inline-block;height:13px;line-height:13px;background-color:#333;border-radius:3px;background-repeat:no-repeat;background-position:6px 4px;font-size:7px;font-family:Verdana;color:white;text-transform:uppercase;text-align:center;font-weight:bold;vertical-align:middle;margin-right:6px;margin-top:2px;} .gtvzhS.get{background-color:#6bbd5b;} .gtvzhS.post{background-color:#248fb2;} .gtvzhS.put{background-color:#9b708b;} .gtvzhS.options{background-color:#d3ca12;} .gtvzhS.patch{background-color:#e09d43;} .gtvzhS.delete{background-color:#e27a7a;} .gtvzhS.basic{background-color:#999;} .gtvzhS.link{background-color:#31bbb6;} .gtvzhS.head{background-color:#c167e4;}\n/* sc-component-id: sc-10atcbm-1 */\n.cpIzTj{margin:0;padding:0;} .cpIzTj .sc-10atcbm-1{font-size:0.929em;}.iOvGuS{margin:0;padding:0;display:none;} .iOvGuS .sc-10atcbm-1{font-size:0.929em;}\n/* sc-component-id: sc-10atcbm-2 */\n.fSEbYg{list-style:none inside none;overflow:hidden;text-overflow:ellipsis;padding:0;}\n/* sc-component-id: sc-10atcbm-3 */\n.djJpRG{cursor:pointer;color:#333333;margin:0;padding:12.5px 20px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;font-family:Montserrat,sans-serif;font-size:0.929em;text-transform:none;} .djJpRG:hover{color:#32329f;} .djJpRG:hover{background-color:#ededed;} .djJpRG .sc-1g5rdgs-0{height:1.5em;width:1.5em;} .djJpRG .sc-1g5rdgs-0 polygon{fill:#333333;}.jWFgPR{cursor:pointer;color:#333333;margin:0;padding:12.5px 20px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;font-family:Montserrat,sans-serif;color:#333333;} .jWFgPR:hover{background-color:#e1e1e1;} .jWFgPR .sc-1g5rdgs-0{height:1.5em;width:1.5em;} .jWFgPR .sc-1g5rdgs-0 polygon{fill:#333333;}\n/* sc-component-id: sc-10atcbm-4 */\n.bZzFwo{display:inline-block;vertical-align:middle;width:auto;overflow:hidden;text-overflow:ellipsis;}.ixfdRO{display:inline-block;vertical-align:middle;width:calc(100% - 38px);overflow:hidden;text-overflow:ellipsis;}\n/* sc-component-id: sc-10atcbm-5 */\n.kmvDqY{font-size:0.8em;margin-top:10px;padding:0 20px;text-align:left;opacity:0.7;} .kmvDqY a,.kmvDqY a:visited,.kmvDqY a:hover{color:#333333 !important;border-top:1px solid #e1e1e1;padding:5px 0;display:block;}\n/* sc-component-id: sc-1qaepcz-0 */\n.jtdytL{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:20px;height:20px;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;color:#32329f;}\n/* sc-component-id: sc-1sch5l7-0 */\n.ebXbwy{width:260px;background-color:#fafafa;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-backface-visibility:hidden;backface-visibility:hidden;contain:strict;height:100vh;position:-webkit-sticky;position:sticky;position:-webkit-sticky;top:0;} @media screen and (max-width:50rem){.ebXbwy{position:fixed;z-index:20;width:100%;background:#ffffff;display:none;}} @media print{.ebXbwy{display:none;}}\n/* sc-component-id: sc-1sch5l7-1 */\n.cublZ{outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#f2f2f2;color:#32329f;display:none;cursor:pointer;position:fixed;right:20px;z-index:100;border-radius:50%;box-shadow:0 0 20px rgba(0,0,0,0.3);bottom:44px;width:60px;height:60px;padding:0 20px;} @media screen and (max-width:50rem){.cublZ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}} @media print{.cublZ{display:none;}}\n/* sc-component-id: sc-13p9gjn-0 */\n.hvnOJY{font-family:Roboto,sans-serif;font-size:14px;font-weight:400;line-height:1.5em;color:#333333;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;text-align:left;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;text-rendering:optimizeSpeed !important;tap-highlight-color:rgba(0,0,0,0);-webkit-text-size-adjust:100%;text-size-adjust:100%;} .hvnOJY *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(255,255,255,0);}\n/* sc-component-id: sc-13p9gjn-1 */\n.iAMmDn{z-index:1;position:relative;overflow:hidden;width:calc(100% - 260px);contain:layout;} @media print,screen and (max-width:50rem){.iAMmDn{width:100%;}}\n/* sc-component-id: sc-13p9gjn-2 */\n.egwcPy{background:#263238;position:absolute;top:0;bottom:0;right:0;width:calc((100% - 260px) * 0.4);} @media print,screen and (max-width:85rem){.egwcPy{display:none;}}\n/* sc-component-id: k4h4y9-0 */\n.hsnYXF{padding:5px 0;}\n/* sc-component-id: k4h4y9-1 */\n.kkiuWB{width:calc(100% - 40px);box-sizing:border-box;margin:0 20px;padding:5px 10px 5px 20px;border:0;border-bottom:1px solid #e1e1e1;font-family:Roboto,sans-serif;font-weight:bold;font-size:13px;color:#333333;background-color:transparent;outline:none;}\n/* sc-component-id: k4h4y9-2 */\n.hVCzEQ{position:absolute;left:20px;height:1.8em;width:0.9em;} .hVCzEQ path{fill:#333333;}</style>\n  <link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n</head>\n\n<body>\n  \n    <div id=\"redoc\"><div class=\"redoc-wrap sc-13p9gjn-0 hvnOJY\"><div class=\"menu-content sc-1sch5l7-0 ebXbwy\" style=\"top:0px;height:calc(100vh - 0px)\"><div role=\"search\" class=\"k4h4y9-0 hsnYXF\"><svg class=\"k4h4y9-2 search-icon hVCzEQ\" version=\"1.1\" viewBox=\"0 0 1000 1000\" x=\"0px\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0px\"><path d=\"M968.2,849.4L667.3,549c83.9-136.5,66.7-317.4-51.7-435.6C477.1-25,252.5-25,113.9,113.4c-138.5,138.3-138.5,362.6,0,501C219.2,730.1,413.2,743,547.6,666.5l301.9,301.4c43.6,43.6,76.9,14.9,104.2-12.4C981,928.3,1011.8,893,968.2,849.4z M524.5,522c-88.9,88.7-233,88.7-321.8,0c-88.9-88.7-88.9-232.6,0-321.3c88.9-88.7,233-88.7,321.8,0C613.4,289.4,613.4,433.3,524.5,522z\"></path></svg><input type=\"text\" class=\"k4h4y9-1 search-input kkiuWB\" value=\"\" placeholder=\"Search...\"/></div><div class=\"scrollbar-container undefined i2xdng-0 gakpRU\"><ul class=\"sc-10atcbm-1 cpIzTj\" role=\"navigation\"><li data-item-id=\"section/Authentication\" class=\"sc-10atcbm-2 fSEbYg\"><label role=\"menuitem\" class=\"sc-10atcbm-3 -depth1 djJpRG\" type=\"section\"><span title=\"Authentication\" class=\"sc-10atcbm-4 bZzFwo\">Authentication</span></label></li><li data-item-id=\"tag/Application\" class=\"sc-10atcbm-2 fSEbYg\"><label role=\"menuitem\" class=\"sc-10atcbm-3 -depth1 djJpRG\" type=\"tag\"><span title=\"Application\" class=\"sc-10atcbm-4 bZzFwo\">Application</span><svg class=\"sc-1g5rdgs-0 ecqFVy\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></label><ul class=\"sc-10atcbm-1 iOvGuS\"><li data-item-id=\"tag/Application/paths/~1v1~1apps~1{appId}/get\" class=\"sc-10atcbm-2 fSEbYg\"><label role=\"menuitem\" class=\"sc-10atcbm-3 -depth2 jWFgPR\"><span class=\"sc-10atcbm-0 operation-type get gtvzhS\" type=\"get\">get</span><span width=\"calc(100% - 38px)\" class=\"sc-10atcbm-4 ixfdRO\">Retrieve an application defintion</span></label></li><li data-item-id=\"tag/Application/paths/~1v1~1apps/post\" class=\"sc-10atcbm-2 fSEbYg\"><label role=\"menuitem\" class=\"sc-10atcbm-3 -depth2 jWFgPR\"><span class=\"sc-10atcbm-0 operation-type post gtvzhS\" type=\"post\">post</span><span width=\"calc(100% - 38px)\" class=\"sc-10atcbm-4 ixfdRO\">Create a new application definition</span></label></li><li data-item-id=\"tag/Application/paths/~1v1~1apps~1search/get\" class=\"sc-10atcbm-2 fSEbYg\"><label role=\"menuitem\" class=\"sc-10atcbm-3 -depth2 jWFgPR\"><span class=\"sc-10atcbm-0 operation-type get gtvzhS\" type=\"get\">get</span><span width=\"calc(100% - 38px)\" class=\"sc-10atcbm-4 ixfdRO\">Retrieve a list of applications</span></label></li></ul></li></ul><div class=\"sc-10atcbm-5 kmvDqY\"><a target=\"_blank\" href=\"https://github.com/Rebilly/ReDoc\">Documentation Powered by ReDoc</a></div></div></div><div class=\"sc-1sch5l7-1 cublZ\"><div class=\"sc-1qaepcz-0 jtdytL\"><svg class=\"\" style=\"transform:translate(2px, -4px) rotate(180deg);transition:transform 0.2s ease\" viewBox=\"0 0 926.23699 573.74994\" version=\"1.1\" x=\"0px\" y=\"0px\" width=\"15\" height=\"15\"><g transform=\"translate(904.92214,-879.1482)\"><path d=\"\n          m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,\n          -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894,\n          0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892,\n          -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696,\n          -174.68583 0.6895,0 26.281,25.03215 56.8701,\n          55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864\n          -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,\n          -104.0616 -231.873,-231.248 z\n        \" fill=\"currentColor\"></path></g></svg><svg class=\"\" style=\"transform:translate(2px, 4px);transition:transform 0.2s ease\" viewBox=\"0 0 926.23699 573.74994\" version=\"1.1\" x=\"0px\" y=\"0px\" width=\"15\" height=\"15\"><g transform=\"translate(904.92214,-879.1482)\"><path d=\"\n          m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,\n          -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894,\n          0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892,\n          -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696,\n          -174.68583 0.6895,0 26.281,25.03215 56.8701,\n          55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864\n          -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,\n          -104.0616 -231.873,-231.248 z\n        \" fill=\"currentColor\"></path></g></svg></div></div><div class=\"api-content sc-13p9gjn-1 iAMmDn\"><div class=\"sc-6itmo6-1 kmipUx\"><div class=\"sc-6itmo6-4 bRFgPh\"><div class=\"api-info sc-6itmo6-0 diqfaT\"><h1 class=\"shv3r-0 sc-1mcjnf5-0 kVweLN\">Application Directory specification<!-- --> <span>(<!-- -->1.0<!-- -->)</span></h1><p>Download OpenAPI specification:<a download=\"swagger.json\" target=\"_blank\" class=\"sc-1mcjnf5-1 eoxkJU\">Download</a></p><div class=\"sc-107yc6q-0 sc-1m0b31p-0 javeGx\"></div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 javeGx\"><p>Application Directory specification providing both interface definition and objects necessary to construct an application directory service.</p>\n</div></div></div></div><div data-section-id=\"section/Authentication\" id=\"section/Authentication\" class=\"sc-6itmo6-1 kmipUx\"><div class=\"sc-6itmo6-4 bRFgPh\"><div class=\"sc-6itmo6-0 diqfaT\"><h1 class=\"shv3r-0 gtqIqk\"><a class=\"eb0njo-0 kvqXYL\" href=\"#section/Authentication\"></a>Authentication</h1></div></div><div data-section-id=\"section/Authentication/bearerAuth\" id=\"section/Authentication/bearerAuth\" class=\"sc-6itmo6-1 kmipUx\"><div class=\"sc-6itmo6-4 bRFgPh\"><div class=\"sc-6itmo6-0 diqfaT\"><h2 class=\"shv3r-1 fAUnug\"><a class=\"eb0njo-0 kvqXYL\" href=\"#section/Authentication/bearerAuth\"></a>bearerAuth</h2><div class=\"sc-107yc6q-0 sc-1m0b31p-0 javeGx\"></div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 javeGx\"><table class=\"security-details\"><tbody><tr><th> Security scheme type: </th><td> <!-- -->HTTP<!-- --> </td></tr><tr><th> HTTP Authorization Scheme </th><td> <!-- -->bearer<!-- --> </td></tr><tr><th> Bearer format </th><td> &quot;<!-- -->JWT<!-- -->&quot; </td></tr></tbody></table></div></div></div></div></div><div data-section-id=\"tag/Application\" id=\"tag/Application\" class=\"sc-6itmo6-1 kmipUx\"><div class=\"sc-6itmo6-4 bRFgPh\"><div class=\"sc-6itmo6-0 diqfaT\"><h1 class=\"shv3r-0 gtqIqk\"><a class=\"eb0njo-0 kvqXYL\" href=\"#tag/Application\"></a>Application</h1></div></div></div><div data-section-id=\"tag/Application/paths/~1v1~1apps~1{appId}/get\" id=\"tag/Application/paths/~1v1~1apps~1{appId}/get\" class=\"sc-6itmo6-1 ghcciP\"><div class=\"sc-6itmo6-4 bf7xj3-0 IavJd\"><div class=\"sc-6itmo6-0 diqfaT\"><h2 class=\"shv3r-1 fAUnug\"><a class=\"eb0njo-0 kvqXYL\" href=\"#tag/Application/paths/~1v1~1apps~1{appId}/get\"></a>Retrieve an application defintion<!-- --> </h2><div class=\"zmmjx2-6 dltiCp\"><div class=\"zmmjx2-3 kTspdE\"><h5 class=\"shv3r-4 zmmjx2-5 huVGWs\">Authorizations: </h5></div><div class=\"zmmjx2-4 jAGbXb\"><span class=\"zmmjx2-2 fyEFuw\"><span class=\"zmmjx2-1 kJdFmc\"><a href=\"#section/Authentication/bearerAuth\">bearerAuth</a></span></span></div></div><div><div><h5 class=\"shv3r-4 gLzrjW\">path<!-- --> Parameters</h5><table class=\"dz44d2-7 iYGBSY\"><tbody><tr class=\"last undefined\"><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"appId\"><span class=\"dz44d2-5 jwaijW\"></span>appId<div class=\"sc-1noysbl-1-div sc-1noysbl-5 jXDsIv\"> required </div></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"></div></div></div></td></tr></tbody></table></div></div><div><h3 class=\"zr04gj-0 jKmdQj\"> Responses </h3><div><div class=\"sc-1kbihq-0 kXBEML\"><svg class=\"sc-1g5rdgs-0 fgqOex\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>200<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>OK</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>400<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Bad request.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>403<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Forbidden: Certificate authentication is not allowed for the requested user.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>500<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Server error, see response body for further details.</p>\n</span></div></div></div></div><div class=\"sc-6itmo6-2 sc-6itmo6-3 iJUwRU\"><div class=\"nrhuz6-0 kmORFN\"><div class=\"nrhuz6-2 jmkkdP\"><span class=\"nrhuz6-3 http-verb get klEXcZ\" type=\"get\"> <!-- -->get</span> <span class=\"nrhuz6-1 eYuvls\">/v1/apps/{appId}</span><svg class=\"sc-1g5rdgs-0 gtRsjv\" style=\"margin-right:-25px\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></div><div class=\"nrhuz6-4 hKgcyu\"><div class=\"nrhuz6-5 kjYYZz\"><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"></div><div><div class=\"nrhuz6-6 iuqUuR\"><span>/appd</span>/v1/apps/{appId}</div></div></div></div></div><div><h3 class=\"shv3r-3 dlDeJR\"> Response samples </h3><div class=\"sc-1vrf7wa-0 jBYmRf\" data-tabs=\"true\"><ul class=\"react-tabs__tab-list\" role=\"tablist\"><li class=\"tab-success react-tabs__tab--selected\" role=\"tab\" id=\"react-tabs-0\" aria-selected=\"true\" aria-disabled=\"false\" aria-controls=\"react-tabs-1\" tabindex=\"0\">200</li></ul><div class=\"react-tabs__tab-panel react-tabs__tab-panel--selected\" role=\"tabpanel\" id=\"react-tabs-1\" aria-labelledby=\"react-tabs-0\"><div><div class=\"futasu-0 wbaPa\">application/json</div><div><div class=\"sc-1d3n1g3-0 iwRsmX\"><div class=\"sc-1rd7dj7-0 dAOSNf\"><span><div class=\"t0v3fg-0 cUzSHk\">Copy</div></span><span> Expand all </span><span> Collapse all </span></div><div class=\"sc-1d3n1g3-1 cMGcAP sc-107yc6q-0 kVzLlf\"><div class=\"redoc-json\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable \"><span class=\"property token string\">\"appId\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"manifest\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"manifestType\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"version\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"title\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"tooltip\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"description\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"images\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"url\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"contactEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"supportEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"publisher\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"icons\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icon\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"customConfig\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"value\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"intents\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"displayName\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contexts\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <span class=\"token punctuation\">{ }</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span></div></li></ul><span class=\"token punctuation\">}</span></div></div></div></div></div></div></div></div></div></div></div><div data-section-id=\"tag/Application/paths/~1v1~1apps/post\" id=\"tag/Application/paths/~1v1~1apps/post\" class=\"sc-6itmo6-1 ghcciP\"><div class=\"sc-6itmo6-4 bf7xj3-0 IavJd\"><div class=\"sc-6itmo6-0 diqfaT\"><h2 class=\"shv3r-1 fAUnug\"><a class=\"eb0njo-0 kvqXYL\" href=\"#tag/Application/paths/~1v1~1apps/post\"></a>Create a new application definition<!-- --> </h2><div class=\"zmmjx2-6 dltiCp\"><div class=\"zmmjx2-3 kTspdE\"><h5 class=\"shv3r-4 zmmjx2-5 huVGWs\">Authorizations: </h5></div><div class=\"zmmjx2-4 jAGbXb\"><span class=\"zmmjx2-2 fyEFuw\"><span class=\"zmmjx2-1 kJdFmc\"><a href=\"#section/Authentication/bearerAuth\">bearerAuth</a></span></span></div></div><div><h5 class=\"shv3r-4 gLzrjW\">Request Body schema: <span class=\"sc-1c2fwzw-2 iyEGWY\">application/json</span></h5><table class=\"dz44d2-7 iYGBSY\"><tbody><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"appId\"><span class=\"dz44d2-5 jwaijW\"></span>appId<div class=\"sc-1noysbl-1-div sc-1noysbl-5 jXDsIv\"> required </div></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>The unique application identifier located within a specific application directory instance.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"name\"><span class=\"dz44d2-5 jwaijW\"></span>name<div class=\"sc-1noysbl-1-div sc-1noysbl-5 jXDsIv\"> required </div></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>The name of the application.\nThe name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app.\nThe same appName could occur in other directories. We are not currently specifying app name conventions in the document.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"manifest\"><span class=\"dz44d2-5 jwaijW\"></span>manifest<div class=\"sc-1noysbl-1-div sc-1noysbl-5 jXDsIv\"> required </div></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>URI or full JSON of the application manifest providing all details related to launch and use requirements as described by the vendor.\nThe format of this manifest is vendor specific, but can be identified by the manifestType attribute.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"manifestType\"><span class=\"dz44d2-5 jwaijW\"></span>manifestType<div class=\"sc-1noysbl-1-div sc-1noysbl-5 jXDsIv\"> required </div></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>The manifest type which relates to the format and structure of the manifest content. The definition is based on the vendor specific format and definition outside of this specification.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"version\"><span class=\"dz44d2-5 jwaijW\"></span>version</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"title\"><span class=\"dz44d2-5 jwaijW\"></span>title</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Optional title for the application, if missing use appName, typically used in a launcher UI.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"tooltip\"><span class=\"dz44d2-5 jwaijW\"></span>tooltip</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Optional tooltip description e.g. for a launcher</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"description\"><span class=\"dz44d2-5 jwaijW\"></span>description</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 sc-1noysbl-0 eOMNXV\" kind=\"field\" title=\"images\"><span class=\"dz44d2-5 jwaijW\"></span>images<svg class=\"sc-1g5rdgs-0 fevDVT\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\">Array of </span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">object</span><span class=\"sc-1noysbl-1 sc-1noysbl-4 lbvhxb\"> (<!-- -->AppImage<!-- -->) </span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"contactEmail\"><span class=\"dz44d2-5 jwaijW\"></span>contactEmail</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Optional e-mail to receive queries about the application</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"supportEmail\"><span class=\"dz44d2-5 jwaijW\"></span>supportEmail</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Optional e-mail to receive support requests for the application</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 ehjTDN\" kind=\"field\" title=\"publisher\"><span class=\"dz44d2-5 jwaijW\"></span>publisher</td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\"></span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">string</span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>The name of the company that owns the application. The publisher has control over their namespace/app/signature.</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 sc-1noysbl-0 eOMNXV\" kind=\"field\" title=\"icons\"><span class=\"dz44d2-5 jwaijW\"></span>icons<svg class=\"sc-1g5rdgs-0 fevDVT\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\">Array of </span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">object</span><span class=\"sc-1noysbl-1 sc-1noysbl-4 lbvhxb\"> (<!-- -->Icon<!-- -->) </span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a &#39;button&#39; Icon</p>\n</div></div></div></td></tr><tr><td class=\"dz44d2-1 dz44d2-3 sc-1noysbl-0 eOMNXV\" kind=\"field\" title=\"customConfig\"><span class=\"dz44d2-5 jwaijW\"></span>customConfig<svg class=\"sc-1g5rdgs-0 fevDVT\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\">Array of </span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">object</span><span class=\"sc-1noysbl-1 sc-1noysbl-4 lbvhxb\"> (<!-- -->NameValuePair<!-- -->) </span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.</p>\n</div></div></div></td></tr><tr class=\"last undefined\"><td class=\"dz44d2-1 dz44d2-3 sc-1noysbl-0 eOMNXV\" kind=\"field\" title=\"intents\"><span class=\"dz44d2-5 jwaijW\"></span>intents<svg class=\"sc-1g5rdgs-0 fevDVT\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></td><td class=\"dz44d2-4 iWnyBt\"><div><div><span class=\"sc-1noysbl-1 sc-1noysbl-2 hYZGfb\">Array of </span><span class=\"sc-1noysbl-1 sc-1noysbl-3 Hidzy\">object</span><span class=\"sc-1noysbl-1 sc-1noysbl-4 lbvhxb\"> (<!-- -->Intent<!-- -->) </span></div> <div><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"><p>The list of intents implemented by the Application as defined by <a href=\"https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\">https://github.com/FDC3/Intents/blob/main/src/Intent.yaml</a></p>\n</div></div></div></td></tr></tbody></table></div><div><h3 class=\"zr04gj-0 jKmdQj\"> Responses </h3><div><div class=\"sc-1kbihq-0 kXBEML\"><svg class=\"sc-1g5rdgs-0 fgqOex\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>200<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>OK</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>400<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Bad request.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>403<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Forbidden: Certificate authentication is not allowed for the requested user.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>500<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Server error, see response body for further details.</p>\n</span></div></div></div></div><div class=\"sc-6itmo6-2 sc-6itmo6-3 iJUwRU\"><div class=\"nrhuz6-0 kmORFN\"><div class=\"nrhuz6-2 jmkkdP\"><span class=\"nrhuz6-3 http-verb post gnKpxH\" type=\"post\"> <!-- -->post</span> <span class=\"nrhuz6-1 eYuvls\">/v1/apps</span><svg class=\"sc-1g5rdgs-0 gtRsjv\" style=\"margin-right:-25px\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></div><div class=\"nrhuz6-4 hKgcyu\"><div class=\"nrhuz6-5 kjYYZz\"><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"></div><div><div class=\"nrhuz6-6 iuqUuR\"><span>/appd</span>/v1/apps</div></div></div></div></div><div><h3 class=\"shv3r-3 dlDeJR\"> Request samples </h3><div class=\"sc-1vrf7wa-0 jBYmRf\" data-tabs=\"true\"><ul class=\"react-tabs__tab-list\" role=\"tablist\"><li class=\"react-tabs__tab react-tabs__tab--selected\" role=\"tab\" id=\"react-tabs-2\" aria-selected=\"true\" aria-disabled=\"false\" aria-controls=\"react-tabs-3\" tabindex=\"0\"> Payload </li></ul><div class=\"react-tabs__tab-panel react-tabs__tab-panel--selected\" role=\"tabpanel\" id=\"react-tabs-3\" aria-labelledby=\"react-tabs-2\"><div><div class=\"futasu-0 wbaPa\">application/json</div><div><div class=\"sc-1d3n1g3-0 iwRsmX\"><div class=\"sc-1rd7dj7-0 dAOSNf\"><span><div class=\"t0v3fg-0 cUzSHk\">Copy</div></span><span> Expand all </span><span> Collapse all </span></div><div class=\"sc-1d3n1g3-1 cMGcAP sc-107yc6q-0 kVzLlf\"><div class=\"redoc-json\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable \"><span class=\"property token string\">\"appId\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"manifest\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"manifestType\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"version\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"title\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"tooltip\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"description\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"images\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"url\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"contactEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"supportEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"publisher\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"icons\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icon\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"customConfig\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"value\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"intents\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"displayName\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contexts\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <span class=\"token punctuation\">{ }</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span></div></li></ul><span class=\"token punctuation\">}</span></div></div></div></div></div></div></div></div><div><h3 class=\"shv3r-3 dlDeJR\"> Response samples </h3><div class=\"sc-1vrf7wa-0 jBYmRf\" data-tabs=\"true\"><ul class=\"react-tabs__tab-list\" role=\"tablist\"><li class=\"tab-success react-tabs__tab--selected\" role=\"tab\" id=\"react-tabs-4\" aria-selected=\"true\" aria-disabled=\"false\" aria-controls=\"react-tabs-5\" tabindex=\"0\">200</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-6\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-7\">400</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-8\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-9\">403</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-10\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-11\">500</li></ul><div class=\"react-tabs__tab-panel react-tabs__tab-panel--selected\" role=\"tabpanel\" id=\"react-tabs-5\" aria-labelledby=\"react-tabs-4\"><div><div class=\"futasu-0 wbaPa\">application/json</div><div><div class=\"sc-1d3n1g3-0 iwRsmX\"><div class=\"sc-1rd7dj7-0 dAOSNf\"><span><div class=\"t0v3fg-0 cUzSHk\">Copy</div></span><span> Expand all </span><span> Collapse all </span></div><div class=\"sc-1d3n1g3-1 cMGcAP sc-107yc6q-0 kVzLlf\"><div class=\"redoc-json\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable \"><span class=\"property token string\">\"applications\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"appId\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"manifest\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"manifestType\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"version\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"title\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"tooltip\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"description\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"images\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"url\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contactEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"supportEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"publisher\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icons\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icon\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"value\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"intents\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"displayName\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contexts\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <span class=\"token punctuation\">{ }</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"message\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></div></div></div></div></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-7\" aria-labelledby=\"react-tabs-6\"></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-9\" aria-labelledby=\"react-tabs-8\"></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-11\" aria-labelledby=\"react-tabs-10\"></div></div></div></div></div></div><div data-section-id=\"tag/Application/paths/~1v1~1apps~1search/get\" id=\"tag/Application/paths/~1v1~1apps~1search/get\" class=\"sc-6itmo6-1 ghcciP\"><div class=\"sc-6itmo6-4 bf7xj3-0 IavJd\"><div class=\"sc-6itmo6-0 diqfaT\"><h2 class=\"shv3r-1 fAUnug\"><a class=\"eb0njo-0 kvqXYL\" href=\"#tag/Application/paths/~1v1~1apps~1search/get\"></a>Retrieve a list of applications<!-- --> </h2><div class=\"zmmjx2-6 dltiCp\"><div class=\"zmmjx2-3 kTspdE\"><h5 class=\"shv3r-4 zmmjx2-5 huVGWs\">Authorizations: </h5></div><div class=\"zmmjx2-4 jAGbXb\"><span class=\"zmmjx2-2 fyEFuw\"><span class=\"zmmjx2-1 kJdFmc\"><a href=\"#section/Authentication/bearerAuth\">bearerAuth</a></span></span></div></div><div></div><div><h3 class=\"zr04gj-0 jKmdQj\"> Responses </h3><div><div class=\"sc-1kbihq-0 kXBEML\"><svg class=\"sc-1g5rdgs-0 fgqOex\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>200<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>OK</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>400<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Bad request.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>403<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Forbidden: Certificate authentication is not allowed for the requested user.</p>\n</span></div></div><div><div class=\"sc-1kbihq-0 jtbdMW\"><svg class=\"sc-1g5rdgs-0 hkGyhI\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg><strong>500<!-- --> </strong><span class=\"sc-1m0b31p-0-span lnSenT\"><p>Server error, see response body for further details.</p>\n</span></div></div></div></div><div class=\"sc-6itmo6-2 sc-6itmo6-3 iJUwRU\"><div class=\"nrhuz6-0 kmORFN\"><div class=\"nrhuz6-2 jmkkdP\"><span class=\"nrhuz6-3 http-verb get klEXcZ\" type=\"get\"> <!-- -->get</span> <span class=\"nrhuz6-1 eYuvls\">/v1/apps/search</span><svg class=\"sc-1g5rdgs-0 gtRsjv\" style=\"margin-right:-25px\" version=\"1.1\" viewBox=\"0 0 24 24\" x=\"0\" xmlns=\"http://www.w3.org/2000/svg\" y=\"0\"><polygon points=\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \"></polygon></svg></div><div class=\"nrhuz6-4 hKgcyu\"><div class=\"nrhuz6-5 kjYYZz\"><div class=\"sc-107yc6q-0 sc-1m0b31p-0 bRDwMm\"></div><div><div class=\"nrhuz6-6 iuqUuR\"><span>/appd</span>/v1/apps/search</div></div></div></div></div><div><h3 class=\"shv3r-3 dlDeJR\"> Response samples </h3><div class=\"sc-1vrf7wa-0 jBYmRf\" data-tabs=\"true\"><ul class=\"react-tabs__tab-list\" role=\"tablist\"><li class=\"tab-success react-tabs__tab--selected\" role=\"tab\" id=\"react-tabs-12\" aria-selected=\"true\" aria-disabled=\"false\" aria-controls=\"react-tabs-13\" tabindex=\"0\">200</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-14\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-15\">400</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-16\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-17\">403</li><li class=\"tab-error\" role=\"tab\" id=\"react-tabs-18\" aria-selected=\"false\" aria-disabled=\"false\" aria-controls=\"react-tabs-19\">500</li></ul><div class=\"react-tabs__tab-panel react-tabs__tab-panel--selected\" role=\"tabpanel\" id=\"react-tabs-13\" aria-labelledby=\"react-tabs-12\"><div><div class=\"futasu-0 wbaPa\">application/json</div><div><div class=\"sc-1d3n1g3-0 iwRsmX\"><div class=\"sc-1rd7dj7-0 dAOSNf\"><span><div class=\"t0v3fg-0 cUzSHk\">Copy</div></span><span> Expand all </span><span> Collapse all </span></div><div class=\"sc-1d3n1g3-1 cMGcAP sc-107yc6q-0 kVzLlf\"><div class=\"redoc-json\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable \"><span class=\"property token string\">\"applications\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"appId\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"manifest\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"manifestType\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"version\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"title\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"tooltip\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"description\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"images\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"url\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contactEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"supportEmail\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"publisher\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icons\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"icon\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"value\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"intents\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><div class=\"collapser\"></div><span class=\"token punctuation\">{</span><span class=\"ellipsis\"></span><ul class=\"obj collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"name\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"displayName\"</span>: <span class=\"token string\">&quot;string&quot;</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"contexts\"</span>: <div class=\"collapser\"></div><span class=\"token punctuation\">[</span><span class=\"ellipsis\"></span><ul class=\"array collapsible\"><li><div class=\"hoverable collapsed\"><span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable collapsed\"><span class=\"property token string\">\"customConfig\"</span>: <span class=\"token punctuation\">{ }</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span></div></li></ul><span class=\"token punctuation\">}</span></div></li></ul><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></div></li><li><div class=\"hoverable \"><span class=\"property token string\">\"message\"</span>: <span class=\"token string\">&quot;string&quot;</span></div></li></ul><span class=\"token punctuation\">}</span></div></div></div></div></div></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-15\" aria-labelledby=\"react-tabs-14\"></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-17\" aria-labelledby=\"react-tabs-16\"></div><div class=\"react-tabs__tab-panel\" role=\"tabpanel\" id=\"react-tabs-19\" aria-labelledby=\"react-tabs-18\"></div></div></div></div></div></div></div><div class=\"sc-13p9gjn-2 egwcPy\"></div></div></div>\n    <script>\n    const __redoc_state = {\"menu\":{\"activeItemIdx\":-1},\"spec\":{\"data\":{\"openapi\":\"3.0.0\",\"info\":{\"version\":\"1.0\",\"title\":\"Application Directory specification\",\"description\":\"Application Directory specification providing both interface definition and objects necessary to construct an application directory service.\\n\\n# Authentication\\n\\n<!-- ReDoc-Inject: <security-definitions> -->\"},\"security\":[{\"bearerAuth\":[]}],\"paths\":{\"/v1/apps/{appId}\":{\"get\":{\"summary\":\"Retrieve an application defintion\",\"parameters\":[{\"name\":\"appId\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"description\":\"OK\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Application\"}}}},\"400\":{\"description\":\"Bad request.\",\"content\":{\"*/*\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"403\":{\"description\":\"Forbidden: Certificate authentication is not allowed for the requested user.\",\"content\":{\"*/*\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"500\":{\"description\":\"Server error, see response body for further details.\",\"content\":{\"*/*\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}}},\"tags\":[\"Application\"]}},\"/v1/apps\":{\"post\":{\"summary\":\"Create a new application definition\",\"responses\":{\"200\":{\"description\":\"OK\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApplicationSearchResponse\"}}}},\"400\":{\"description\":\"Bad request.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"403\":{\"description\":\"Forbidden: Certificate authentication is not allowed for the requested user.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"500\":{\"description\":\"Server error, see response body for further details.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}}},\"tags\":[\"Application\"],\"requestBody\":{\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Application\"}}},\"required\":true}}},\"/v1/apps/search\":{\"get\":{\"summary\":\"Retrieve a list of applications\",\"responses\":{\"200\":{\"description\":\"OK\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApplicationSearchResponse\"}}}},\"400\":{\"description\":\"Bad request.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"403\":{\"description\":\"Forbidden: Certificate authentication is not allowed for the requested user.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}},\"500\":{\"description\":\"Server error, see response body for further details.\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ErrorDTO\"}}}}},\"tags\":[\"Application\"]}}},\"servers\":[{\"url\":\"/appd\"}],\"components\":{\"securitySchemes\":{\"bearerAuth\":{\"type\":\"http\",\"scheme\":\"bearer\",\"bearerFormat\":\"JWT\"}},\"schemas\":{\"ErrorDTO\":{\"type\":\"object\",\"properties\":{\"code\":{\"type\":\"integer\",\"format\":\"int32\"},\"message\":{\"type\":\"string\"}}},\"Application\":{\"description\":\"Defines an application retrieved from an FDC3 App Directory, which can then be launched.\\nLaunching typically means running for a user on a desktop.  The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\\n\",\"required\":[\"appId\",\"name\",\"manifest\",\"manifestType\"],\"properties\":{\"appId\":{\"type\":\"string\",\"description\":\"The unique application identifier located within a specific application directory instance.\\n\"},\"name\":{\"type\":\"string\",\"description\":\"The name of the application.\\nThe name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app.\\nThe same appName could occur in other directories. We are not currently specifying app name conventions in the document.\\n\"},\"manifest\":{\"type\":\"string\",\"description\":\"URI or full JSON of the application manifest providing all details related to launch and use requirements as described by the vendor.\\nThe format of this manifest is vendor specific, but can be identified by the manifestType attribute.\\n\"},\"manifestType\":{\"type\":\"string\",\"description\":\"The manifest type which relates to the format and structure of the manifest content. The definition is based on the vendor specific format and definition outside of this specification.\\n\"},\"version\":{\"type\":\"string\",\"description\":\"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"},\"title\":{\"type\":\"string\",\"description\":\"Optional title for the application, if missing use appName, typically used in a launcher UI.\"},\"tooltip\":{\"type\":\"string\",\"description\":\"Optional tooltip description e.g. for a launcher\"},\"description\":{\"type\":\"string\",\"description\":\"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"},\"images\":{\"type\":\"array\",\"description\":\"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\"items\":{\"$ref\":\"#/components/schemas/AppImage\"}},\"contactEmail\":{\"type\":\"string\",\"description\":\"Optional e-mail to receive queries about the application\"},\"supportEmail\":{\"type\":\"string\",\"description\":\"Optional e-mail to receive support requests for the application\"},\"publisher\":{\"type\":\"string\",\"description\":\"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"},\"icons\":{\"type\":\"array\",\"description\":\"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\"items\":{\"$ref\":\"#/components/schemas/Icon\"}},\"customConfig\":{\"type\":\"array\",\"description\":\"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.\",\"items\":{\"$ref\":\"#/components/schemas/NameValuePair\"}},\"intents\":{\"type\":\"array\",\"description\":\"The list of intents implemented by the Application as defined by https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\\n\",\"items\":{\"$ref\":\"#/components/schemas/Intent\"}}}},\"ApplicationSearchResponse\":{\"properties\":{\"applications\":{\"type\":\"array\",\"description\":\"List of applications\\n\",\"items\":{\"$ref\":\"#/components/schemas/Application\"}},\"message\":{\"type\":\"string\",\"description\":\"Response message providing status of query\\n\"}}},\"NameValuePair\":{\"description\":\"Simple name value pair\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"name\"},\"value\":{\"type\":\"string\",\"description\":\"value\"}}},\"Icon\":{\"description\":\"Icon holder\",\"properties\":{\"icon\":{\"type\":\"string\",\"description\":\"Icon URL\"}}},\"AppImage\":{\"description\":\"App Image holder\",\"properties\":{\"url\":{\"type\":\"string\",\"description\":\"App Image URL\"}}},\"Intent\":{\"description\":\"An intent definition as defined by spec https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\"required\":[\"name\"],\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"The name of the intent to 'launch'. In this case the name of an Intent supported by an Application.\"},\"displayName\":{\"type\":\"string\",\"description\":\"An optional display name for the intent that may be used in UI instead of the name.\"},\"contexts\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"A comma sepaarted list of the types of contexts the intent offered by the application can process.  where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"},\"customConfig\":{\"type\":\"object\",\"description\":\"Custom configuration for the intent that may be required for a particular desktop agent.\"}}}}}}},\"searchIndex\":{\"store\":[\"section/Authentication\",\"tag/Application\",\"tag/Application/paths/~1v1~1apps~1{appId}/get\",\"tag/Application/paths/~1v1~1apps/post\",\"tag/Application/paths/~1v1~1apps~1search/get\"],\"index\":{\"version\":\"2.3.5\",\"fields\":[\"title\",\"description\"],\"fieldVectors\":[[\"title/0\",[0,1.821]],[\"description/0\",[1,0.897,2,0.526,3,0.526]],[\"title/1\",[4,0.378]],[\"description/1\",[]],[\"title/2\",[4,0.261,5,0.794,6,1.258]],[\"description/2\",[]],[\"title/3\",[4,0.226,7,1.089,8,1.089,9,1.089]],[\"description/3\",[]],[\"title/4\",[4,0.261,5,0.794,10,1.258]],[\"description/4\",[]]],\"invertedIndex\":[[\"\",{\"_index\":1,\"title\":{},\"description\":{\"0\":{}}}],[\"applic\",{\"_index\":4,\"title\":{\"1\":{},\"2\":{},\"3\":{},\"4\":{}},\"description\":{}}],[\"authent\",{\"_index\":0,\"title\":{\"0\":{}},\"description\":{}}],[\"creat\",{\"_index\":7,\"title\":{\"3\":{}},\"description\":{}}],[\"definit\",{\"_index\":9,\"title\":{\"3\":{}},\"description\":{}}],[\"defint\",{\"_index\":6,\"title\":{\"2\":{}},\"description\":{}}],[\"list\",{\"_index\":10,\"title\":{\"4\":{}},\"description\":{}}],[\"new\",{\"_index\":8,\"title\":{\"3\":{}},\"description\":{}}],[\"redoc-inject\",{\"_index\":2,\"title\":{},\"description\":{\"0\":{}}}],[\"retriev\",{\"_index\":5,\"title\":{\"2\":{},\"4\":{}},\"description\":{}}],[\"security-definit\",{\"_index\":3,\"title\":{},\"description\":{\"0\":{}}}]],\"pipeline\":[]}},\"options\":{}};\n\n    var container = document.getElementById('redoc');\n    Redoc.hydrate(__redoc_state, container);;\n\n    </script>\n</body>\n\n</html>"
  },
  {
    "path": "website/static/schemas/1.1/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/1.1/app-directory.yaml'></redoc>\n<script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"></script>\n"
  },
  {
    "path": "website/static/schemas/1.1/app-directory.yaml",
    "content": "openapi: 3.0.0\ninfo:\n  title: FDC3 Application Directory\n  version: '1.1'\n  description: >\n    Application Directory specification providing both interface\n    definition and objects necessary to construct an application directory\n    service.\n  x-logo:\n    url: '/img/fdc3-logo-2019-color.png'\n    altText: FDC3 logo\nsecurity:\n- bearerAuth: []\npaths:\n  '/v1/apps/{appId}':\n    get:\n      summary: Retrieve an application defintion\n      parameters:\n        - name: appId\n          in: path\n          required: true\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Application'\n        '400':\n          description: Bad request.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n  /v1/apps:\n    post:\n      summary: Create a new application definition\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponse'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Application'\n        required: true\n  /v1/apps/search:\n    get:\n      summary: Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter\n              values should self describe search format and type (e.g. Regex)\n      parameters:\n        - in: query\n          name: appId\n          schema:\n            type: string\n          required: false\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        - in: query\n          name: name\n          schema:\n            type: string\n          required: false\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        - in: query\n          name: manifest\n          schema:\n            type: string\n          required: false\n          description: >\n            URI or full JSON of the application manifest providing all details related to launch\n            and use requirements as described by the vendor.\n\n            The format of this manifest is vendor specific, but can be identified by\n            the manifestType attribute.\n        - in: query\n          name: version\n          schema:\n            type: string\n          required: false\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        - in: query\n          name: title\n          schema:\n            type: string\n          required: false\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        - in: query\n          name: tooltip\n          schema:\n            type: string\n          required: false\n          description: Optional tooltip description e.g. for a launcher\n        - in: query\n          name: description\n          schema:\n            type: string\n          required: false\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        - in: query\n          name: intent_name\n          schema:\n            type: string\n          required: false\n          description: name of intent\n        - in: query\n          name: intent_displayName\n          schema:\n            type: string\n          required: false\n          description: displayName of intent\n        - in: query\n          name: intent_context\n          schema:\n            type: string\n          required: false\n          description: search contexts list\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponse'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n \nservers:\n  - url: /appd\ncomponents:\n  securitySchemes:\n    bearerAuth:            # arbitrary name for the security scheme\n      type: http\n      scheme: bearer\n      bearerFormat: JWT    # optional, arbitrary value for documentation purposes\n  schemas:\n    ErrorDTO:\n      type: object\n      properties:\n        code:\n          type: integer\n          format: int32\n        message:\n          type: string\n    Application:\n      description: >\n        Defines an application retrieved from an FDC3 App Directory, which can\n        then be launched.\n\n        Launching typically means running for a user on a desktop. \n        The details around 'launching' including who or what might do it, and how the launch action is initiated are\n        discussed elsewhere in the FDC3 App Directory spec.\n      required:\n        - appId\n        - name\n        - manifest\n        - manifestType\n      properties:\n        appId:\n          type: string\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        name:\n          type: string\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        manifest:\n          type: string\n          description: >\n            URI or full JSON of the application manifest providing all details related to launch\n            and use requirements as described by the vendor.\n\n            The format of this manifest is vendor specific, but can be identified by\n            the manifestType attribute.\n        manifestType:\n          type: string\n          description: >\n            The manifest type which relates to the format and structure of the manifest content.\n            The definition is based on the vendor specific format and definition outside of this specification.\n        version:\n          type: string\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        title:\n          type: string\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        tooltip:\n          type: string\n          description: Optional tooltip description e.g. for a launcher\n        description:\n          type: string\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        images:\n          type: array\n          description: >-\n            Array of images to show the user when they are looking at app\n            description. Each image can have an optional description/tooltip\n          items:\n            $ref: '#/components/schemas/AppImage'\n        contactEmail:\n          type: string\n          description: Optional e-mail to receive queries about the application\n        supportEmail:\n          type: string\n          description: Optional e-mail to receive support requests for the application\n        publisher:\n          type: string\n          description: >-\n            The name of the company that owns the application. The publisher has\n            control over their namespace/app/signature.\n        icons:\n          type: array\n          description: >-\n            Holds Icons used for the application, a Launcher may be able to use\n            multiple Icon sizes or there may be a 'button' Icon\n          items:\n            $ref: '#/components/schemas/Icon'\n        customConfig:\n          type: array\n          description: >-\n            An optional set of name value pairs that can be used to deliver\n            custom data from an App Directory to a launcher.\n          items:\n            $ref: '#/components/schemas/NameValuePair'\n        intents:\n          type: array\n          description: >\n            The list of intents implemented by the Application as defined by\n            https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n          items:\n            $ref: '#/components/schemas/Intent'\n    ApplicationSearchResponse:\n      properties:\n        applications:\n          type: array\n          description: |\n            List of applications\n          items:\n            $ref: '#/components/schemas/Application'\n        message:\n          type: string\n          description: |\n            Response message providing status of query\n    NameValuePair:\n      description: Simple name value pair\n      properties:\n        name:\n          type: string\n          description: name\n        value:\n          type: string\n          description: value\n    Icon:\n      description: Icon holder\n      properties:\n        icon:\n          type: string\n          description: Icon URL\n    AppImage:\n      description: App Image holder\n      properties:\n        url:\n          type: string\n          description: App Image URL\n    Intent:\n      description: >-\n        An intent definition as defined by spec\n        https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n      required:\n        - name\n      properties:\n        name:\n          type: string\n          description: The name of the intent to 'launch'. In this case the name of an Intent supported by an Application.\n        displayName:\n          type: string\n          description: An optional display name for the intent that may be used in UI instead of the name.\n        contexts:\n          type: array\n          items:\n            type: string\n          description: >-\n            A comma sepaarted list of the types of contexts the intent offered by the application can process. \n            where the first part of the context type is the namespace e.g.\"fdc3.contact, org.symphony.contact\"\n        customConfig:\n          type: object\n          description: >-\n            Custom configuration for the intent that may be required for a\n            particular desktop agent.\n"
  },
  {
    "path": "website/static/schemas/1.1/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contact\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"email\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contactList\" },\n    \"contacts\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"contact.schema.json#\" }\n    }\n  },\n  \"required\": [\"contacts\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"properties\": {\n    \"type\": { \"type\": \"string\" },\n    \"name\": { \"type\": \"string\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"additionalProperties\": { \"type\": \"string\" }\n    }\n  },\n  \"required\": [\"type\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.country\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"ISOALPHA2\": { \"type\": \"string\" },\n        \"ISOALPHA3\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrument\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"BBG\": { \"type\": \"string\" },\n        \"CUSIP\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" },\n        \"FIGI\": { \"type\": \"string\" },\n        \"ISIN\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"RIC\": { \"type\": \"string\" },\n        \"SEDOL\": { \"type\": \"string\" },\n        \"ticker\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrumentList\" },\n    \"instruments\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"instrument.schema.json#\" }\n    }\n  },\n  \"required\": [\"instruments\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.organization\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"LEI\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.portfolio\" },\n    \"positions\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"position.schema.json#\" }\n    }\n  },\n  \"required\": [\"positions\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.1/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.1/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.position\" },\n    \"instrument\": { \"$ref\": \"instrument.schema.json#\" },\n    \"holding\": { \"type\": \"number\", \"minimum\": 0 }\n  },\n  \"required\": [\"instrument\",\"holding\"]\n}"
  },
  {
    "path": "website/static/schemas/1.2/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/1.2/app-directory.yaml'></redoc>\n<script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"></script>\n"
  },
  {
    "path": "website/static/schemas/1.2/app-directory.yaml",
    "content": "openapi: 3.0.0\ninfo:\n  title: FDC3 Application Directory\n  version: '1.2'\n  description: >\n    Application Directory specification providing both interface\n    definition and objects necessary to construct an application directory\n    service.\n  x-logo:\n    url: '/img/fdc3-logo-2019-color.png'\n    altText: FDC3 logo\nsecurity:\n- bearerAuth: []\npaths:\n  '/v1/apps/{appId}':\n    get:\n      summary: Retrieve an application definition\n      parameters:\n        - name: appId\n          in: path\n          required: true\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Application'\n        '400':\n          description: Bad request.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n  /v1/apps:\n    post:\n      summary: Create a new application definition\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponse'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Application'\n        required: true\n  /v1/apps/search:\n    get:\n      summary: Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter\n              values should self describe search format and type (e.g. Regex)\n      parameters:\n        - in: query\n          name: appId\n          schema:\n            type: string\n          required: false\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        - in: query\n          name: name\n          schema:\n            type: string\n          required: false\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        - in: query\n          name: manifest\n          schema:\n            type: string\n          required: false\n          description: >\n            URI or full JSON of the application manifest providing all details related to launch\n            and use requirements as described by the vendor.\n\n            The format of this manifest is vendor specific, but can be identified by\n            the manifestType attribute.\n        - in: query\n          name: version\n          schema:\n            type: string\n          required: false\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        - in: query\n          name: title\n          schema:\n            type: string\n          required: false\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        - in: query\n          name: tooltip\n          schema:\n            type: string\n          required: false\n          description: Optional tooltip description e.g. for a launcher\n        - in: query\n          name: description\n          schema:\n            type: string\n          required: false\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        - in: query\n          name: intent_name\n          schema:\n            type: string\n          required: false\n          description: name of intent\n        - in: query\n          name: intent_displayName\n          schema:\n            type: string\n          required: false\n          description: displayName of intent\n        - in: query\n          name: intent_context\n          schema:\n            type: string\n          required: false\n          description: search contexts list\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponse'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n \nservers:\n  - url: /appd\ncomponents:\n  securitySchemes:\n    bearerAuth:            # arbitrary name for the security scheme\n      type: http\n      scheme: bearer\n      bearerFormat: JWT    # optional, arbitrary value for documentation purposes\n  schemas:\n    ErrorDTO:\n      type: object\n      properties:\n        code:\n          type: integer\n          format: int32\n        message:\n          type: string\n    Application:\n      description: >\n        Defines an application retrieved from an FDC3 App Directory, which can\n        then be launched.\n\n        Launching typically means running for a user on a desktop. \n        The details around 'launching' including who or what might do it, and how the launch action is initiated are\n        discussed elsewhere in the FDC3 App Directory spec.\n      required:\n        - appId\n        - name\n        - manifest\n        - manifestType\n      properties:\n        appId:\n          type: string\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        name:\n          type: string\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        manifest:\n          type: string\n          description: >\n            URI or full JSON of the application manifest providing all details related to launch\n            and use requirements as described by the vendor.\n\n            The format of this manifest is vendor specific, but can be identified by\n            the manifestType attribute.\n        manifestType:\n          type: string\n          description: >\n            The manifest type which relates to the format and structure of the manifest content.\n            The definition is based on the vendor specific format and definition outside of this specification.\n        version:\n          type: string\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        title:\n          type: string\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        tooltip:\n          type: string\n          description: Optional tooltip description e.g. for a launcher\n        description:\n          type: string\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        images:\n          type: array\n          description: >-\n            Array of images to show the user when they are looking at app\n            description. Each image can have an optional description/tooltip\n          items:\n            $ref: '#/components/schemas/AppImage'\n        contactEmail:\n          type: string\n          description: Optional e-mail to receive queries about the application\n        supportEmail:\n          type: string\n          description: Optional e-mail to receive support requests for the application\n        publisher:\n          type: string\n          description: >-\n            The name of the company that owns the application. The publisher has\n            control over their namespace/app/signature.\n        icons:\n          type: array\n          description: >-\n            Holds Icons used for the application, a Launcher may be able to use\n            multiple Icon sizes or there may be a 'button' Icon\n          items:\n            $ref: '#/components/schemas/Icon'\n        customConfig:\n          type: array\n          description: >-\n            An optional set of name value pairs that can be used to deliver\n            custom data from an App Directory to a launcher.\n          items:\n            $ref: '#/components/schemas/NameValuePair'\n        intents:\n          type: array\n          description: >\n            The list of intents implemented by the Application as defined by\n            https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n          items:\n            $ref: '#/components/schemas/Intent'\n    ApplicationSearchResponse:\n      properties:\n        applications:\n          type: array\n          description: |\n            List of applications\n          items:\n            $ref: '#/components/schemas/Application'\n        message:\n          type: string\n          description: |\n            Response message providing status of query\n    NameValuePair:\n      description: Simple name value pair\n      properties:\n        name:\n          type: string\n          description: name\n        value:\n          type: string\n          description: value\n    Icon:\n      description: Icon holder\n      properties:\n        icon:\n          type: string\n          description: Icon URL\n    AppImage:\n      description: App Image holder\n      properties:\n        url:\n          type: string\n          description: App Image URL\n    Intent:\n      description: >-\n        An intent definition as defined by spec\n        https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n      required:\n        - name\n      properties:\n        name:\n          type: string\n          description: The name of the intent to 'launch'. In this case the name of an Intent supported by an Application.\n        displayName:\n          type: string\n          description: An optional display name for the intent that may be used in UI instead of the name.\n        contexts:\n          type: array\n          items:\n            type: string\n          description: >-\n            A comma separated list of the types of contexts the intent offered by the application can process. \n            where the first part of the context type is the namespace e.g.\"fdc3.contact, org.symphony.contact\"\n        customConfig:\n          type: object\n          description: >-\n            Custom configuration for the intent that may be required for a\n            particular desktop agent.\n"
  },
  {
    "path": "website/static/schemas/1.2/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contact\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"email\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contactList\" },\n    \"contacts\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"contact.schema.json#\" }\n    }\n  },\n  \"required\": [\"contacts\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"properties\": {\n    \"type\": { \"type\": \"string\" },\n    \"name\": { \"type\": \"string\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"additionalProperties\": { \"type\": \"string\" }\n    }\n  },\n  \"required\": [\"type\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.country\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"ISOALPHA2\": { \"type\": \"string\" },\n        \"ISOALPHA3\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrument\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"BBG\": { \"type\": \"string\" },\n        \"CUSIP\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" },\n        \"FIGI\": { \"type\": \"string\" },\n        \"ISIN\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"RIC\": { \"type\": \"string\" },\n        \"SEDOL\": { \"type\": \"string\" },\n        \"ticker\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrumentList\" },\n    \"instruments\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"instrument.schema.json#\" }\n    }\n  },\n  \"required\": [\"instruments\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.organization\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"LEI\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.portfolio\" },\n    \"positions\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"position.schema.json#\" }\n    }\n  },\n  \"required\": [\"positions\"]\n}\n"
  },
  {
    "path": "website/static/schemas/1.2/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/1.2/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.position\" },\n    \"instrument\": { \"$ref\": \"instrument.schema.json#\" },\n    \"holding\": { \"type\": \"number\", \"minimum\": 0 }\n  },\n  \"required\": [\"instrument\",\"holding\"]\n}"
  },
  {
    "path": "website/static/schemas/2.0/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/2.0/app-directory.yaml'></redoc>\n<script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"></script>"
  },
  {
    "path": "website/static/schemas/2.0/app-directory.yaml",
    "content": "openapi: 3.0.0\ninfo:\n  title: FDC3 Application Directory\n  version: '2.0'\n  description: >\n    Application Directory specification providing both interface\n    definition and objects necessary to construct an application directory\n    service.\n  x-logo:\n    url: '/img/fdc3-logo-2019-color.png'\n    altText: FDC3 logo\nsecurity:\n- bearerAuth: []\npaths:\n  '/v2/apps/{appId}':\n    get:\n      summary: Retrieve an application definition\n      parameters:\n        - name: appId\n          in: path\n          required: true\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Application'\n              examples:\n                MyAppDefinition:\n                  $ref: '#/components/examples/MyAppDefinition'\n                FDC3WorkbenchAppDefinition:\n                  $ref: '#/components/examples/FDC3WorkbenchAppDefinition'\n        '400':\n          description: Bad request.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n  /v2/apps:\n    get:\n      summary: Retrieve all application definitions\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/AllApplicationsResponse'\n              examples:\n                AllAppsResponse:\n                  $ref: '#/components/examples/AllAppsResponse'\n        '400':\n          description: Bad request.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n  '/v1/apps/{appId}':\n    get:\n      deprecated: true\n      summary: Retrieve an application definition\n      parameters:\n        - name: appId\n          in: path\n          required: true\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationV1'\n        '400':\n          description: Bad request.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            '*/*':\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n  /v1/apps:\n    post:\n      deprecated: true\n      summary: Create a new application definition\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponseV1'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/ApplicationV1'\n        required: true\n  /v1/apps/search:\n    get:\n      deprecated: true\n      summary: Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter\n              values should self describe search format and type (e.g. Regex)\n      parameters:\n        - in: query\n          name: appId\n          schema:\n            type: string\n          required: false\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        - in: query\n          name: name\n          schema:\n            type: string\n          required: false\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        - in: query\n          name: version\n          schema:\n            type: string\n          required: false\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        - in: query\n          name: title\n          schema:\n            type: string\n          required: false\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        - in: query\n          name: tooltip\n          schema:\n            type: string\n          required: false\n          description: Optional tooltip description e.g. for a launcher\n        - in: query\n          name: description\n          schema:\n            type: string\n          required: false\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        - in: query\n          name: intent_name\n          schema:\n            type: string\n          required: false\n          description: name of intent\n        - in: query\n          name: intent_displayName\n          schema:\n            type: string\n          required: false\n          description: displayName of intent\n        - in: query\n          name: intent_context\n          schema:\n            type: string\n          required: false\n          description: search contexts list\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ApplicationSearchResponseV1'\n        '400':\n          description: Bad request.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '403':\n          description: >-\n            Forbidden: Certificate authentication is not allowed for the\n            requested user.\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n        '500':\n          description: 'Server error, see response body for further details.'\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorDTO'\n      tags:\n        - Application\n\nservers:\n  - url: /appd\ncomponents:\n  securitySchemes:\n    bearerAuth:            # arbitrary name for the security scheme\n      type: http\n      scheme: bearer\n      bearerFormat: JWT    # optional, arbitrary value for documentation purposes\n  schemas:\n    ErrorDTO:\n      type: object\n      properties:\n        code:\n          type: integer\n          format: int32\n        message:\n          type: string\n    BaseApplication:\n      properties:\n        appId:\n          type: string\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        name:\n          type: string\n          description: >\n            The name of the application.\n\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        type:\n          $ref: '#/components/schemas/Type'\n        details:\n          $ref: '#/components/schemas/LaunchDetails'\n        version:\n          type: string\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        title:\n          type: string\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        tooltip:\n          type: string\n          description: Optional tooltip description e.g. for a launcher\n        lang:\n          type: string\n          pattern: '^[a-z]{2}(-[a-zA-Z0-9]{2,8}){0,1}$'\n          description: >- \n            A language tag that specifies the primary language of both the\n            application and its AppD entry, as defined by IETF RFC 5646.\n        description:\n          type: string\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. \n        categories:\n          description: |\n            An array of string categories that describe the application. \n            These are meant as a hint to catalogs or stores listing FDC3-enabled \n            apps and it is expected that these will make a best effort to find \n            appropriate categories (or category) under which to list the app. \n            AppD record authors are encouraged to use lower-case and, where \n            possible, to select categories from the following list:\n\n            - allocations\n            - analytics\n            - charts\n            - chat\n            - communication\n            - compliance\n            - crm\n            - developer tools\n            - events\n            - execution management\n            - file sharing\n            - market data\n            - news\n            - networking\n            - office apps\n            - order management\n            - other\n            - portfolio management\n            - presentation\n            - pricing\n            - productivity\n            - research\n            - risk\n            - screen sharing\n            - security\n            - spreadsheet\n            - trade cost analysis\n            - trading system\n            - training\n            - travel\n            - video\n            - visualization\n            - weather\n          type: array\n          items:\n            type: string\n        icons:\n          type: array\n          description: >-\n            Holds Icons used for the application, a Launcher may be able to use\n            multiple Icon sizes or there may be a 'button' Icon\n          items:\n            $ref: '#/components/schemas/Icon'\n        screenshots:\n          type: array\n          description: >-\n            Array of images to show the user when they are looking at app\n            description. Each image can have an optional description/tooltip\n          items:\n            $ref: '#/components/schemas/Screenshot'\n        contactEmail:\n          type: string\n          format: email\n          description: Optional e-mail to receive queries about the application\n        supportEmail:\n          type: string\n          format: email\n          description: Optional e-mail to receive support requests for the application\n        moreInfo:\n          type: string\n          format: uri\n          description: Optional URL that provides more information about the application\n        publisher:\n          type: string\n          description: >-\n            The name of the company that owns the application. The publisher has\n            control over their namespace/app/signature.\n        customConfig:\n          type: array\n          description: >-\n            An optional set of name value pairs that can be used to deliver\n            custom data from an App Directory to a launcher.\n          items:\n            $ref: '#/components/schemas/NameValuePair'\n        hostManifests:\n          $ref: '#/components/schemas/HostManifests'\n        interop:\n          $ref: '#/components/schemas/Interop'\n    Application:\n      description: >\n        Defines an application retrieved from an FDC3 App Directory, which can\n        then be launched.\n\n        Launching typically means running for a user on a desktop.\n        The details around 'launching' including who or what might do it, and how the launch action is initiated are\n        discussed elsewhere in the FDC3 App Directory spec.\n      required:\n        - appId\n        - name\n        - type\n        - details\n      allOf:\n        - $ref: '#/components/schemas/BaseApplication'\n        - type: object\n          properties:\n            localizedVersions:\n              $ref: '#/components/schemas/LocalizedVersions'\n    AllApplicationsResponse:\n      properties:\n        applications:\n          type: array\n          description: |\n            List of applications\n          items:\n            $ref: '#/components/schemas/Application'\n        message:\n          type: string\n          description: |\n            Response message providing status of query\n    NameValuePair:\n      description: Simple name value pair\n      properties:\n        name:\n          type: string\n          description: name\n        value:\n          type: string\n          description: value\n    Icon:\n      description: Icon holder\n      properties:\n        src:\n          type: string\n          format: uri\n          description: Icon URL\n        size:\n          type: string\n          description: Icon dimension formatted as `<height>x<width>`\n        type:\n          type: string\n          description: Image media type. If not present the Desktop Agent may use the src file extension\n    Screenshot:\n      description: Images representing the app in common usage scenarios\n      properties:\n        src:\n          type: string\n          format: uri\n          description: App Image URL\n        size:\n          type: string\n          description: Image dimension formatted as `<height>x<width>`\n        type:\n          type: string\n          description: Image media type. If not present the Desktop Agent may use the src file extension.\n        label:\n          type: string\n          description: Optional caption for the image\n    Type:\n      type: string\n      description: |\n        The technology type that is used to launch and run the application. \n        Each application type implies a particular set of launch `details`.\n        The supported types include:\n\n        - `web`: Web applications launched via a URL\n        - `native`: Native applications pre-installed on a device and launch via a filesystem path\n        - `citrix`: Apps virtualized via Citrix\n        - `onlineNative`: Native apps that have an online launcher, e.g. online ClickOnce app deployments.\n        - `other`: Used to represent apps that do not conform to or cannot be launched via the other types, and are likely to be defined solely by a hostManifest.\n\n        FDC3 Desktop Agents MUST support at least the `web` application type and MAY support any or all of the other types.\n      enum:\n        - web\n        - native\n        - citrix\n        - onlineNative\n        - other\n    LaunchDetails:\n      description: >-\n        The type specific launch details of the application. These details are intended to be \n        vendor-agnostic and MAY be duplicated or overridden by details provided in the hostManifests \n        object for a specific host.\n      anyOf:\n        - $ref: '#/components/schemas/WebAppDetails'\n        - $ref: '#/components/schemas/NativeAppDetails'\n        - $ref: '#/components/schemas/CitrixAppDetails'\n        - $ref: '#/components/schemas/OnlineNativeAppDetails'\n        - $ref: '#/components/schemas/OtherAppDetails'\n    WebAppDetails:\n      description: 'Properties used to launch apps with `type: web`.'\n      required:\n        - url\n      properties:\n        url:\n          type: string\n          format: uri\n          description: Application start URL.\n      additionalProperties: false\n    NativeAppDetails:\n      description: 'Properties used to launch apps with `type: native` that are already installed on the device.'\n      required:\n        - path\n      properties:\n        path:\n          type: string\n          description: The path on disk from which the application is launched.\n        arguments:\n          type: string\n          description: Arguments that must be passed on the command line to launch the app in the expected configuration.\n      additionalProperties: false\n    CitrixAppDetails:\n      description: 'Properties used to launch apps virtualized apps with `type: citrix`.'\n      required:\n        - alias\n      properties:\n        alias:\n          type: string\n          description: The Citrix alias / name of the virtual app (passed to the Citrix SelfService qlaunch parameter).\n        arguments:\n          type: string\n          description: Arguments that must be passed on the command line to launch the app in the expected configuration.\n      additionalProperties: false\n    OnlineNativeAppDetails:\n      description: 'Properties used to launch a native apps with `type: onlineNative` that have an online launcher, e.g. online ClickOnce app deployments.'\n      required:\n        - url\n      properties:\n        url:\n          type: string\n          format: uri\n          description: Application URL.\n      additionalProperties: false\n    OtherAppDetails:\n      description: 'Apps with `type: other` are defined by a hostManifest and do not require other details.'\n      additionalProperties: false\n    HostManifests:\n      type: object\n      description: >-\n        A mapping from host name to a host-specific application manifest object or URI\n        from which that manifest can be retrieved. The manifest should provide details required to\n        launch and use the application within the specified host. The manifest _MAY_ duplicate or \n        override information provided in the `details` field.\n      additionalProperties:\n        x-additionalPropertiesName: Host name\n        oneOf:\n          - type: string   # URI pointing to a JSON containing all host specific properties\n            format: uri\n          - $ref: '#/components/schemas/HostManifest'\n    HostManifest:\n      type: object\n      description: >-\n        Object containing all host specific properties.\n    LocalizedVersions:\n      type: object # keys should be constrained to valid language tags '^[a-z]{2}(-[a-zA-Z0-9]{2,8}){0,1}$' - not possible to express in OpenAPI without moving to v3.1.0 and the javascript/jsonschema version\n      description: >\n        Provides localized alternatives to any field of the AppD record, which may also refer to an alternative\n        version of the application that is also localized (e.g. by providing customConfig or an alternative URL). \n        The keys to this object should be language tags as defined by IETF RFC 5646, e.g. en, en-GB or fr-FR.\n      additionalProperties:\n        x-additionalPropertiesName: Language tag\n        $ref: '#/components/schemas/BaseApplication' # due to a bug in redoc this may display as a recursive definition, it is not. It will render correctly in swagger and other OpenAPI parsers.\n    Intent:\n      description: >-\n        Definition of an intent that an app listens for\n      required:\n        - contexts\n      properties:\n        displayName:\n          type: string\n          description: An optional display name for the intent that may be used in UI instead of the name.\n        contexts:\n          type: array\n          items:\n            type: string\n          description: >-\n            A comma separated list of the types of contexts the intent offered by the application can process,  \n            where the first part of the context type is the namespace e.g.\"fdc3.contact, org.symphony.contact\"\n        resultType:\n          type: string\n          description: >-\n            An optional type for output returned by the application, if any, when resolving this intent. \n            May indicate a context type by type name (e.g. \"fdc3.instrument\"), a channel (e.g. \"channel\") \n            or a combination that indicates a channel that returns a particular context type \n            (e.g. \"channel<fdc3.instrument>\").\n        customConfig:\n          type: object\n          description: >-\n            Custom configuration for the intent that may be required for a\n            particular desktop agent.\n    Interop:\n      type: object\n      description: |\n        Metadata that describes how the application uses FDC3 APIs. This metadata serves multiple purposes:\n        \n        - It supports intent resolution by a desktop agent, by declaring what intents an app listens for.\n        - It may be used, for example in an app catalog UI, to find apps that 'interoperate with' other apps. \n        - It provides a standard location to document how the app interacts with user channels, app channels, \n          and intents, for use by other app developers and desktop assemblers.\n      properties:\n        intents:\n          type: object\n          description: Describes the app's interactions with intents.\n          properties:\n            listensFor:\n              type: object\n              description: | \n                A mapping of Intents names that an app listens for via `fdc3.addIntentListener()` to their \n                configuration. \n                \n                Used to support intent resolution by desktop agents. Replaces the `intents` element used in appD records prior to FDC3 2.0. \n              additionalProperties:\n                x-additionalPropertiesName: Intent name\n                $ref: '#/components/schemas/Intent'\n            raises:\n              type: object\n              description: | \n                A mapping of Intent names that an app raises (via `fdc3.raiseIntent`) to an array of context \n                type names that it may be raised with.\n\n                Use the intent name \"any\" to represent use of the `fdc3.raiseIntentForContext` and \n                `fdc3.findIntentForContext` functions, which allow the user to select from intents available for a \n                specified context type.\n\n                This metadata is not currently used by the desktop agent, but is provided to help find apps\n                that will interoperate with this app and to document API interactions for use by other app\n                developers.\n              additionalProperties:\n                x-additionalPropertiesName: Intent name\n                type: array\n                description: Context type names that the intent may be raised with.\n                items:\n                  type: string\n        userChannels:\n          type: object\n          description: |\n            Describes the application's use of context types on User Channels.\n\n            This metadata is not currently used by the desktop agent, but is provided to help find apps\n            that will interoperate with this app and to document API interactions for use by other app\n            developers.\n          properties:\n            broadcasts:\n              type: array\n              description: Context type names that are broadcast by the application.\n              items:\n                type: string\n            listensFor:\n              type: array\n              description: Context type names that the application listens for.\n              items:\n                type: string\n        appChannels:\n          type: array\n          description: | \n            Describes the application's use of App Channels.\n\n            This metadata is not currently used by the desktop agent, but is provided to help find apps \n            that will interoperate with this app and to document API interactions for use by other app \n            developers.\n          items:\n            type: object\n            required:\n              - name\n            properties:\n              name:\n                type: string\n                description: The name of the App Channel.\n              description:\n                type: string\n                description: A description of how the channel is used.\n              broadcasts:\n                type: array\n                description: Context type names that are broadcast by the application on the channel.\n                items:\n                  type: string\n              listensFor:\n                type: array\n                description: Context type names that the application listens for on the channel.\n                items:\n                  type: string\n    AppImageV1:\n      description: App Image holder\n      properties:\n        url:\n          type: string\n          format: uri\n          description: App Image URL\n    IconV1:\n      description: (Deprecated v1 API version) Icon holder\n      properties:\n        icon:\n          type: string\n          format: uri\n          description: Icon URL\n    IntentV1:\n      description: >-\n        (Deprecated v1 API version) An intent definition as defined by spec\n        https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n      required:\n        - name\n      properties:\n        name:\n          type: string\n          description: The name of the intent to 'launch'. In this case the name of an Intent supported by an application.\n        displayName:\n          type: string\n          description: An optional display name for the intent that may be used in UI instead of the name.\n        contexts:\n          type: array\n          items:\n            type: string\n          description: >-\n            A comma separated list of the types of contexts the intent offered by the application can process. \n            where the first part of the context type is the namespace e.g.\"fdc3.contact, org.symphony.contact\"\n        customConfig:\n          type: object\n          description: >-\n            Custom configuration for the intent that may be required for a\n            particular desktop agent.\n    ApplicationV1:\n      description: >\n        (Deprecated v1 API version) Defines an application retrieved from an FDC3 App Directory, which can\n        then be launched.\n        Launching typically means running for a user on a desktop. \n        The details around 'launching' including who or what might do it, and how the launch action is initiated are\n        discussed elsewhere in the FDC3 App Directory spec.\n      required:\n        - appId\n        - name\n        - manifest\n        - manifestType\n      properties:\n        appId:\n          type: string\n          description: >\n            The unique application identifier located within a specific\n            application directory instance.\n        name:\n          type: string\n          description: >\n            The name of the application.\n            The name should be unique within an FDC3 App Directory instance. The\n            exception to the uniqueness constraint is that an App Directory can\n            hold definitions for multiple versions of the same app.\n            The same appName could occur in other directories. We are not\n            currently specifying app name conventions in the document.\n        manifest:\n          type: string\n          description: >\n            URI or full JSON of the application manifest providing all details related to launch\n            and use requirements as described by the vendor.\n            The format of this manifest is vendor specific, but can be identified by\n            the manifestType attribute.\n        manifestType:\n          type: string\n          description: >\n            The manifest type which relates to the format and structure of the manifest content.\n            The definition is based on the vendor specific format and definition outside of this specification.\n        version:\n          type: string\n          description: >-\n            Version of the application. This allows multiple app versions to be\n            defined using the same app name. This can be a triplet but can also\n            include things like 1.2.5 (BETA)\n        title:\n          type: string\n          description: >-\n            Optional title for the application, if missing use appName,\n            typically used in a launcher UI.\n        tooltip:\n          type: string\n          description: Optional tooltip description e.g. for a launcher\n        description:\n          type: string\n          description: >-\n            Description of the application. This will typically be a 1-2\n            paragraph style blurb about the application. Allow mark up language\n        images:\n          type: array\n          description: >-\n            Array of images to show the user when they are looking at app\n            description. Each image can have an optional description/tooltip\n          items:\n            $ref: '#/components/schemas/AppImageV1'\n        contactEmail:\n          type: string\n          format: email\n          description: Optional e-mail to receive queries about the application\n        supportEmail:\n          type: string\n          format: email\n          description: Optional e-mail to receive support requests for the application\n        publisher:\n          type: string\n          description: >-\n            The name of the company that owns the application. The publisher has\n            control over their namespace/app/signature.\n        icons:\n          type: array\n          description: >-\n            Holds Icons used for the application, a Launcher may be able to use\n            multiple Icon sizes or there may be a 'button' Icon\n          items:\n            $ref: '#/components/schemas/IconV1'\n        customConfig:\n          type: array\n          description: >-\n            An optional set of name value pairs that can be used to deliver\n            custom data from an App Directory to a launcher.\n          items:\n            $ref: '#/components/schemas/NameValuePair'\n        intents:\n          type: array\n          description: >\n            The list of intents implemented by the application as defined by\n            https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\n          items:\n            $ref: '#/components/schemas/IntentV1'\n    ApplicationSearchResponseV1:\n      properties:\n        applications:\n          type: array\n          description: |\n            List of applications\n          items:\n            $ref: '#/components/schemas/ApplicationV1'\n        message:\n          type: string\n          description: |\n            Response message providing status of query\n  examples:\n    FDC3WorkbenchAppDefinition:\n      value:\n        appId: fdc3-workbench\n        name: fdc3-workbench\n        title: FDC3 Workbench\n        description: Development and test tool for FDC3 desktop agents and apps\n        categories: [developer tools, training]\n        version: 1.0.0\n        tooltip: FDC3 Workbench\n        lang: en-US\n        icons:\n          - src: http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\n        screenshots:\n          - src: https://fdc3.finos.org/docs/assets/fdc3-logo.png\n            label: FDC3 logo\n        contactEmail: fdc3@finos.org\n        supportEmail: fdc3-maintainers@finos.org\n        moreInfo: https://fdc3.finos.org #update to point to implementations page when it exists\n        publisher: FDC3\n        type: web\n        details:\n          url: https://fdc3.finos.org/toolbox/fdc3-workbench/\n        hostManifests: {\n          Glue42: {\n            type: window,\n            icon: https://fdc3.finos.org/docs/assets/fdc3-logo.png,\n            details: {\n              height: 640,\n              width: 560,\n              left: 120,\n              top: 120,\n              mode: tab,\n              allowChannels: true,\n              loader: {\n                enabled: true,\n                hideOnLoad: true\n              }\n            },\n            customProperties: {\n              folder: FDC3 Toolbox\n            }\n          },\n          Finsemble: {\n            window: {\n              left: 120,\n              top: 120,\n              width: 800,\n              height: 750,\n              options: {\n                minWidth: 75\n              }\n            },\n            foreign: {\n              components: {\n                App Launcher: {\n                  launchableByUser: true\n                },\n                Toolbar: {\n                  iconURL: http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\n                },\n                Window Manager: {\n                  FSBLHeader: true,\n                  persistWindowState: true\n                }\n              }\n            },\n            interop: {\n              autoConnect: true\n            }\n          },\n          Web App Manifest: https://example.com/fdc3-workbench.json\n        }\n        localizedVersions: {\n          fr-FR: {\n            title: FDC3 Table de travail,\n            description: Outil de développement et de test pour les desktop agents et applications FDC3\n          }\n        }\n      summary: A sample app definition for the FDC3 Workbench application\n    MyAppDefinition:\n      value:\n        appId: my-application\n        name: my-application\n        title: My Application\n        description: An example application that uses FDC3 and fully describes itself in an AppD record.\n        categories: [market data, research, news]\n        version: 1.0.0\n        tooltip: My example application definition\n        lang: en-US\n        icons:\n          - src: http://example.domain.com/assets/my-app-icon.png\n            size: 256x256\n            type: image/png\n        screenshots:\n          - src: http://example.domain.com/assets/my-app-screenshot-1.png\n            label: The first screenshot of my example app\n            type: image/png\n            size: 800x600\n          - src: http://example.domain.com/assets/my-app-screenshot-2.png\n            label: The second screenshot of my example app\n            type: image/png\n            size: 800x600\n        contactEmail: fdc3@finos.org\n        supportEmail: fdc3-maintainers@finos.org\n        moreInfo: http://example.domain.com/\n        publisher: Example App, Inc.\n        type: web\n        details:\n          url: http://example.domain.com/app.html\n        hostManifests: {\n          Finsemble: {\n            window: {\n              left: 120,\n              top: 120,\n              width: 600,\n              height: 800,\n              options: {\n                minWidth: 75\n              }\n            },\n            foreign: {\n              components: {\n                App Launcher: {\n                  launchableByUser: true\n                },\n                Window Manager: {\n                  FSBLHeader: true,\n                  persistWindowState: true\n                }\n              }\n            },\n            interop: {\n              autoConnect: true\n            }\n          },\n          Glue42: {\n            type: window,\n            details: {\n              height: 800,\n              width: 600,\n              left: 120,\n              top: 120,\n              mode: tab,\n              allowChannels: true,\n              loader: {\n                enabled: true,\n                hideOnLoad: true\n              }\n            },\n            customProperties: {\n              folder: FDC3 Toolbox\n            }\n          },\n          Web App Manifest: http://example.domain.com/my-app.json\n        }\n        interop:\n          intents: \n            listensFor: \n              ViewChart: \n                displayName: View Chart\n                contexts: \n                  - fdc3.instrument\n              myApp.GetPrice: \n                displayName: Get Price\n                contexts: \n                  - fdc3.instrument\n                resultType: myApp.quote\n            raises: \n              ViewOrders: \n                - fdc3.instrument\n                - fdc3.organization\n              StartEmail: \n                - fdc3.email\n          userChannels: \n            broadcasts: \n              - fdc3.instrument\n              - fdc3.organization\n            listensFor: \n              - fdc3.instrument\n              - fdc3.organization\n          appChannels: \n            - name: myApp.quotes,\n              description: >-\n                Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\n              broadcasts: \n                - myApp.quote\n              listensFor: \n                - fdc3.instrument\n        localizedVersions: \n          fr-FR: \n            title: Mon application,\n            description: Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\n      summary: A sample app definition for an application that describes its use of interop.\n    AllAppsResponse:\n      value:\n        applications: # you can't $ref inside a $ref so example is repeated here for search response\n          - appId: my-application\n            name: my-application\n            title: My Application\n            description: An example application that uses FDC3 and fully describes itself in an AppD record.\n            categories: [market data, research, news]\n            version: 1.0.0\n            tooltip: My example application definition\n            lang: en-US\n            icons:\n              - src: http://example.domain.com/assets/my-app-icon.png\n                size: 256x256\n                type: image/png\n            screenshots:\n              - src: http://example.domain.com/assets/my-app-screenshot-1.png\n                label: The first screenshot of my example app\n                type: image/png\n                size: 800x600\n              - src: http://example.domain.com/assets/my-app-screenshot-2.png\n                label: The second screenshot of my example app\n                type: image/png\n                size: 800x600\n            contactEmail: fdc3@finos.org\n            supportEmail: fdc3-maintainers@finos.org\n            moreInfo: http://example.domain.com/\n            publisher: Example App, Inc.\n            type: web\n            details:\n              url: http://example.domain.com/app.html\n            hostManifests: {\n              Finsemble: {\n                window: {\n                  left: 120,\n                  top: 120,\n                  width: 600,\n                  height: 800,\n                  options: {\n                    minWidth: 75\n                  }\n                },\n                foreign: {\n                  components: {\n                    App Launcher: {\n                      launchableByUser: true\n                    },\n                    Window Manager: {\n                      FSBLHeader: true,\n                      persistWindowState: true\n                    }\n                  }\n                },\n                interop: {\n                  autoConnect: true\n                }\n              },\n              Glue42: {\n                type: window,\n                details: {\n                  height: 800,\n                  width: 600,\n                  left: 120,\n                  top: 120,\n                  mode: tab,\n                  allowChannels: true,\n                  loader: {\n                    enabled: true,\n                    hideOnLoad: true\n                  }\n                },\n                customProperties: {\n                  folder: FDC3 Toolbox\n                }\n              },\n              Web App Manifest: http://example.domain.com/my-app.json\n            }\n            interop:\n              intents: \n                listensFor: \n                  ViewChart: \n                    displayName: View Chart\n                    contexts: \n                      - fdc3.instrument\n                  myApp.GetPrice: \n                    displayName: Get Price\n                    contexts: \n                      - fdc3.instrument\n                    resultType: myApp.quote\n                raises: \n                  ViewOrders: \n                    - fdc3.instrument\n                    - fdc3.organization\n                  StartEmail: \n                    - fdc3.email\n              userChannels: \n                broadcasts: \n                  - fdc3.instrument\n                  - fdc3.organization\n                listensFor: \n                  - fdc3.instrument\n                  - fdc3.organization\n              appChannels: \n                - name: myApp.quotes,\n                  description: >-\n                    Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\n                  broadcasts:\n                    - myApp.quote\n                  listensFor: \n                    - fdc3.instrument\n            localizedVersions: \n              fr-FR:\n                title: Mon application,\n                description: Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\n          - appId: fdc3-workbench\n            name: fdc3-workbench\n            title: FDC3 Workbench\n            description: Development and test tool for FDC3 desktop agents and apps\n            categories: [developer tools, training]\n            version: 1.0.0\n            tooltip: FDC3 Workbench\n            lang: en-US\n            icons:\n              - src: http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\n            screenshots:\n              - src: https://fdc3.finos.org/docs/assets/fdc3-logo.png\n                label: FDC3 logo\n            contactEmail: fdc3@finos.org\n            supportEmail: fdc3-maintainers@finos.org\n            publisher: FDC3,\n            type: web\n            details:\n              url: https://fdc3.finos.org/toolbox/fdc3-workbench/\n            hostManifests: {\n              Glue42: {\n                type: window,\n                icon: https://fdc3.finos.org/docs/assets/fdc3-logo.png,\n                details: {\n                  height: 640,\n                  width: 560,\n                  left: 120,\n                  top: 120,\n                  mode: tab,\n                  allowChannels: true,\n                  loader: {\n                    enabled: true,\n                    hideOnLoad: true\n                  }\n                },\n                customProperties: {\n                  folder: FDC3 Toolbox\n                }\n              },\n              Finsemble: {\n                window: {\n                  left: 120,\n                  top: 120,\n                  width: 800,\n                  height: 750,\n                  options: {\n                    minWidth: 75\n                  }\n                },\n                foreign: {\n                  components: {\n                    App Launcher: {\n                      launchableByUser: true\n                    },\n                    Toolbar: {\n                      iconURL: http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\n                    },\n                    Window Manager: {\n                      FSBLHeader: true,\n                      persistWindowState: true\n                    }\n                  }\n                },\n                interop: {\n                  autoConnect: true\n                }\n              },\n              Web App Manifest: https://example.com/fdc3-workbench.json\n            }\n            localizedVersions: {\n              fr-FR: {\n                title: FDC3 Table de travail,\n                description: Outil de développement et de test pour les desktop agents et applications FDC3\n              }\n            }\n        message: OK\n      summary: A sample 'all applications' listing response\n"
  },
  {
    "path": "website/static/schemas/2.0/chart.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/chart.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chart\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.chart\" },\n    \"instruments\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"instrument.schema.json#\"\n      }\n    },\n    \"range\": {\n      \"$ref\": \"timerange.schema.json#\"\n    },\n    \"style\": {\n      \"type\": \"string\",\n      \"enum\": [\t\"line\", \"bar\", \"stacked-bar\", \"mountain\", \"candle\", \"pie\", \"scatter\", \"histogram\", \"heatmap\", \"custom\"]\n    },\n    \"otherConfig\": {\n      \"type\": \"object\"\n    }\n  },\n  \"required\": [\"instruments\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/chatInitSettings.schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/2.0/chatInitSettings.schema.json\",\n    \"type\": \"object\",\n    \"title\": \"ChatInitSettings\",\n    \"properties\": {\n        \"type\": {\n            \"const\": \"fdc3.chat.initSettings\"\n        },\n        \"chatName\": {\n            \"type\": \"string\"\n        },\n        \"members\": {\n            \"$ref\": \"contactList.schema.json#\"\n        },\n        \"initMessage\": {\n            \"type\": \"string\"\n        },\n        \"options\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"groupRecipients\": {\"type\": \"boolean\"},\n              \"isPublic\": {\"type\": \"boolean\"},\n              \"allowHistoryBrowsing\":  {\"type\": \"boolean\"},\n              \"allowMessageCopy\":  {\"type\": \"boolean\"},\n              \"allowAddUser\":  {\"type\": \"boolean\"}\n            }\n        }\n    },\n    \"required\": [\n        \"type\"\n    ]\n}"
  },
  {
    "path": "website/static/schemas/2.0/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contact\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"email\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.contactList\" },\n    \"contacts\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"contact.schema.json#\" }\n    }\n  },\n  \"required\": [\"contacts\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"properties\": {\n    \"type\": { \"type\": \"string\" },\n    \"name\": { \"type\": \"string\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"additionalProperties\": { \"type\": \"string\" }\n    }\n  },\n  \"required\": [\"type\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.country\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"COUNTRY_ISOALPHA2\": { \"type\": \"string\" },\n        \"COUNTRY_ISOALPHA3\": { \"type\": \"string\" },\n        \"ISOALPHA2\": { \"type\": \"string\" },\n        \"ISOALPHA3\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/currency.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/currency.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Currency\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.currency\" },\n    \"name\": { \"type\": \"string\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"CURRENCY_ISOCODE\": { \"type\": \"string\", \"pattern\": \"^[A-Z]{3}$\"}\n      }\n    }\n    \n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/email.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/email.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Email\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.email\" },\n    \"recipients\": {\n      \"oneOf\": [\n        { \"$ref\": \"contact.schema.json#\" },\n        { \"$ref\": \"contactList.schema.json#\" }\n      ]\n    },\n    \"subject\": { \"type\": \"string\" },\n    \"textBody\": { \"type\": \"string\" }\n  },\n  \"required\": [\"recipients\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrument\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"BBG\": { \"type\": \"string\" },\n        \"CUSIP\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" },\n        \"FIGI\": { \"type\": \"string\" },\n        \"ISIN\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"RIC\": { \"type\": \"string\" },\n        \"SEDOL\": { \"type\": \"string\" },\n        \"ticker\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.instrumentList\" },\n    \"instruments\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"instrument.schema.json#\" }\n    }\n  },\n  \"required\": [\"instruments\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/nothing.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/nothing.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Nothing\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.nothing\" }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.organization\" },\n    \"id\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"LEI\": { \"type\": \"string\" },\n        \"PERMID\": { \"type\": \"string\" },\n        \"FDS_ID\": { \"type\": \"string\" }\n      }\n    }\n  },\n  \"required\": [\"id\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.portfolio\" },\n    \"positions\": {\n      \"type\": \"array\",\n      \"items\": { \"$ref\": \"position.schema.json#\" }\n    }\n  },\n  \"required\": [\"positions\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.position\" },\n    \"instrument\": { \"$ref\": \"instrument.schema.json#\" },\n    \"holding\": { \"type\": \"number\" }\n  },\n  \"required\": [\"instrument\", \"holding\"]\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.0/timerange.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/timerange.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TimeRange\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"anyOf\": [\n    {\n      \"required\": [\"startTime\", \"endTime\"]\n    },\n    {\n      \"required\": [\"startTime\"]\n    },\n    {\n      \"required\": [\"endTime\"]\n    }\n  ],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.timerange\" },\n    \"startTime\": { \"type\": \"string\", \"format\": \"date-time\" },\n    \"endTime\":  {\"type\": \"string\", \"format\": \"date-time\" }\n  },\n  \"required\": []\n}\n"
  },
  {
    "path": "website/static/schemas/2.0/valuation.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.0/valuation.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Valuation\",\n  \"allOf\": [{ \"$ref\": \"context.schema.json#\" }],\n  \"properties\": {\n    \"type\": { \"const\": \"fdc3.valuation\" },\n    \"value\": { \"type\": \"number\" },\n    \"price\": { \"type\": \"number\"},\n    \"CURRENCY_ISOCODE\": { \"type\": \"string\", \"pattern\": \"^[A-Z]{3}$\" },\n    \"valuationTime\": {\"type\": \"string\", \"format\": \"date-time\" },\n    \"expiryTime\": {\"type\": \"string\", \"format\": \"date-time\" }\n  },\n  \"required\": [\"value\", \"CURRENCY_ISOCODE\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/api/README.md",
    "content": "# Intro\n\nQuicktype, the chosen generation tool currently has some limitations that prevent fully automatic schema generation from the existing TS types. For example it can not handle interfaces that contain methods in their definition. It also fails to generate schemas even if a type contains unused references to other types or interfaces that contain async functions (Promise return types). Therefore, in order to generate the `api\\schemas\\api.schema.json` some manual intervention was needed.\n\nOnce these limitations are not an issue the `api\\schemas\\t2sQuicktypeUtil.js` script should be moved to the root level of the project and a new npm script `\"api-schema-gen\": \"node t2sQuicktypeUtil.js src/api schemas/api/api.schema.json\"` should be added.\n\n`api\\schemas\\api.schema.json` - partially auto-generated schema from the existing `src\\api` types.\n`api\\schemas\\baseImplementationMetadata.schema.json` - Used by bridging types that leave out the metadata of the calling application as it does not apply to bridging.\n`api\\schemas\\intentResolution.schema.json` - At the moment it is not possible to auto-generate this due to limitations in the generation tool (quicktype)\n`api\\schemas\\t2sQuicktypeUtil.js` - Script used to run the generation of the schema from the types. Should be moved to the root level of the repo once fully-automated generation can be achieved.\n"
  },
  {
    "path": "website/static/schemas/2.1/api/api.schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/2.1/api/api.schema.json\",\n    \"title\": \"FDC3 Desktop Agent API Schema\",\n    \"definitions\": {\n        \"AppIdentifier\": {\n            \"description\": \"Identifies an application, or instance of an application, and is used to target FDC3 API calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application instances.\\n\\nWill always include at least an `appId` field, which uniquely identifies a specific app.\\n\\nIf the `instanceId` field is set then the `AppMetadata` object represents a specific instance of the application that may be addressed using that Id.\",\n            \"title\": \"AppIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"Icon\": {\n            \"description\": \"SPDX-License-Identifier: Apache-2.0\\nCopyright FINOS FDC3 contributors - see NOTICE file\",\n            \"title\": \"Icon\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The icon url\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The icon dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Icon media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"Image\": {\n            \"description\": \"SPDX-License-Identifier: Apache-2.0\\nCopyright FINOS FDC3 contributors - see NOTICE file\",\n            \"title\": \"Image\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The image url.\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The image dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"label\": {\n                    \"description\": \"Caption for the image.\",\n                    \"type\": \"string\",\n                    \"title\": \"label\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"AppMetadata\": {\n            \"description\": \"Extends an `AppIdentifier`, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\\n\\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\\n\\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\",\n            \"title\": \"AppMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The 'friendly' app name. \\nThis field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier` wth `appId` set. \\nNote that for display purposes the `title` field should be used, if set, in preference to this field.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"version\": {\n                    \"description\": \"The Version of the application.\",\n                    \"type\": \"string\",\n                    \"title\": \"version\"\n                },\n                \"instanceMetadata\": {\n                    \"description\": \"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.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": {},\n                    \"title\": \"instanceMetadata\"\n                },\n                \"title\": {\n                    \"description\": \"A more user-friendly application title that can be used to render UI elements\",\n                    \"type\": \"string\",\n                    \"title\": \"title\"\n                },\n                \"tooltip\": {\n                    \"description\": \"A tooltip for the application that can be used to render UI elements\",\n                    \"type\": \"string\",\n                    \"title\": \"tooltip\"\n                },\n                \"description\": {\n                    \"description\": \"A longer, multi-paragraph description for the application that could include markup\",\n                    \"type\": \"string\",\n                    \"title\": \"description\"\n                },\n                \"icons\": {\n                    \"description\": \"A list of icon URLs for the application that can be used to render UI elements\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Icon\"\n                    },\n                    \"title\": \"icons\"\n                },\n                \"screenshots\": {\n                    \"description\": \"Images representing the app in common usage scenarios that can be used to render UI elements\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Image\"\n                    },\n                    \"title\": \"screenshots\"\n                },\n                \"resultType\": {\n                    \"description\": \"The type of output 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 (e.g. \\\"channel<fdc3.instrument>\\\").\",\n                    \"type\": [\n                        \"null\",\n                        \"string\"\n                    ],\n                    \"title\": \"resultType\"\n                },\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"IntentMetadata\": {\n            \"description\": \"Intent descriptor\",\n            \"title\": \"IntentMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The unique name of the intent that can be invoked by the raiseIntent call\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"displayName\": {\n                    \"description\": \"Display name for the intent.\",\n                    \"type\": \"string\",\n                    \"title\": \"displayName\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"displayName\",\n                \"name\"\n            ]\n        },\n        \"AppIntent\": {\n            \"description\": \"An interface that relates an intent to apps\",\n            \"title\": \"AppIntent\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"intent\": {\n                    \"$ref\": \"#/definitions/IntentMetadata\",\n                    \"description\": \"Details of the intent whose relationship to resolving applications is being described.\",\n                    \"title\": \"intent\"\n                },\n                \"apps\": {\n                    \"description\": \"Details of applications that can resolve the intent.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/AppMetadata\"\n                    },\n                    \"title\": \"apps\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"apps\",\n                \"intent\"\n            ]\n        },\n        \"DisplayMetadata\": {\n            \"description\": \"A system channel will be global enough to have a presence across many apps. This gives us some hints\\nto render them in a standard way. It is assumed it may have other properties too, but if it has these,\\nthis is their meaning.\",\n            \"title\": \"DisplayMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"A user-readable name for this channel, e.g: `\\\"Red\\\"`\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"color\": {\n                    \"description\": \"The color that should be associated within this channel when displaying this channel in a UI, e.g: `0xFF0000`.\",\n                    \"type\": \"string\",\n                    \"title\": \"color\"\n                },\n                \"glyph\": {\n                    \"description\": \"A URL of an image that can be used to display this channel\",\n                    \"type\": \"string\",\n                    \"title\": \"glyph\"\n                }\n            },\n            \"additionalProperties\": false\n        },\n        \"Channel\": {\n            \"description\": \"Represents a context channel that applications can use to send and receive\\ncontext data.\\n\\nPlease note that There are differences in behavior when you interact with a\\nUser channel via the `DesktopAgent` interface and the `Channel` interface.\\nSpecifically, when 'joining' a User channel or adding a context listener\\nwhen already joined to a channel via the `DesktopAgent` interface, existing\\ncontext (matching the type of the context listener) on the channel is\\nreceived by the context listener immediately. Whereas, when a context\\nlistener is added via the Channel interface, context is not received\\nautomatically, but may be retrieved manually via the `getCurrentContext()`\\nfunction.\",\n            \"title\": \"Channel\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"id\": {\n                    \"description\": \"Constant that uniquely identifies this channel.\",\n                    \"type\": \"string\",\n                    \"title\": \"id\"\n                },\n                \"type\": {\n                    \"description\": \"Uniquely defines each channel type.\\nCan be \\\"user\\\", \\\"app\\\" or \\\"private\\\".\",\n                    \"enum\": [\n                        \"app\",\n                        \"private\",\n                        \"user\"\n                    ],\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"displayMetadata\": {\n                    \"description\": \"Channels may be visualized and selectable by users. DisplayMetadata may be used to provide hints on how to see them.\\nFor App channels, displayMetadata would typically not be present.\",\n                    \"$ref\": \"#/definitions/DisplayMetadata\",\n                    \"title\": \"displayMetadata\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"id\",\n                \"type\"\n            ]\n        },\n        \"ContextMetadata\": {\n            \"description\": \"Metadata relating to a context or intent and context received through the\\n`addContextListener` and `addIntentListener` functions.\",\n            \"title\": \"ContextMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that sent the context and/or intent.\",\n                    \"title\": \"source\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"source\"\n            ]\n        },\n        \"DesktopAgentIdentifier\": {\n            \"description\": \"Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\\nwhere a request needs to be directed to a Desktop Agent rather than a specific app, or a\\nresponse message is returned by the Desktop Agent (or more specifically its resolver)\\nrather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\\napp details are available or are appropriate.\",\n            \"title\": \"DesktopAgentIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"desktopAgent\": {\n                    \"description\": \"Used in Desktop Agent Bridging to attribute or target a message to a\\nparticular Desktop Agent.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"desktopAgent\"\n            ]\n        },\n        \"OpenError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`).\",\n            \"title\": \"OpenError\",\n            \"enum\": [\n                \"AppNotFound\",\n                \"AppTimeout\",\n                \"DesktopAgentNotFound\",\n                \"ErrorOnLaunch\",\n                \"MalformedContext\",\n                \"ResolverUnavailable\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResolveError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\",\n            \"title\": \"ResolveError\",\n            \"enum\": [\n                \"DesktopAgentNotFound\",\n                \"IntentDeliveryFailed\",\n                \"MalformedContext\",\n                \"NoAppsFound\",\n                \"ResolverTimeout\",\n                \"ResolverUnavailable\",\n                \"TargetAppUnavailable\",\n                \"TargetInstanceUnavailable\",\n                \"UserCancelledResolution\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResultError\": {\n            \"title\": \"ResultError\",\n            \"enum\": [\n                \"IntentHandlerRejected\",\n                \"NoResultReturned\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ChannelError\": {\n            \"title\": \"ChannelError\",\n            \"enum\": [\n                \"AccessDenied\",\n                \"CreationFailed\",\n                \"MalformedContext\",\n                \"NoChannelFound\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BridgingError\": {\n            \"title\": \"BridgingError\",\n            \"enum\": [\n                \"AgentDisconnected\",\n                \"NotConnectedToBridge\",\n                \"ResponseToBridgeTimedOut\",\n                \"MalformedMessage\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ImplementationMetadata\": {\n            \"description\": \"Metadata relating to the FDC3 Desktop Agent implementation and its provider.\",\n            \"title\": \"ImplementationMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"fdc3Version\": {\n                    \"description\": \"The version number of the FDC3 specification that the implementation provides.\\nThe string must be a numeric semver version, e.g. 1.2 or 1.2.1.\",\n                    \"type\": \"string\",\n                    \"title\": \"fdc3Version\"\n                },\n                \"provider\": {\n                    \"description\": \"The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42, OpenFin etc.).\",\n                    \"type\": \"string\",\n                    \"title\": \"provider\"\n                },\n                \"providerVersion\": {\n                    \"description\": \"The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\",\n                    \"type\": \"string\",\n                    \"title\": \"providerVersion\"\n                },\n                \"optionalFeatures\": {\n                    \"description\": \"Metadata indicating whether the Desktop Agent implements optional features of\\nthe Desktop Agent API.\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"OriginatingAppMetadata\": {\n                            \"description\": \"Used to indicate whether the exposure of 'originating app metadata' for\\ncontext and intent messages is supported by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"OriginatingAppMetadata\"\n                        },\n                        \"UserChannelMembershipAPIs\": {\n                            \"description\": \"Used to indicate whether the optional `fdc3.joinUserChannel`,\\n`fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\\nthe Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"UserChannelMembershipAPIs\"\n                        },\n                        \"DesktopAgentBridging\": {\n                            \"description\": \"Used to indicate whether the experimental Desktop Agent Bridging\\nfeature is implemented by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"DesktopAgentBridging\"\n                        }\n                    },\n                    \"additionalProperties\": false,\n                    \"required\": [\n                        \"DesktopAgentBridging\",\n                        \"OriginatingAppMetadata\",\n                        \"UserChannelMembershipAPIs\"\n                    ],\n                    \"title\": \"optionalFeatures\"\n                },\n                \"appMetadata\": {\n                    \"$ref\": \"#/definitions/AppMetadata\",\n                    \"description\": \"The calling application instance's own metadata, according to the Desktop Agent (MUST include at least the `appId` and `instanceId`).\",\n                    \"title\": \"appMetadata\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"appMetadata\",\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\"\n            ]\n        },\n        \"IntentResolution\": {\n            \"description\": \"IntentResolution provides a standard format for data returned upon resolving an intent.\\n\\n```javascript\\n//resolve a \\\"Chain\\\" type intent\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\n\\n//resolve a \\\"Client-Service\\\" type intent with a data response or a Channel\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\ntry {\\n\\t   const result = await resolution.getResult();\\n    if (result && result.broadcast) {\\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\\n    } else if (result){\\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\\n    } else {\\n        console.error(`${resolution.source} didn't return data`\\n    }\\n} catch(error) {\\n    console.error(`${resolution.source} returned an error: ${error}`);\\n}\\n\\n// Use metadata about the resolving app instance to target a further intent\\nawait agent.raiseIntent(\\\"intentName\\\", context, resolution.source);\\n```\",\n            \"title\": \"IntentResolution\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that was selected (or started) to resolve the intent.\\n`source.instanceId` MUST be set, indicating the specific app instance that\\nreceived the intent.\",\n                    \"title\": \"source\"\n                },\n                \"intent\": {\n                    \"description\": \"The intent that was raised. May be used to determine which intent the user\\nchose in response to `fdc3.raiseIntentForContext()`.\",\n                    \"type\": \"string\",\n                    \"title\": \"intent\"\n                },\n                \"version\": {\n                    \"description\": \"The version number of the Intents schema being used.\",\n                    \"type\": \"string\",\n                    \"title\": \"version\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"intent\",\n                \"source\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/api/baseImplementationMetadata.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/api/baseImplementationMetadata.schema.json\",\n  \"title\": \"BaseImplementationMetadata\",\n  \"description\": \"Metadata relating to the FDC3 Desktop Agent implementation and its provider.\",\n  \"type\": \"object\",\n  \"properties\": {\n      \"fdc3Version\": {\n          \"description\": \"The version number of the FDC3 specification that the implementation provides.\\nThe string must be a numeric semver version, e.g. 1.2 or 1.2.1.\",\n          \"type\": \"string\",\n          \"title\": \"fdc3Version\"\n      },\n      \"provider\": {\n          \"description\": \"The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42, OpenFin etc.).\",\n          \"type\": \"string\",\n          \"title\": \"provider\"\n      },\n      \"providerVersion\": {\n          \"description\": \"The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\",\n          \"type\": \"string\",\n          \"title\": \"providerVersion\"\n      },\n      \"optionalFeatures\": {\n          \"description\": \"Metadata indicating whether the Desktop Agent implements optional features of\\nthe Desktop Agent API.\",\n          \"type\": \"object\",\n          \"properties\": {\n              \"OriginatingAppMetadata\": {\n                  \"description\": \"Used to indicate whether the exposure of 'originating app metadata' for\\ncontext and intent messages is supported by the Desktop Agent.\",\n                  \"type\": \"boolean\",\n                  \"title\": \"OriginatingAppMetadata\"\n              },\n              \"UserChannelMembershipAPIs\": {\n                  \"description\": \"Used to indicate whether the optional `fdc3.joinUserChannel`,\\n`fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\\nthe Desktop Agent.\",\n                  \"type\": \"boolean\",\n                  \"title\": \"UserChannelMembershipAPIs\"\n              },\n              \"DesktopAgentBridging\": {\n                  \"description\": \"Used to indicate whether the experimental Desktop Agent Bridging\\nfeature is implemented by the Desktop Agent.\",\n                  \"type\": \"boolean\",\n                  \"title\": \"DesktopAgentBridging\"\n              }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n              \"DesktopAgentBridging\",\n              \"OriginatingAppMetadata\",\n              \"UserChannelMembershipAPIs\"\n          ],\n          \"title\": \"optionalFeatures\"\n      }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\n      \"fdc3Version\",\n      \"optionalFeatures\",\n      \"provider\"\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/api/t2sQuicktypeUtil.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n \n/** Utility for preparing arguments to quicktype, which workaround a specific\n * quicktype bug in command line argument handling (where a directory is used\n * as input the source language argument is ignored which causes our schemas\n * to be interpreted as JSON input, rather than JSONSchema).\n * Bug issue:\n *  */\n\nconst path = require('path');\nconst fs = require('fs');\nconst exec = require('child_process').exec;\n\nconst args = process.argv.slice(2);\nconst outputPath = args.pop();\nconst inputs = args;\n\nconsole.log('Inputs: ' + inputs.join(' | '));\nconsole.log('Output path argument: ' + outputPath);\n\nlet source = '';\n\nlet dirIndex = 0;\n\nconst excludedTypes = [\n  'DesktopAgent.ts',\n  'Listener.ts',\n  'Methods.ts',\n  'PrivateChannel.ts',\n  'Types.ts',\n  'RecommendedChannels.ts',\n];\n\nlet sources = '';\n\nwhile (dirIndex < inputs.length) {\n  if (inputs[dirIndex].endsWith('.ts')) {\n    sources += `--src ${path.join(inputs[dirIndex])} `;\n  } else {\n    fs.readdirSync(inputs[dirIndex], { withFileTypes: true }).forEach(file => {\n      if (file.isDirectory()) {\n        inputs.push(path.join(inputs[dirIndex], file.name));\n      } else {\n        if (!excludedTypes.includes(file.name)) {\n          sources += `--src ${path.join(inputs[dirIndex], file.name)} `;\n        }\n      }\n    });\n  }\n  dirIndex++;\n}\n\n// Normalise path to local quicktype executable.\nconst quicktypeExec = ['.', 'node_modules', '.bin', 'quicktype'].join(path.sep);\n\nconst command = `${quicktypeExec} -l schema -o ${outputPath} ${sources}`;\nconsole.log('command to run: ' + command);\n\nexec(command, function(error, stdout, stderr) {\n  if (stdout) {\n    console.log(stdout);\n  }\n  if (stderr) {\n    console.log(stderr);\n  }\n});\n"
  },
  {
    "path": "website/static/schemas/2.1/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/next/appd.schema.json'></redoc>\n<script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"></script>"
  },
  {
    "path": "website/static/schemas/2.1/appd.schema.json",
    "content": "{\n\t\"openapi\": \"3.0.0\",\n\t\"info\": {\n\t  \"title\": \"FDC3 Application Directory\",\n\t  \"version\": \"2.1\",\n\t  \"description\": \"Application Directory specification providing both interface definition and objects necessary to construct an application directory service.\",\n\t  \"x-logo\": {\n\t\t\"url\": \"/img/fdc3-logo-2019-color.png\",\n\t\t\"altText\": \"FDC3 logo\"\n\t  }\n\t},\n\t\"security\": [\n\t  {\n\t\t\"bearerAuth\": []\n\t  }\n\t],\n\t\"paths\": {\n\t  \"/v2/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"MyAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/MyAppDefinition\"\n\t\t\t\t\t},\n\t\t\t\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/FDC3WorkbenchAppDefinition\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v2/apps\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve all application definitions\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/AllApplicationsResponse\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"AllAppsResponse\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/AllAppsResponse\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps\": {\n\t\t\"post\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Create a new application definition\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ],\n\t\t  \"requestBody\": {\n\t\t\t\"content\": {\n\t\t\t  \"application/json\": {\n\t\t\t\t\"schema\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"required\": true\n\t\t  }\n\t\t}\n\t  },\n\t  \"/v1/apps/search\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter values should self describe search format and type (e.g. Regex)\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"version\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"title\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"tooltip\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"description\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"name of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_displayName\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"displayName of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_context\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"search contexts list\"\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  }\n\t},\n\t\"servers\": [\n\t  {\n\t\t\"url\": \"/appd\"\n\t  }\n\t],\n\t\"components\": {\n\t  \"securitySchemes\": {\n\t\t\"bearerAuth\": {\n\t\t  \"type\": \"http\",\n\t\t  \"scheme\": \"bearer\",\n\t\t  \"bearerFormat\": \"JWT\"\n\t\t}\n\t  },\n\t  \"schemas\": {\n\t\t\"ErrorDTO\": {\n\t\t  \"type\": \"object\",\n\t\t  \"properties\": {\n\t\t\t\"code\": {\n\t\t\t  \"type\": \"integer\",\n\t\t\t  \"format\": \"int32\"\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"BaseApplication\": {\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Title for the application, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Type\"\n\t\t\t},\n\t\t\t\"details\": {\n\t\t\t  \"$ref\": \"#/components/schemas/LaunchDetails\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Deprecated in favour of using `appId` to identify apps and `title` for their display names. The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"lang\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"pattern\": \"^[a-z]{2}(-[a-zA-Z0-9]{2,8}){0,1}$\",\n\t\t\t  \"description\": \"A language tag that specifies the primary language of both the application and its AppD entry, as defined by IETF RFC 5646.\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. \"\n\t\t\t},\n\t\t\t\"categories\": {\n\t\t\t  \"description\": \"An array of string categories that describe the application. These are meant as a hint to catalogs or stores listing FDC3-enabled apps and it is expected that these will make a best effort to find appropriate categories (or category) under which to list the app. AppD record authors are encouraged to use lower-case and, where possible, to select categories from the following list:\\n\\n- allocations\\n- analytics\\n- charts\\n- chat\\n- communication\\n- compliance\\n- crm\\n- developer tools\\n- events\\n- execution management\\n- file sharing\\n- market data\\n- news\\n- networking\\n- office apps\\n- order management\\n- other\\n- portfolio management\\n- presentation\\n- pricing\\n- productivity\\n- research\\n- risk\\n- screen sharing\\n- security\\n- spreadsheet\\n- trade cost analysis\\n- trading system\\n- training\\n- travel\\n- video\\n- visualization\\n- weather\\n\",\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Icon\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"screenshots\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Screenshot\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"moreInfo\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Optional URL that provides more information about the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher. Deprecated due to a lack of a standard means of retrieval via the Desktop Agent API. To be replaced in a future version with an `applicationConfig` element and standard API to retrieve it. See issue  [#1006](https://github.com/finos/FDC3/issues/1006) for details.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"$ref\": \"#/components/schemas/HostManifests\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Interop\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Application\": {\n\t\t  \"description\": \"Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"title\",\n\t\t\t\"type\",\n\t\t\t\"details\"\n\t\t  ],\n\t\t  \"allOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/LocalizedVersions\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"AllApplicationsResponse\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"NameValuePair\": {\n\t\t  \"description\": \"Simple name value pair\",\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"name\"\n\t\t\t},\n\t\t\t\"value\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"value\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Icon\": {\n\t\t  \"description\": \"Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Icon dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t    \"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Screenshot\": {\n\t\t  \"description\": \"Images representing the app in common usage scenarios\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional caption for the image\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t\t\"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Type\": {\n\t\t  \"type\": \"string\",\n\t\t  \"description\": \"The technology type that is used to launch and run the application. Each application type implies a particular set of launch `details`.\\nThe supported types include:\\n\\n- `web`: Web applications launched via a URL\\n- `native`: Native applications pre-installed on a device and launch via a filesystem path\\n- `citrix`: Apps virtualized via Citrix\\n- `onlineNative`: Native apps that have an online launcher, e.g. online ClickOnce app deployments.\\n- `other`: Used to represent apps that do not conform to or cannot be launched via the other types, and are likely to be defined solely by a hostManifest.\\n\\nFDC3 Desktop Agents MUST support at least the `web` application type and MAY support any or all of the other types.\",\n\t\t  \"enum\": [\n\t\t\t\"web\",\n\t\t\t\"native\",\n\t\t\t\"citrix\",\n\t\t\t\"onlineNative\",\n\t\t\t\"other\"\n\t\t  ]\n\t\t},\n\t\t\"LaunchDetails\": {\n\t\t  \"description\": \"The type specific launch details of the application. These details are intended to be vendor-agnostic and MAY be duplicated or overridden by details provided in the hostManifests object for a specific host.\",\n\t\t  \"anyOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/WebAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/NativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/CitrixAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OnlineNativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OtherAppDetails\"\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"WebAppDetails\": {\n\t\t  \"description\": \"Properties used to launch apps with `type: web`.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application start URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"NativeAppDetails\": {\n\t\t  \"description\": \"Properties used to launch apps with `type: native` that are already installed on the device.\",\n\t\t  \"required\": [\n\t\t\t\"path\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"path\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The path on disk from which the application is launched.\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"CitrixAppDetails\": {\n\t\t  \"description\": \"Properties used to launch apps virtualized apps with `type: citrix`.\",\n\t\t  \"required\": [\n\t\t\t\"alias\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"alias\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The Citrix alias / name of the virtual app (passed to the Citrix SelfService qlaunch parameter).\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OnlineNativeAppDetails\": {\n\t\t  \"description\": \"Properties used to launch a native apps with `type: onlineNative` that have an online launcher, e.g. online ClickOnce app deployments.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OtherAppDetails\": {\n\t\t  \"description\": \"Apps with `type: other` are defined by a hostManifest and do not require other details.\",\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"HostManifests\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"A mapping from host name to a host-specific application manifest object or URI from which that manifest can be retrieved. The manifest should provide details required to launch and use the application within the specified host. The manifest _MAY_ duplicate or  override information provided in the `details` field.\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Host name\",\n\t\t\t\"oneOf\": [\n\t\t\t  {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"format\": \"uri\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"$ref\": \"#/components/schemas/HostManifest\"\n\t\t\t  }\n\t\t\t]\n\t\t  }\n\t\t},\n\t\t\"HostManifest\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Object containing all host specific properties.\"\n\t\t},\n\t\t\"LocalizedVersions\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Provides localized alternatives to any field of the AppD record, which may also refer to an alternative version of the application that is also localized (e.g. by providing an alternative URL).  The keys to this object should be language tags as defined by IETF RFC 5646, e.g. en, en-GB or fr-FR.\\n\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Language tag\",\n\t\t\t\"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t  }\n\t\t},\n\t\t\"Intent\": {\n\t\t  \"description\": \"Definition of an intent that an app listens for\",\n\t\t  \"required\": [\n\t\t\t\"contexts\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional display name for the intent. Deprecated in favour of the intent name, which is common amongst all apps that support it, where the display name may vary as it is defined in the app's AppD record.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"resultType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional type for output returned by the application, if any, when resolving this intent. May indicate a context type by type name (e.g. \\\"fdc3.instrument\\\"), a channel (e.g. \\\"channel\\\") or a combination that indicates a channel that returns a particular context type (e.g. \\\"channel<fdc3.instrument>\\\").\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Interop\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Metadata that describes how the application uses FDC3 APIs. This metadata serves multiple purposes:\\n\\n- It supports intent resolution by a desktop agent, by declaring what intents an app listens for.\\n- It may be used, for example in an app catalog UI, to find apps that 'interoperate with' other apps. \\n- It provides a standard location to document how the app interacts with user channels, app channels, and intents, for use by other app developers and desktop assemblers.\",\n\t\t  \"properties\": {\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the app's interactions with intents.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intents names that an app listens for via `fdc3.addIntentListener()` to their configuration. \\n\\nUsed to support intent resolution by desktop agents. Replaces the `intents` element used in appD records prior to FDC3 2.0.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Intent\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intent names that an app raises (via `fdc3.raiseIntent`) to an array of context type names that it may be raised with.\\n\\nUse the intent name \\\"any\\\" to represent use of the `fdc3.raiseIntentForContext` and `fdc3.findIntentForContext` functions, which allow the user to select from intents available for a specified context type.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the intent may be raised with.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"userChannels\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the application's use of context types on User Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"broadcasts\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that are broadcast by the application.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that the application listens for.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"appChannels\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Describes the application's use of App Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": [\n\t\t\t\t  \"id\"\n\t\t\t\t],\n\t\t\t\t\"properties\": {\n\t\t\t\t  \"id\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The id of the App Channel. N.b. in FDC3 2.0 this field was incorrectly called `name`.\"\n\t\t\t\t  },\n\t\t\t\t  \"description\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"A description of how the channel is used.\"\n\t\t\t\t  },\n\t\t\t\t  \"broadcasts\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that are broadcast by the application on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"listensFor\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the application listens for on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"AppImageV1\": {\n\t\t  \"description\": \"App Image holder\",\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IconV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"icon\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IntentV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) An intent definition as defined by spec https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t  \"required\": [\n\t\t\t\"name\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the intent to 'launch'. In this case the name of an Intent supported by an application.\"\n\t\t\t},\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional display name for the intent that may be used in UI instead of the name.\"\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"name\",\n\t\t\t\"manifest\",\n\t\t\t\"manifestType\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t\"manifest\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"URI or full JSON of the application manifest providing all details related to launch and use requirements as described by the vendor. The format of this manifest is vendor specific, but can be identified by the manifestType attribute.\"\n\t\t\t},\n\t\t\t\"manifestType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The manifest type which relates to the format and structure of the manifest content. The definition is based on the vendor specific format and definition outside of this specification.\"\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t\"images\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/AppImageV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IconV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"The list of intents implemented by the application as defined by https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IntentV1\"\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationSearchResponseV1\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t}\n\t  },\n\t  \"examples\": {\n\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\"categories\": [\n\t\t\t  \"developer tools\",\n\t\t\t  \"training\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"https://fdc3.finos.org\",\n\t\t\t\"publisher\": \"FDC3\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 640,\n\t\t\t\t  \"width\": 560,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 800,\n\t\t\t\t  \"height\": 750,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition for the FDC3 Workbench\"\n\t\t},\n\t\t\"MyAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"my-application\",\n\t\t\t\"title\": \"My Application\",\n\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\"categories\": [\n\t\t\t  \"market data\",\n\t\t\t  \"research\",\n\t\t\t  \"news\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\"type\": \"image/png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"intents\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t],\n\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t  ],\n\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"userChannels\": {\n\t\t\t\t\"broadcasts\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t],\n\t\t\t\t\"listensFor\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t]\n\t\t\t  },\n\t\t\t  \"appChannels\": [\n\t\t\t\t{\n\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t  ],\n\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition that describes the app's use of interop.\"\n\t\t},\n\t\t\"AllAppsResponse\": {\n\t\t  \"value\": {\n\t\t\t\"applications\": [\n\t\t\t  {\n\t\t\t\t\"appId\": \"my-application\",\n\t\t\t\t\"title\": \"My Application\",\n\t\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"market data\",\n\t\t\t\t  \"research\",\n\t\t\t\t  \"news\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\t\"type\": \"image/png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  },\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t]\n\t\t\t\t\t  },\n\t\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"raises\": {\n\t\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"userChannels\": {\n\t\t\t\t\t\"broadcasts\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t],\n\t\t\t\t\t\"listensFor\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"appChannels\": [\n\t\t\t\t\t{\n\t\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  ]\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"developer tools\",\n\t\t\t\t  \"training\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png,\",\n\t\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"publisher\": \"FDC3,\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 640,\n\t\t\t\t\t  \"width\": 560,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 800,\n\t\t\t\t\t  \"height\": 750,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t],\n\t\t\t\"message\": \"OK\"\n\t\t  },\n\t\t  \"summary\": \"A sample 'all applications' listing response\"\n\t\t},\n\t\t\"Error400Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 400,\n\t\t\t\"message\": \"There was an error in your request.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Bad Request error.\"\n\t\t},\n\t\t\"Error403Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 403,\n\t\t\t\"message\": \"Certificate authentication failed for the requested user.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Forbidden error.\"\n\t\t},\n\t\t\"Error500Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 500,\n\t\t\t\"message\": \"An internal server error occurred. See the response body for further details.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Server error.\"\n\t\t}\n\t  }\n\t}\n  }"
  },
  {
    "path": "website/static/schemas/2.1/bridging/agentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/agentErrorResponse.schema.json\",\n  \"title\": \"Agent Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge containing an error, to be used in preference to the standard response when an error needs to be returned.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Error Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"Error message payload containing an standardized error string.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n        }\n      },\n      \"unevaluatedProperties\": false,\n      \"required\": [\"error\"]\n    },\n    \"meta\": {\n      \"$ref\": \"agentResponse.schema.json#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/agentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/agentRequest.schema.json\",\n  \"title\": \"Agent Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Request Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"broadcastRequest\",\n        \"findInstancesRequest\",\n        \"findIntentRequest\",\n        \"findIntentsByContextRequest\",\n        \"getAppMetadataRequest\",\n        \"openRequest\",\n        \"PrivateChannel.broadcast\",\n        \"PrivateChannel.eventListenerAdded\",\n        \"PrivateChannel.eventListenerRemoved\",\n        \"PrivateChannel.onAddContextListener\",\n        \"PrivateChannel.onDisconnect\",\n        \"PrivateChannel.onUnsubscribe\",\n        \"raiseIntentRequest\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"AgentRequestMeta\": {\n      \"title\": \"Agent Request Metadata\",\n      \"description\": \"Metadata for a request message sent by Desktop Agents to the Bridge.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself.\",\n          \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/agentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/agentResponse.schema.json\",\n  \"title\": \"Agent Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"$defs\": {\n    \"AgentResponseMeta\": {\n      \"title\": \"Agent Response Metadata\",\n      \"description\": \"Metadata for a response messages sent by a Desktop Agent to the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/bridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/bridgeErrorResponse.schema.json\",\n  \"title\": \"Bridge Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request, used where all connected agents returned errors.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Error Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The error message payload contains details of an error return to the app or agent that raised the original request.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n        }\n      }\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeErrorResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeErrorResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\", \"errorSources\", \"errorDetails\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/bridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/bridgeRequest.schema.json\",\n  \"title\": \"Bridge Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message forwarded from the Bridge onto a Desktop Agent connected to it.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Message type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeRequestMeta\": {\n      \"title\": \"Bridge Request Metadata\",\n      \"description\": \"Metadata required in a request message forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Bridge Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST be set by the bridge.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\", \"source\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/bridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/bridgeResponse.schema.json\",\n  \"title\": \"Bridge Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"sources\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseSources\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/broadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/broadcastAgentRequest.schema.json\",\n  \"title\": \"Broadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"BroadcastRequestBase\": {\n      \"title\": \"Broadcast Request\",\n      \"type\":\"object\",\n      \"description\": \"A request to broadcast context on a channel.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Broadcast Request Message Type\",\n          \"const\": \"broadcastRequest\"\n        },\n        \"payload\": {\n          \"title\": \"broadcast Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The Id of the Channel that the broadcast was sent on\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\",\n              \"description\": \"The context object that was the payload of a broadcast message.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"context\"]\n        },\n        \"meta\": {\n          \"type\": \"object\",\n          \"title\": \"broadcast request metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/broadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/broadcastBridgeRequest.schema.json\",\n  \"title\": \"Broadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"broadcastAgentRequest.schema.json#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/common.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/common.schema.json\",\n  \"title\": \"Bridging Commons\",\n  \"type\": \"object\",\n  \"description\": \"Common elements referenced by other schemas\",\n  \"$defs\": {\n    \"RequestUuid\": {\n      \"title\": \"Request UUID\",\n      \"type\": \"string\",\n      \"description\": \"UUID for the request\"\n    },\n    \"ResponseUuid\": {\n      \"title\": \"Response UUID\",\n      \"type\": \"string\",\n      \"description\": \"UUID for this specific response message.\"\n    },\n    \"Timestamp\": {\n      \"title\": \"Timestamp\",\n      \"type\": \"string\",\n      \"format\": \"date-time\",\n      \"description\": \"Timestamp at which request was generated\"\n    },\n    \"RequestSource\": {\n      \"title\": \"Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from, or the source Desktop Agent if it issued the request or response itself.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ]\n    },\n    \"AppRequestSource\": {\n      \"title\": \"App Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n    },\n    \"AgentDestination\": {\n      \"title\": \"Agent Destination identifier\",\n      \"description\": \"Field that represents a destination Desktop Agent that a request is to be sent to.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n    },\n    \"AppDestination\": {\n      \"title\": \"App Destination identifier\",\n      \"description\": \"Field that represents a destination App on a remote Desktop Agent that a request is to be sent to.\",\n      \"allOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        }\n      ]\n    },\n    \"BridgeParticipantIdentifier\": {\n      \"title\": \"Bridge Participant Identifier\",\n      \"description\": \"Represents identifiers that MUST include the Desktop Agent name and MAY identify a specific app or instance.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"allOf\": [\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n            },\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n            }\n          ]\n        }\n      ]\n    },\n    \"BridgeResponseSources\": {\n      \"title\": \"Desktop Agents that responded\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for the sources that generated responses to the request. Will contain a single value for individual responses and multiple values for responses that were collated by the bridge. May be omitted if all sources errored. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"BridgeResponseErrorSources\": {\n      \"title\": \"Desktop Agents that errored\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for responses that were not returned to the bridge before the timeout or because an error occurred. May be omitted if all sources responded without errors. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"ErrorMessages\": {\n      \"oneOf\": [\n        { \"$ref\": \"../api/api.schema.json#/definitions/ChannelError\" },\n        { \"$ref\": \"../api/api.schema.json#/definitions/OpenError\" },\n        { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n        { \"$ref\": \"../api/api.schema.json#/definitions/ResultError\" },\n        { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n      ]\n    },\n    \"BridgeResponseErrorDetails\": {\n      \"title\": \"Response Error Details\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/$defs/ErrorMessages\"\n      },\n      \"description\": \"Array of error message strings for responses that were not returned to the bridge before the timeout or because an error occurred. Should be the same length as the `errorSources` array and ordered the same. May be omitted if all sources responded without errors.\"\n    },\n    \"PrivateChannelEventListenerTypes\": {\n      \"title\": \"Private Channel Event Listener Types\",\n      \"description\": \"Event listener type names for Private Channel events\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"onAddContextListener\",\n        \"onUnsubscribe\",\n        \"onDisconnect\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/connectionStep.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/connectionStep.schema.json\",\n  \"title\": \"Connection Step Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used during the connection flow for a Desktop Agent to the Bridge. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Connection Step Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"hello\",\n        \"handshake\",\n        \"authenticationFailed\",\n        \"connectedAgentsUpdate\"\n      ],\n      \"description\": \"Identifies the type of the connection step message.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload, containing data pertaining to this connection step.\",\n      \"unevaluatedProperties\": false\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/ConnectionStepMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"ConnectionStepMeta\": {\n      \"title\": \"Connection Step Metadata\",\n      \"description\": \"Metadata for this connection step message.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        }\n      },\n      \"required\": [\"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/connectionStep2Hello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/connectionStep2Hello.schema.json\",\n  \"title\": \"ConnectionStep2Hello\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep2HelloBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep2HelloBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep2Hello\",\n      \"description\": \"Hello message sent by the Bridge to anyone connecting to the Bridge (enables identification as a bridge and confirmation of whether authentication is required)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 2 Message Type\",\n          \"const\": \"hello\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 2 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"desktopAgentBridgeVersion\": {\n              \"title\": \"Desktop Agent Bridge Version Number\",\n              \"description\": \"The version of the Bridge\",\n              \"type\": \"string\"\n            },\n            \"supportedFDC3Versions\": {\n              \"title\": \"Supported FDC3 Versions\",\n              \"type\": \"array\",\n              \"description\": \"The FDC3 versions supported by the Bridge\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"authRequired\": {\n              \"title\": \"Authentication Required\",\n              \"type\": \"boolean\",\n              \"description\": \"A flag indicating whether the Desktop Agent Bridge requires authentication or not.\"\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\",\n              \"description\": \"An optional Desktop Agent Bridge JWT authentication token if the Desktop Agent want to authenticate a bridge.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"desktopAgentBridgeVersion\", \"supportedFDC3Versions\", \"authRequired\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 2 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"timestamp\": {\n              \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.1/bridging/connectionStep3Handshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/connectionStep3Handshake.schema.json\",\n  \"title\": \"ConnectionStep3Handshake\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep3HandshakeBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep3HandshakeBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep3Handshake\",\n      \"description\": \"Handshake message sent by the Desktop Agent to the Bridge (including requested name, channel state and authentication data)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 3 Message Type\",\n          \"const\": \"handshake\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 3 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"implementationMetadata\": {\n              \"title\": \"Desktop Agent ImplementationMetadata\",\n              \"description\": \"Desktop Agent ImplementationMetadata trying to connect to the bridge.\",\n              \"$ref\": \"../api/baseImplementationMetadata.schema.json\"\n            },\n            \"requestedName\": {\n              \"title\": \"Requested name\",\n              \"description\": \"The requested Desktop Agent name\",\n              \"type\": \"string\"\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The current state of the Desktop Agent's channels, excluding any private channels, as a mapping of channel id to an array of Context objects, most recent first.\",\n              \"additionalProperties\": {\n                \"title\": \"Channel \",\n                \"type\": \"array\",\n                  \"items\": {\n                    \"$ref\": \"../context/context.schema.json\"\n                  }\n              }\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"implementationMetadata\", \"requestedName\", \"channelsState\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 3 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.1/bridging/connectionStep4AuthenticationFailed.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/connectionStep4AuthenticationFailed.schema.json\",\n  \"title\": \"ConnectionStep4AuthenticationFailed\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep4AuthenticationFailedBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep4AuthenticationFailedBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep4AuthenticationFailed\",\n      \"description\": \"Message sent by Bridge to Desktop Agent if their authentication fails.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 4 Message Type\",\n          \"const\": \"authenticationFailed\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 4 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"message\": {\n              \"title\": \"Authentication failed message\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 4 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.1/bridging/connectionStep6ConnectedAgentsUpdate.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/connectionStep6ConnectedAgentsUpdate.schema.json\",\n  \"title\": \"ConnectionStep6ConnectedAgentsUpdate\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep6ConnectedAgentsUpdateBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep6ConnectedAgentsUpdateBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep6ConnectedAgentsUpdateBase\",\n      \"description\": \"Message sent by Bridge to all Desktop Agent when an agent joins or leaves the bridge, includes the details of all agents, the change made and the expected channel state for all agents.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 6 Message Type\",\n          \"const\": \"connectedAgentsUpdate\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 6 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"addAgent\": {\n              \"title\": \"Agents To Add\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent first connects to the bridge and provide its assigned name.\"\n            },\n            \"removeAgent\": {\n              \"title\": \"Agents To Remove\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent disconnects from the bridge and provide the name that no longer is assigned.\"\n            },\n            \"allAgents\": {\n              \"title\": \"All Connected Agents\",\n              \"type\": \"array\",\n              \"description\": \"Desktop Agent Bridge implementation metadata of all connected agents.\",\n              \"items\": {\n                \"$ref\": \"../api/baseImplementationMetadata.schema.json\"\n              }\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The updated state of channels that should be adopted by the agents. Should only be set when an agent is connecting to the bridge.\",\n              \"additionalProperties\": {\n                \"type\": \"array\",\n                  \"items\": {\n                    \"$ref\": \"../context/context.schema.json\"\n                  }\n              }\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"allAgents\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 6 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentErrorResponse.schema.json\",\n  \"title\": \"FindInstances Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesErrorResponseBase\": {\n      \"title\": \"FindInstances Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindInstances Response Message Type\",\n          \"const\": \"findInstancesResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindInstances Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"FindInstances Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindInstances Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentRequest.schema.json\",\n  \"title\": \"FindInstances Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesRequestBase\": {\n      \"title\": \"FindInstances Request\",\n      \"type\": \"object\",\n      \"description\": \"A request for details of instances of a particular app\",\n      \"properties\":{\n        \"type\": {\n          \"title\": \"FindInstances Request Message Type\",\n          \"const\": \"findInstancesRequest\"\n        },\n        \"payload\": {\n          \"type\": \"object\",\n          \"title\": \"FindInstances Request Payload\",\n          \"properties\": {\n            \"app\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n            }\n          },\n          \"required\": [\"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindInstances request metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"oneOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentResponse.schema.json\",\n  \"title\": \"FindInstances Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesResponseBase\": {\n      \"title\": \"FindInstances Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindInstances Response Message Type\",\n          \"const\": \"findInstancesResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindInstances Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appIdentifiers\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"$ref\": \"../api/api.schema.json#/definitions/AppMetadata\"\n              }\n            }\n          },\n          \"required\": [\"appIdentifiers\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindInstances Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeErrorResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentErrorResponse.schema.json#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeRequest.schema.json\",\n  \"title\": \"FindInstances Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentRequest.schema.json#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findInstancesBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentResponse.schema.json#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentErrorResponseBase\": {\n      \"title\": \"FindIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntent Response Message Type\",\n          \"const\": \"findIntentResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntent Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"FindIntent Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentRequest.schema.json\",\n  \"title\": \"FindIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentRequestBase\": {\n      \"title\": \"FindIntent Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of apps available to resolve a particular intent and context pair.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntent Request Message Type\",\n          \"const\": \"findIntentRequest\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntent Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intent\": {\n              \"title\": \"Intent name\",\n              \"type\": \"string\"\n            },\n            \"context\": {\n              \"title\": \"Context argument\",\n              \"$ref\": \"../context/context.schema.json\"\n            }\n          },\n          \"required\": [\"intent\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\" : \"FindIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": true\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentResponse.schema.json\",\n  \"title\": \"FindIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentResponseBase\": {\n      \"title\": \"FindIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntent Response Message Type\",\n          \"const\": \"findIntentResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntent Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appIntent\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIntent\"\n            }\n          },\n          \"required\": [\"appIntent\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentErrorResponse.schema.json#/$defs/FindIntentErrorResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeRequest.schema.json\",\n  \"title\": \"FindIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentRequest.schema.json#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentResponse.schema.json#/$defs/FindIntentResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextErrorResponseBase\": {\n      \"title\": \"FindIntentsByContext Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntentsByContext Response Message Type\",\n          \"const\": \"findIntentsByContextResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntentsByContext Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"FindIntentsByContext Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"error\"]\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextRequestBase\": {\n      \"title\": \"FindIntentsByContext Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of intents and apps available to resolve them for a particular context.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntentsByContext Request Message Type\",\n          \"const\": \"findIntentsByContextRequest\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntentsByContext Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            }\n          },\n          \"required\": [\"context\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextResponseBase\": {\n      \"title\": \"FindIntentsByContext Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"FindIntentsByContext Response Message Type\",\n          \"const\": \"findIntentsByContextResponse\"\n        },\n        \"payload\": {\n          \"title\": \"FindIntentsByContext Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appIntents\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"$ref\": \"../api/api.schema.json#/definitions/AppIntent\"\n              },\n              \"additionalProperties\": false\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"appIntents\"]\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentErrorResponse.schema.json#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentRequest.schema.json#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/findIntentsByContextBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentResponse.schema.json#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataErrorResponseBase\": {\n      \"title\": \"GetAppMetadata Error Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"GetAppMetadata Response Message Type\",\n          \"const\": \"getAppMetadataResponse\"\n        },\n        \"payload\": {\n          \"title\": \"GetAppMetadata Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"GetAppMetadata Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentRequest.schema.json\",\n  \"title\": \"GetAppMetadata Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataRequestBase\": {\n      \"title\": \"GetAppMetadata Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for metadata about an app\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"GetAppMetadata Request Message Type\",\n          \"const\": \"getAppMetadataRequest\"\n        },\n        \"payload\": {\n          \"title\": \"GetAppMetadata Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"app\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"required\": [\"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\" : \"GetAppMetadata Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataResponseBase\": {\n      \"title\": \"GetAppMetadata Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"GetAppMetadata Response Message Type\",\n          \"const\": \"getAppMetadataResponse\"\n        },\n        \"payload\": {\n          \"title\": \"GetAppMetadata Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appMetadata\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppMetadata\"\n            }\n          },\n          \"required\": [\"appMetadata\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentErrorResponse.schema.json#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeRequest.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentRequest.schema.json#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/getAppMetadataBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentResponse.schema.json#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openAgentErrorResponse.schema.json\",\n  \"title\": \"Open Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenErrorResponseBase\": {\n      \"title\": \"Open Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request that contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Open Response Message Type\",\n          \"const\": \"openResponse\"\n        },\n        \"payload\": {\n          \"title\": \"Open Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"Open Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/OpenError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openAgentRequest.schema.json\",\n  \"title\": \"Open Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenRequestBase\": {\n      \"title\": \"Open Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to open an application\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Open Request Message Type\",\n          \"const\": \"openRequest\"\n        },\n        \"payload\": {\n          \"title\": \"Open Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"app\": {\n              \"type\": \"object\",\n              \"title\": \"App to open\",\n              \"description\": \"The application to open on the specified Desktop Agent\",\n              \"allOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            }\n          },\n          \"required\": [\"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\":  {\n          \"title\": \"Open Request Metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openAgentResponse.schema.json\",\n  \"title\": \"Open Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenResponseBase\": {\n      \"title\": \"Open Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Open Response Message Type\",\n          \"const\": \"openResponse\"\n        },\n        \"payload\": {\n          \"title\": \"Open Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appIdentifier\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n            }\n          },\n          \"required\": [\"appIdentifier\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openBridgeErrorResponse.schema.json\",\n  \"title\": \"Open Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentErrorResponse.schema.json#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openBridgeRequest.schema.json\",\n  \"title\": \"Open Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentRequest.schema.json#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/openBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/openBridgeResponse.schema.json\",\n  \"title\": \"Open Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentResponse.schema.json#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelBroadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelBroadcastAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelBroadcastRequestBase\": {\n      \"title\": \"PrivateChannelBroadcast Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to broadcast on a PrivateChannel.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel Broadcast Message type\",\n          \"const\": \"PrivateChannel.broadcast\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelBroadcast Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channel\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The Id of the PrivateChannel that the broadcast was sent on\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\",\n              \"description\": \"The context object that was the payload of a broadcast message.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"context\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelBroadcast Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelBroadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelBroadcastBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelBroadcastAgentRequest.schema.json#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelEventListenerAddedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerAddedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerAddedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerAdded Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerAdded event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerAdded Message type\",\n          \"const\": \"PrivateChannel.eventListenerAdded\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"common.schema.json#/$defs/PrivateChannelEventListenerTypes\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerAddedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerRemovedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerRemoved Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerRemoved event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerRemoved Message type\",\n          \"const\": \"PrivateChannel.eventListenerRemoved\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"common.schema.json#/$defs/PrivateChannelEventListenerTypes\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerRemovedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnAddContextListenerRequestBase\": {\n      \"title\": \"PrivateChannelOnAddContextListener Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an AddContextListener event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnAddContextListener Message type\",\n          \"const\": \"PrivateChannel.onAddContextListener\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\"\n            },\n            \"contextType\": {\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnAddContextListenerAgentRequest.schema.json#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnDisconnectAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnDisconnectAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnDisconnectRequestBase\": {\n      \"title\": \"PrivateChannelOnDisconnect Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on a Disconnect event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnDisconnect Message type\",\n          \"const\": \"PrivateChannel.onDisconnect\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnDisconnectBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnDisconnectBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnDisconnectAgentRequest.schema.json#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnUnsubscribeRequestBase\": {\n      \"title\": \"PrivateChannelOnUnsubscribe Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an Unsubscribe event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnUnsubscribe Message type\",\n          \"const\": \"PrivateChannel.onUnsubscribe\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\"\n            },\n            \"contextType\": {\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnUnsubscribeAgentRequest.schema.json#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentErrorResponseBase\": {\n      \"title\": \"RaiseIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Response Message type\",\n          \"const\": \"raiseIntentResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"RaiseIntent Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResolveError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentRequest.schema.json\",\n  \"title\": \"RaiseIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentRequestBase\": {\n      \"title\": \"RaiseIntent Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Request Message type\",\n          \"const\": \"raiseIntentRequest\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intent\": {\n              \"type\": \"string\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            },\n            \"app\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"required\": [\"intent\", \"context\", \"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false,\n          \"required\": [\"requestUuid\",\"timestamp\",\"destination\",\"source\"] \n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResponseBase\": {\n      \"title\": \"RaiseIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Response Message type\",\n          \"const\": \"raiseIntentResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intentResolution\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/IntentResolution\"\n            }\n          },\n          \"required\": [\"intentResolution\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentErrorResponse.schema.json#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeRequest.schema.json\",\n  \"title\": \"RaiseIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentRequest.schema.json#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentResponse.schema.json#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentResultAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultErrorResponseBase\": {\n      \"title\": \"RaiseIntent Result Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result, which contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Result Response Message type\",\n          \"const\": \"raiseIntentResultResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Result Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"RaiseIntent Result Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResultError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentResultAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultResponseBase\": {\n      \"title\": \"RaiseIntent Result Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Result Response Message type\",\n          \"const\": \"raiseIntentResultResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Result Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intentResult\": {\n              \"title\": \"IntentResult\",\n              \"anyOf\": [\n                {\n                  \"type\": \"object\",\n                  \"title\": \"IntentResult Context\",\n                  \"properties\": {\n                    \"context\": {\n                      \"$ref\": \"../context/context.schema.json\"\n                    }\n                  },\n                  \"required\": [\"context\"],\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"object\",\n                  \"title\": \"IntentResult Channel\",\n                  \"properties\": {\n                    \"channel\": {\n                      \"$ref\": \"../api/api.schema.json#/definitions/Channel\"\n                    }\n                  },\n                  \"required\": [\"channel\"],\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"object\",\n                  \"title\": \"IntentResult Void\",\n                  \"properties\": {},\n                  \"additionalProperties\": false\n                }\n              ]\n            }\n          },\n          \"required\": [\"intentResult\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentResultBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentErrorResponse.schema.json#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridging/raiseIntentResultBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentResponse.schema.json#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/bridgingAsyncAPI/README.md",
    "content": "# Agent Bridging AsyncAPI schema\n\nThis folder contains an AsyncAPI schema that may be used to generate clients and server stubs for Desktop Agent Bridging. It is based on references to the JSON schema files that define the various messages in the adjacent schemas/bridging folder.\n\nExample commands to generate code from the AsyncAPI schema:\n(run from the root of your FDC3 checkout)\n\nFirst run:\n\n```ps\nnpm install -g @asyncapi/generator\n```\n\nThen:\n\n- .NET\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/dotnet-nats-template -o ../some/path/outside/FDC3/folder\n    ```\n\n- Node.js\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/nodejs-ws-template -o ../some/path/outside/FDC3/folder -p server=local\n     ```\n\n- Markdown\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/markdown-template -o ../some/path/outside/FDC3/folder \n     ```\n\n- HTML\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/html-template -o ../some/path/outside/FDC3/folder \n    ```\n"
  },
  {
    "path": "website/static/schemas/2.1/bridgingAsyncAPI/bridgingAsyncAPI.json",
    "content": "{\n    \"asyncapi\": \"2.6.0\",\n    \"info\": {\n        \"title\": \"Desktop Agent Bridge\",\n        \"version\": \"1.0.0\",\n        \"description\": \"API for an FDC3 Desktop Agent to communicate with an FDC3 Desktop Agent Bridge and through it, other Desktop Agents.\",\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"https://www.apache.org/licenses/LICENSE-2.0\"\n        }\n    },\n    \"servers\": {\n        \"local\": {\n            \"url\": \"ws://localhost:4475\",\n            \"description\": \"Desktop agent bridge server exposing websocket connection\",\n            \"protocol\": \"ws\"\n        }\n    },\n    \"defaultContentType\": \"application/json\",\n    \"channels\": {\n        \"/\": {\n            \"publish\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/handshake\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/broadcastRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelBroadcast-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerAdded-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerRemoved-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnAddContextListener-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnUnsubscribe-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Agent\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by A Desktop Agent to a Bridge\",\n                \"operationId\": \"Send\"\n            },\n            \"subscribe\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/hello\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/authenticationFailed\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/connectedAgentsUpdate\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Bridge\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by a Bridge to a Desktop Agent\",\n                \"operationId\": \"Receive\"\n            }\n        }\n    },\n    \"components\": {\n        \"messages\": {\n            \"broadcastRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/broadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"hello\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep2Hello.schema.json#\"\n                }\n            },\n            \"handshake\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep3Handshake.schema.json#\"\n                }\n            },\n            \"authenticationFailed\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep4AuthenticationFailed.schema.json#\"\n                }\n            },\n            \"connectedAgentsUpdate\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep6ConnectedAgentsUpdate.schema.json#\"\n                }\n            },\n            \"findInstancesRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentRequest.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentRequest.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"openRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentRequest.schema.json#\"\n                }\n            },\n            \"openResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"openResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"privateChannelBroadcast-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelBroadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerAdded-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerAddedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerRemoved-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerRemovedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnAddContextListener-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnAddContextListenerAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnDisconnect-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnDisconnectAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnUnsubscribe-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnUnsubscribeAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeErrorResponse.schema.json#\"\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/action.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/action.schema.json\",\n  \"title\": \"Action\",\n  \"description\": \"A representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\\n\\nThe action may be completed by calling `fdc3.raiseIntent()` with the specified Intent and Context, or, if only a context is specified, by calling `fdc3.raiseIntentForContext()` (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\\n\\nAccepts an optional `app` parameter in order to specify a specific app.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.action\" },\n        \"title\": {\n          \"title\": \"Action Title\",\n          \"description\": \"A human readable display name for the action\",\n          \"type\": \"string\"\n        },\n        \"intent\": {\n          \"title\": \"Action Intent\",\n          \"description\": \"Optional Intent to raise to perform the actions. Should reference an intent type name, such as those defined in the FDC3 Standard. If intent is not set then `fdc3.raiseIntentForContext` should be used to perform the action as this will usually allow the user to choose the intent to raise.\",\n          \"type\": \"string\"\n        },\n        \"context\": {\n          \"title\": \"Action Context\",\n          \"description\": \"A context object with which the action will be performed\",\n          \"$ref\": \"context.schema.json#\"\n        },\n        \"app\": {\n          \"title\": \"Action Target App\",\n          \"description\": \"An optional target application identifier that should perform the action\",\n          \"allOf\": [\n            { \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\" }\n          ]\n        }\n      },\n      \"required\": [\n        \"title\", \"context\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.action\",\n      \"title\": \"Click to view Chart\",\n      \"intent\": \"ViewChart\",\n      \"context\": {\n          \"type\": \"fdc3.chart\",\n          \"instruments\": [\n              {\n                  \"type\": \"fdc3.instrument\",\n                  \"id\": {\n                      \"ticker\": \"EURUSD\"\n                  }\n              }\n          ],\n          \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n          },\n          \"style\": \"candle\"\n      },\n      \"app\" :{\n          \"appId\": \"MyChartViewingApp\",\n          \"instanceId\": \"instance1\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/chart.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/chart.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chart\",\n  \"description\": \"A context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\\n\\n- A list of instruments for comparison\\n- The time period to plot the chart over\\n- The style of chart (line, bar, mountain, candle etc.)\\n- Other settings such as indicators to calculate, or data representing drawings and annotations.\\n\\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chart\" },\n        \"instruments\": {\n          \"title\": \"Instruments to plot\",\n          \"description\": \"An array of instrument contexts whose data should be plotted.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        },\n        \"range\": {\n          \"title\": \"Time Range\",\n          \"description\": \"The time range that should be plotted\",\n          \"allOf\": [{\n            \"$ref\": \"timeRange.schema.json#\"\n          }]\n        },\n        \"style\": {\n          \"title\": \"Chart style\",\n          \"description\": \"The type of chart that should be plotted\",\n          \"type\": \"string\",\n          \"enum\": [\t\"line\", \"bar\", \"stacked-bar\", \"mountain\", \"candle\", \"pie\", \"scatter\", \"histogram\", \"heatmap\", \"custom\"]\n        },\n        \"otherConfig\": {\n          \"title\": \"Other configuration\",\n          \"description\": \"It is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"context.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\"instruments\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chart\",\n      \"instruments\": [\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"AAPL\"\n              }\n          },\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"GOOG\"\n              }\n          }\n      ],\n      \"range\": {\n          \"type\": \"fdc3.timeRange\",\n          \"startTime\": \"2020-09-01T08:00:00.000Z\",\n          \"endTime\": \"2020-10-31T08:00:00.000Z\"\n      },\n      \"style\": \"line\",\n      \"otherConfig\": [\n          {\n              \"type\": \"somevendor.someproduct.indicator\",\n              \"name\": \"stddev\",\n              \"parameters\": {\n                  \"period\": 10,\n                  \"matype\": \"exponential\"\n              }\n          },\n          {\n              \"type\": \"someothervendor.someotherproduct.formula\",\n              \"formula\": \"standard-deviation\",\n              \"fields\": {\n                  \"lookback\": 10,\n                  \"type\": \"ema\"\n              }\n          }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/chatInitSettings.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/chatInitSettings.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatInitSettings\",\n  \"description\": \"A collection of settings to start a new chat conversation\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.initSettings\" },\n        \"chatName\": {\n          \"title\": \"Chat name\",\n          \"description\": \"Name to apply to the chat created\",\n          \"type\": \"string\"\n        },\n        \"members\": {\n          \"title\": \"Chat members\",\n          \"description\": \"Contacts to add to the chat\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"message\": {\n          \"title\": \"Initial chat message\",\n          \"description\": \"An initial message to post in the chat when created.\",\n          \"anyOf\": [\n            {\n              \"type\": \"string\"\n            },\n            {\n              \"$ref\": \"message.schema.json#\"\n            }\n          ]\n        },\n        \"options\": {\n          \"title\": \"Chat options\",\n          \"description\": \"Option settings that affect the creation of the chat\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"groupRecipients\": {\n              \"title\": \"Group recipients option\",\n              \"description\": \"if false a separate chat will be created for each member\",\n              \"type\": \"boolean\"\n            },\n            \"isPublic\": {\n              \"title\": \"Public chat option\",\n              \"description\": \"if true the room will be visible to everyone in the chat application\",\n              \"type\": \"boolean\"\n            },\n            \"allowHistoryBrowsing\":  {\n              \"title\": \"Allow history browsing option\",\n              \"description\": \"if true members will be allowed to browse past messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowMessageCopy\":  {\n              \"title\": \"Allow message copy option\",\n              \"description\": \"if true members will be allowed to copy/paste messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowAddUser\":  {\n              \"title\": \"All adding users option\",\n              \"description\": \"if true members will be allowed to add other members to the chat\",\n              \"type\": \"boolean\"\n            }\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.initSettings\",\n      \"chatName\": \"Chat ABCD\",\n      \"members\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john@mail.com\"\n            }\n          }\n        ]\n      },\n      \"options\": {\n        \"groupRecipients\": true,\n        \"isPublic\": false,\n        \"allowHistoryBrowsing\": true,\n        \"allowMessageCopy\": true\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n          \"0\": {\n            \"type\": \"fdc3.fileAttachment\",\n            \"data\": {\n              \"name\": \"myImage.png\",\n              \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n            }\n          }\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/chatMessage.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/chatMessage.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chat Message\",\n  \"description\": \"A context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.message\" },\n        \"chatRoom\": { \"$ref\": \"chatRoom.schema.json#\" },\n        \"message\": {\n          \"title\": \"Chat message\",\n          \"description\": \"The content of the message to post in the chat when created.\",\n          \"$ref\": \"message.schema.json#\"\n        }\n      },\n      \"required\": [\"type\", \"chatRoom\", \"message\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [{\n      \"type\": \"fdc3.chat.message\",\n      \"chatRoom\": {\n          \"type\": \"fdc3.chat.room\",\n          \"providerName\": \"Symphony\",\n          \"id\": {\n              \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n          }\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n           \"0\": {\n               \"type\": \"fdc3.fileAttachment\",\n                \"data\": {\n                \"name\": \"myImage.png\",\n                      \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n                }\n            }\n        }\n      }\n  }]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/chatRoom.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/chatRoom.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chat Room\",\n  \"description\": \"Reference to the chat room which could be used to send a message to the room\",\n  \"allOf\": [{\n    \"type\": \"object\",\n    \"properties\": {      \n      \"type\": { \"const\": \"fdc3.chat.room\" },\n      \"providerName\": { \n        \"title\": \"Chat provider name\",\n        \"description\": \"The name of the service that hosts the chat\",\n        \"type\": \"string\"\n      },\n      \"id\": { \n        \"title\": \"Chat room id\",\n        \"description\": \"Identifier(s) for the chat - currently unstandardized\",\n        \"type\": \"object\"\n      },\n      \"url\": { \n        \"title\": \"Chat URL\",\n        \"description\": \"Universal url to access to the room. It could be opened from a browser, a mobile app, etc...\",\n        \"type\": \"string\",\n        \"format\": \"uri\"\n      },\n      \"name\": {\n        \"title\": \"Chat name\",\n        \"description\": \"Display name for the chat room\",\n        \"type\": \"string\"\n      }\n    },\n    \"required\": [\"providerName\", \"id\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.room\",\n      \"providerName\": \"Symphony\",\n      \"id\": {\n          \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n      },\n      \"url\": \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n      \"name\": \"My new room\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/chatSearchCriteria.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/chatSearchCriteria.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chat Search Criteria\",\n  \"description\": \"A context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.chat.searchCriteria\"\n        },\n        \"criteria\": {\n          \"title\": \"Criteria array\",\n          \"description\": \"An array of criteria that should match chats returned from by a search.\\n\\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\\n\\nEmpty search criteria can be supported to allow resetting of filters.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"anyOf\": [\n              {\n                \"$ref\": \"instrument.schema.json#\"\n              },\n              {\n                \"$ref\": \"organization.schema.json#\"\n              },\n              {\n                \"$ref\": \"contact.schema.json#\"\n              },\n              {\n                \"type\": \"string\",\n                \"title\": \"Free text\",\n                \"description\": \"Free text to be used for a keyword search\"\n              }\n            ]\n          }\n        }\n      },\n      \"required\": [\n        \"criteria\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.searchCriteria\",\n      \"criteria\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"TSLA\"\n          },\n          \"name\": \"Tesla, inc.\"\n        },\n        \"annual return\"\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"description\": \"A person contact that can be engaged with through email, calling, messaging, CMS, etc.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contact\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Contact Identifiers\",\n          \"description\": \"Identifiers that relate to the Contact represented by this context\",\n          \"properties\": {\n            \"email\": {\n              \"type\": \"string\",\n              \"format\": \"email\",\n              \"title\": \"Email address\",\n              \"description\": \"The email address for the contact\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FDS ID\",\n              \"description\": \"FactSet Permanent Identifier representing the contact\"\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"description\": \"A collection of contacts, e.g. for chatting to or calling multiple contacts.\\n\\nThe contact list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contactList\"\n        },\n        \"contacts\": {\n          \"type\": \"array\",\n          \"title\": \"List of Contacts\",\n          \"description\": \"An array of contact contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"contact.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"contacts\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contactList\",\n      \"contacts\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"John Doe\",\n          \"id\": {\n            \"email\": \"john.doe@mail.com\"\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"description\": \"The `fdc3.context` type defines the basic contract or \\\"shape\\\" for all data exchanged by FDC3 operations. As such, it is not really meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\\n\\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the object represents, and what shape it has.\\n\\nThe FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/definitions/DocumentedContext\"\n    },\n    {\n      \"$ref\": \"#/definitions/BaseContext\"\n    }\n  ],\n  \"definitions\": {\n    \"BaseContext\": {\n      \"$comment\": \"Base definition for the Context object without documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\"\n        },\n        \"name\": {\n          \"type\": \"string\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"unevaluatedProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    },\n    \"DocumentedContext\": {\n      \"$comment\": \"Base definition for the Context object without documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"Type\",\n          \"description\": \"The type property is the only _required_ part of the FDC3 context data schema. The FDC3 [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present to route shared context data appropriately.\\n\\nFDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data types they support in an FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery and routing.\\n\\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an organization-specific namespace, e.g. `blackrock.fund`.\\n\\nSee the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more information about context data types.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"Context data objects may include a name property that can be used for more information, or display purposes. Some derived types may require the name object as mandatory, depending on use case.\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Id\",\n          \"description\": \"Context data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\\n\\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\",\n          \"unevaluatedProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"description\": \"A country entity.\\n\\nNotes:\\n\\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement is for at least one standardized identifier to be provided\\n\\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\\n\\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.country\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code\"\n            },\n            \"COUNTRY_ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code\"\n            },\n            \"ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            },\n            \"ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.country\",\n      \"name\": \"Sweden\",\n      \"id\": {\n        \"COUNTRY_ISOALPHA2\": \"SE\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/currency.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/currency.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Currency\",\n  \"description\": \"A context representing an individual Currency.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.currency\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Currency name\",\n          \"description\": \"The name of the currency for display purposes\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"CURRENCY_ISOCODE\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[A-Z]{3}$\",\n              \"title\": \"CURRENCY_ISOCODE\",\n              \"description\": \"The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.currency\",\n      \"name\": \"US Dollar\",\n      \"id\": {\n        \"CURRENCY_ISOCODE\": \"USD\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/email.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/email.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Email\",\n  \"description\": \"A collection of information to be used to initiate an email with a Contact or ContactList.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.email\"\n        },\n        \"recipients\": {\n          \"title\": \"Email Recipients\",\n          \"description\": \"One or more recipients for the email.\",\n          \"oneOf\": [\n            {\n              \"$ref\": \"contact.schema.json#\"\n            },\n            {\n              \"$ref\": \"contactList.schema.json#\"\n            }\n          ]\n        },\n        \"subject\": {\n          \"title\": \"Email Subject\",\n          \"description\": \"Subject line for the email.\",\n          \"type\": \"string\"\n        },\n        \"textBody\": {\n          \"title\": \"Email Body\",\n          \"description\": \"Body content for the email.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"recipients\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.email\",\n      \"recipients\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@example.com\"\n        }\n      },\n      \"subject\": \"The information you requested\",\n      \"textBody\": \"Blah, blah, blah ...\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"description\": \"A financial instrument from any asset class.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrument\"\n        },\n        \"id\": {\n          \"title\": \"Instrument identifiers\",\n          \"description\": \"Any combination of instrument identifiers can be used together to resolve ambiguity, or for a better match. Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified. In general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\\n\\nIt is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement is for at least one instrument identifier to be provided.\\n\\nTry to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define a property that makes it clear what the value represents. Doing so will make interpretation easier for the developers of target applications.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg security\",\n              \"description\": \"<https://www.bloomberg.com/>\"\n            },\n            \"CUSIP\": {\n              \"type\": \"string\",\n              \"title\": \"CUSIP\",\n              \"description\": \"<https://www.cusip.com/>\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FactSet Permanent Security Identifier\",\n              \"description\": \"<https://www.factset.com/>\"\n            },\n            \"FIGI\": {\n              \"type\": \"string\",\n              \"title\": \"Open FIGI\",\n              \"description\": \"<https://www.openfigi.com/>\"\n            },\n            \"ISIN\": {\n              \"type\": \"string\",\n              \"title\": \"ISIN\",\n              \"description\": \"<https://www.isin.org/>\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv PERMID\",\n              \"description\": \"<https://permid.org/>\"\n            },\n            \"RIC\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv Identification Code\",\n              \"description\": \" <https://www.refinitiv.com/>\"\n            },\n            \"SEDOL\": {\n              \"type\": \"string\",\n              \"title\": \"SEDOL\",\n              \"description\": \"<https://www.lseg.com/sedol>\"\n            },\n            \"ticker\": {\n              \"type\": \"string\",\n              \"title\": \"Stock ticker\",\n              \"description\": \"Unstandardized stock tickers\"\n            }\n          }\n        },\n        \"market\": {\n          \"description\": \"The `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"MIC\": {\n              \"type\": \"string\",\n              \"title\": \"Market Identifier Code\",\n              \"description\": \"<https://en.wikipedia.org/wiki/Market_Identifier_Code>\"\n            },\n            \"name\": {\n              \"type\": \"string\",\n              \"title\": \"Market Name\",\n              \"description\": \"Human readable market name\"\n            },\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"Country ISO Code\",\n              \"description\": \"<https://www.iso.org/iso-3166-country-codes.html>\"\n            },\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg Market Identifier\",\n              \"description\": \"<https://www.bloomberg.com/>\"\n            }\n          },\n          \"unevaluatedProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"required\": [\n        \"type\",\"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"name\": \"Microsoft\",\n      \"id\": {\n          \"ticker\": \"MSFT\",\n          \"RIC\": \"MSFT.OQ\",\n          \"ISIN\": \"US5949181045\"\n      },\n      \"market\": {\n          \"MIC\": \"XNAS\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"description\": \"A collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist). However, when holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type.\\n\\nThe instrument list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrumentList\"\n        },\n        \"instruments\": {\n          \"type\": \"array\",\n          \"title\": \"List of instruments\",\n          \"description\": \"An array of instrument contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"instruments\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrumentList\",\n      \"instruments\": [\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"AAPL\"\n          },\n          \"market\": {\n            \"MIC\": \"XNAS\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ISIN\": \"US5949181045\"\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/interaction.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/interaction.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Interaction\",\n  \"description\": \"An `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.interaction\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Interaction Id\",\n          \"description\": \"Can be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted. An interaction ID does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\",\n          \"properties\": {\n            \"URI\": {\n              \"type\": \"string\",\n              \"title\": \"Interaction URI\",\n              \"description\": \"Can be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\"\n            },\n            \"SALESFORCE\": {\n              \"type\": \"string\",\n              \"title\": \"Salesforce ID\",\n              \"description\": \"Interactions ID in Salesforce\"\n            },\n            \"SINGLETRACK\": {\n              \"type\": \"string\",\n              \"title\": \"SingleTrack ID\",\n              \"description\": \"Interaction ID in SingleTrack\"\n            }\n          }\n        },\n        \"participants\": {\n          \"title\": \"Interaction Participants\",\n          \"description\": \"A list of contacts involved in the interaction\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"timeRange\": {\n          \"title\": \"Interaction Time range\",\n          \"description\": \"The time range over which the interaction occurred\",\n          \"$ref\": \"timeRange.schema.json#\"\n        },\n        \"interactionType\": {\n          \"title\": \"Interaction Type\",\n          \"description\": \"`interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\",\n          \"anyOf\": [\n            {\n              \"type\": \"string\",\n              \"enum\": [\n                \"Instant Message\",\n                \"Email\",\n                \"Call\",\n                \"Meeting\"\n              ]\n            },\n            {\n              \"type\": \"string\"\n            }\n          ]\n        },\n        \"description\": {\n          \"title\": \"Interaction Description\",\n          \"description\": \"A human-readable description of the interaction\",\n          \"type\": \"string\"\n        },\n        \"initiator\": {\n          \"title\": \"Interaction Initiator\",\n          \"description\": \"The contact that initiated the interaction\",\n          \"$ref\": \"contact.schema.json#\"\n        },\n        \"origin\": {\n          \"title\": \"Interaction Origin\",\n          \"description\": \"Used to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"participants\",\n        \"timeRange\",\n        \"interactionType\",\n        \"description\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.interaction\",\n      \"participants\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane.doe@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john.doe@mail.com\"\n            }\n          }\n        ]\n      },\n      \"interactionType\": \"Instant Message\",\n      \"timeRange\": {\n        \"type\": \"fdc3.timeRange\",\n        \"startTime\": \"2022-02-10T15:12:00Z\"\n      },\n      \"description\": \"Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum\",\n      \"initiator\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"origin\": \"Outlook\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/message.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/message.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Message\",\n  \"description\": \"A chat message to be sent through an instant messaging application. Can contain one or several text bodies (organized by mime-type, plaintext or markdown), as well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.message\"\n        },\n        \"text\": {\n          \"type\": \"object\",\n          \"title\": \"Message text\",\n          \"description\": \"A map of string mime-type to string content\",\n          \"properties\": {\n            \"text/plain\": {\n              \"type\": \"string\",\n              \"title\": \"Plain text\",\n              \"description\": \"Plain text encoded content.\"\n            },\n            \"text/markdown\": {\n              \"title\": \"Markdown text\",\n              \"description\": \"Markdown encoded content\",\n              \"type\": \"string\"\n            }\n          }\n        },\n        \"entities\": {\n          \"type\": \"object\",\n          \"title\": \"Message entities\",\n          \"description\": \"A map of string IDs to entities that should be attached to the message, such as an action to perform, a file attachment, or other FDC3 context object.\",\n          \"additionalProperties\": {\n            \"anyOf\": [\n              {\n                \"$ref\": \"action.schema.json#\"\n              },\n              {\n                \"type\": \"object\",\n                \"title\": \"File attachment\",\n                \"description\": \"A File attachment encoded in the form of a data URI\",\n                \"properties\": {\n                  \"type\": {\n                    \"const\": \"fdc3.entity.fileAttachment\"\n                  },\n                  \"data\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                      \"name\": {\n                        \"type\": \"string\",\n                        \"title\": \"File name\",\n                        \"description\": \"The name of the attached file\"\n                      },\n                      \"dataUri\": {\n                        \"type\": \"string\",\n                        \"format\": \"uri\",\n                        \"title\": \"\",\n                        \"description\": \"A data URI encoding the content of the file to be attached\"\n                      }\n                    },\n                    \"required\": [\n                      \"name\",\n                      \"dataUri\"\n                    ]\n                  }\n                },\n                \"required\": [\n                  \"type\",\n                  \"data\"\n                ]\n              }\n            ]\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.message\",\n      \"text\": {\n        \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate\"\n      },\n      \"entities\": {\n        \"picture1\": {\n          \"type\": \"fdc3.fileAttachment\",\n          \"data\": {\n            \"name\": \"myImage.png\",\n            \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n          }\n        },\n        \"eurusd_action\": {\n          \"type\": \"fdc3.action\",\n          \"title\": \"Click to view Chart\",\n          \"intent\": \"ViewChart\",\n          \"context\": {\n            \"type\": \"fdc3.chart\",\n            \"instruments\": [\n              {\n                \"type\": \"fdc3.instrument\",\n                \"id\": {\n                  \"ticker\": \"EURUSD\"\n                }\n              }\n            ],\n            \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n            },\n            \"style\": \"candle\"\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/nothing.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/nothing.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Nothing\",\n  \"description\": \"A type that explicitly represents a lack of context.\\n\\nNotes:\\n\\n- Intended to be used in situations where no context is desired.\\n- For example:\\n  - Raising an intent without context (e.g. opening a blank order form, or chat interface without a contact selected).\\n  - Resetting context on a channel (e.g. when context is used to set a filter in other applications a null context might release the filter).\\n- An explicit representation of a Null or empty context allows apps to declare support for a lack of context, for example in their intent metadata in an app directory.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.nothing\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.nothing\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/order.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/order.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Order\",\n  \"description\": \"@experimental context type representing an order. To be used with OMS and EMS systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human readable `name` field to be used to summarize the order and an optional `details` field that may be used to provide additional detail about the order, including a context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as a unspecified Context type, but both `details` and `details.product` are expected to be standardized in future.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.order\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Order Identifiers\",\n          \"description\": \"One or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the order.\"\n        },\n        \"details\": {\n          \"type\": \"object\",\n          \"title\": \"Order Details\",\n          \"description\": \"Optional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context\",\n          \"properties\": {\n            \"product\": {\n              \"$ref\": \"product.schema.json\"\n            }\n          },\n          \"additionalProperties\": true\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"id\"\n      ],\n      \"additionalProperties\": true\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.order\",\n      \"name\": \"...\",\n      \"id\": {\n        \"myOMS\": \"12345\"\n      },\n      \"details\": {\n        \"product\": {\n          \"type\": \"fdc3.product\",\n          \"id\": {\n            \"productId\": \"ABC123\"\n          },\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"ABC123\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/orderList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/orderList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"OrderList\",\n  \"description\": \"@experimental A list of orders. Use this type for use cases that require not just a single order, but multiple.\\n\\nThe OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.orderList\"\n        },\n        \"orders\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"order.schema.json#\"\n          },\n          \"title\": \"List of Orders\",\n          \"description\": \"An array of order contexts that forms the list.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"orders\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.orderList\",\n      \"orders\": [\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"ABC123\"\n          }\n        },\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"DEF456\"\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"description\": \"An entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\\n\\nIt is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement is for at least one specified identifier to be provided.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.organization\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Organization Identifiers\",\n          \"description\": \"Identifiers for the organization, at least one must be provided.\",\n          \"minProperties\": 1,\n          \"properties\": {\n            \"LEI\": {\n              \"type\": \"string\",\n              \"title\": \"Legal Entity Identifier\",\n              \"description\": \"The Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO 17442 standard developed by the International Organization for Standardization (ISO). It connects to key reference information that enables clear and unique identification of legal entities participating in financial transactions.\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"Refinitiv Permanent Identifiers, or PermID for the organization\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"FactSet Permanent Identifier representing the organization\"\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.organization\",\n      \"name\": \"Cargill, Incorporated\",\n      \"id\": {\n        \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n        \"FDS_ID\": \"00161G-E\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"description\": \"A financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\\n\\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\\n\\nThe Portfolio type consists of an array of [Position](Position) types, each of which refers to a single [Instrument](Instrument) and a holding amount for that instrument.\\n\\nThe portfolio schema does not explicitly include identifiers in the `id` section, as there bis not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.portfolio\"\n        },\n        \"positions\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"position.schema.json#\"\n          },\n          \"title\": \"Portfolio positions\",\n          \"description\": \"The List of Positions which make up the Portfolio\"\n        }\n      },\n      \"required\": [\n        \"positions\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.portfolio\",\n      \"positions\": [\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"AAPL\"\n            }\n          },\n          \"holding\": 2000000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          },\n          \"holding\": 1500000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"IBM\"\n            }\n          },\n          \"holding\": 3000000\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"description\": \"A financial position made up of an instrument and a holding in that instrument. This type is a good example of how new context types can be composed from existing types.\\n\\nIn this case, the instrument and the holding amount for that instrument are required values.\\n\\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents multiple holdings in a combination of instruments.\\n\\nThe position schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.position\"\n        },\n        \"instrument\": {\n          \"$ref\": \"instrument.schema.json#\",\n          \"title\": \"The financial instrument that this position relates to\",\n          \"description\": \"\"\n        },\n        \"holding\": {\n          \"type\": \"number\",\n          \"title\": \"The size of the holding represented by this position\",\n          \"description\": \"The amount of the holding, e.g. a number of shares\"\n        }\n      },\n      \"required\": [\n        \"instrument\",\n        \"holding\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"AAPL\"\n        }\n      },\n      \"holding\": 2000000\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/product.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.1/context/product.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Product\",\n\t\"description\": \"@experimental context type representing a tradable product. To be used with OMS and EMS systems.\\n\\nThis type is currently only loosely defined as an extensible context object, with an optional instrument field.\\n\\nThe Product schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.product\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Product Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Product Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the product.\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"$ref\": \"instrument.schema.json\",\n\t\t\t\t\t\"title\": \"Product Instrument\",\n\t\t\t\t\t\"description\": \" financial instrument that relates to the definition of this product\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\",\n\t\t\t\t\"id\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\"id\": {\n\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t},\n\t\t\t\"instrument\": {\n\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/timeRange.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/timeRange.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TimeRange\",\n  \"description\": \"A context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\\n\\n- A pricing chart\\n- A trade blotter\\n- A record of client contact/activity in a CRM\\n\\nExample use cases:\\n\\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\\n\\nNotes:\\n\\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\\n  - A timezone indicator should be specified, e.g. `\\\"2022-05-12T15:18:03Z\\\"` or `\\\"2022-05-12T16:18:03+01:00\\\"`\\n  - Times MAY be specified with millisecond precision, e.g. `\\\"2022-05-12T15:18:03.349Z\\\"`\",\n  \"allOf\": [\n    {\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.timeRange\"\n        },\n        \"startTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Start Time\",\n          \"description\": \"The start time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        },\n        \"endTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"End Time\",\n          \"description\": \"The end time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"anyOf\": [\n    {\n      \"required\": [\n        \"startTime\",\n        \"endTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"startTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"endTime\"\n      ]\n    }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44Z\",\n      \"endTime\": \"2022-04-30T23:59:59ZS\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44+00:00\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"endTime\": \"2022-03-30T16:44:44.123Z\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/trade.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.1/context/trade.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Trade\",\n\t\"description\": \"@experimental context type representing a trade. To be used with execution systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as a unspecified Context type, but `product` is expected to be standardized in future.\\n\\n The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.trade\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Trade Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Trade Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the trade.\"\n\t\t\t\t},\n\t\t\t\t\"product\": {\n\t\t\t\t\t\"$ref\": \"product.schema.json\",\n\t\t\t\t\t\"title\": \"Traded product\",\n\t\t\t\t\t\"description\": \"A product that is the subject of th trade.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\", \"id\", \"product\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.trade\",\n\t\t\t\"name\": \"...\",\n\t\t\t\"id\": {\n\t\t\t\t\"myEMS\": \"12345\"\n\t\t\t},\n\t\t\t\"product\": {\n\t\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "website/static/schemas/2.1/context/tradeList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/tradeList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TradeList\",\n  \"description\": \"@experimental A list of trades. Use this type for use cases that require not just a single trade, but multiple.\\n\\nThe TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.tradeList\"\n        },\n        \"trades\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"trade.schema.json#\"\n          },\n          \"title\": \"List of Trades\",\n          \"description\": \"An array of trade contexts that forms the list.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"trades\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.tradeList\",\n      \"trades\": [\n        {\n          \"type\": \"fdc3.trade\",\n          \"name\": \"...\",\n          \"id\": {\n            \"myEMS\": \"12345\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"ABC123\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"MSFT\"\n              }\n            }\n          }\n        },\n        {\n          \"type\": \"fdc3.trade\",\n          \"id\": {\n            \"myEMS\": \"67890\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"DEF456\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"TSLA\"\n              }\n            }\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/transactionresult.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/transactionresult.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TransactionResult\",\n  \"description\": \"A context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an `IntentResult` by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.transactionResult\"\n        },\n        \"status\": {\n          \"type\": \"string\",\n          \"enum\": [\n            \"Created\",\n            \"Deleted\",\n            \"Updated\",\n            \"Failed\"\n          ],\n          \"title\": \"Transaction Status\",\n          \"description\": \"The status of the transaction being reported.\"\n        },\n        \"context\": {\n          \"$ref\": \"context.schema.json#\",\n          \"title\": \"Transaction Result Context\",\n          \"description\": \"A context object returned by the transaction, possibly with updated data.\"\n        }\n      },\n      \"message\": {\n        \"type\": \"string\",\n        \"title\": \"Transaction Message\",\n        \"description\": \"A human readable message describing the outcome of the transaction.\"\n      },\n      \"required\": [\n        \"type\",\n        \"status\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.transactionResult\",\n      \"status\": \"Updated\",\n      \"context\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.1/context/valuation.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/valuation.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Valuation\",\n  \"description\": \"A context type representing the price and value of a holding.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.valuation\"\n        },\n        \"value\": {\n          \"type\": \"number\",\n          \"title\": \"Value\",\n          \"description\": \"The value of the holding, expresses in the nominated currency.\"\n        },\n        \"price\": {\n          \"type\": \"number\",\n          \"title\": \"Price per unit\",\n          \"description\": \"The price per unit the the valuation is based on.\"\n        },\n        \"CURRENCY_ISOCODE\": {\n          \"type\": \"string\",\n          \"pattern\": \"^[A-Z]{3}$\",\n          \"title\": \"Valuation Currency\",\n          \"description\": \"The valuation currency, which should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n        },\n        \"valuationTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Valuation time\",\n          \"description\": \"The time at which the valuation was performed, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        },\n        \"expiryTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Expiry Time\",\n          \"description\": \"The time at which this valuation expires, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        }\n      },\n      \"required\": [\n        \"value\",\n        \"CURRENCY_ISOCODE\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.valuation\",\n      \"value\": 500.0,\n      \"price\": 5.0,\n      \"CURRENCY_ISOCODE\": \"USD\",\n      \"expiryTime\": \"2022-05-13T16:16:24+01:00\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/README.md",
    "content": "# Intro\n\nThe _schemas/api_ folder contains JSONSchema definitions that are used to implement wire protocols for an app working with a Desktop Agent, and for import into the Bridging wire protocols that shares many of the same structures.\n\nPlease note: Quicktype, the chosen generation tool currently has some limitations that prevent fully automatic schema generation from the existing TS types. For example, it can not handle interfaces that contain methods in their definition (as you can't define methods in JSON). It also fails to generate schemas even if a type contains unused references to other types or interfaces that contain async functions (`Promise` return types). Therefore, in order to generate the `api\\schemas\\api.schema.json` some manual intervention was needed.\n\nOnce these limitations are not an issue the `api\\schemas\\t2sQuicktypeUtil.js` script should be moved to the root level of the project and a new npm script `\"api-schema-gen\": \"node t2sQuicktypeUtil.js src/api schemas/api/api.schema.json\"` should be added. Alternatively, schemas (for API types) may be manually maintained against the matching TypeScript definitions\n\nContents:\n\n- `api\\schemas\\t2sQuicktypeUtil.js` - Script used to run the generation of the schema from the types. Should be moved to the root level of the repo once fully-automated generation can be achieved.\n- `api\\schemas\\api.schema.json` - Partially auto-generated schema from the existing `src\\api` types and metadata objects. Expected to be manually maintained in future.\n- `api\\schemas\\common.schema.json` - Common element definitions referenced in multiple other schemas in both the API and Bridging API protocols.\n- `api\\schemas\\appRequest.schema.json` - The base message definition that requests from an app to the DA are derived from.\n- `api\\schemas\\agentResponse.schema.json` - The base message definition that API call response messages from a DA to an app are derived from.\n- `api\\schemas\\agentEvent.schema.json` - The base message definition that event messages from a DA to an app are derived from.\n- `api\\schemas\\*Request.schema.json` - Schemas defining request messages sent from apps to Desktop Agents.\n- `api\\schemas\\*Response.schema.json` - Schemas defining responses from DAs to apps for request messages (sent from apps to Desktop Agents).\n- `api\\schemas\\*Event.schema.json` - Schemas defining event messages sent from Desktop Agents to Apps.\n\nPlease note that when adding a particular message type, that it needs its own schema file, which will declare the type (string). That type string MUST also be added to an enumeration in the base message schema it was derived from - each base message schema (appRequest, agentResponse, agentEvent) has an enumeration of the valid types and it must appear in that or the message will not validate. Unhelpfully, if you've forgotten to do that Quicktype will only report:\n\n```\nError: Internal error: We got an empty string type.\n```\n\nor another similar error - its not always the same one!\n\nIt can be very hard to figure out in which file the problem occurs. Generally, to figure out where an issue is, you can enable Quicktype's debug output by adding `--debug all` or `--debug print-schema-resolving` to the arguments assembled in s2tQuicktypeUtil.js or by taking the command it constructs (printed to the console) and manually add the option and re-run the command. If you're lucky, the error will be hit during the resolution steps which will point to the file(s) with an issue (often a disagreement between types combined with `allOf`).\n"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP1Hello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP1Hello.schema.json\",\n  \"title\": \"Web Connection Protocol 1 Hello\",\n  \"description\": \"Hello message sent by an application to a parent window or frame when attempting to establish connectivity to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP1HelloBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP1HelloBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP1Hello Message Type\",\n          \"const\": \"WCP1Hello\"\n        },\n        \"payload\": {\n          \"title\": \"WCP1Hello Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"identityUrl\": {\n              \"title\": \"Identity URL\",\n              \"description\": \"URL to use for the identity of the application. Desktop Agents MUST validate that the origin of the message matches the URL, but MAY implement custom comparison logic.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"actualUrl\": {\n              \"title\": \"Actual URL\",\n              \"description\": \"The current URL of the page attempting to connect. This may differ from the identityUrl, but the origins MUST match.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"description\": \"The version of FDC3 API that the app supports.\",\n              \"type\": \"string\"\n            },\n            \"intentResolver\": {\n              \"title\": \"Intent Resolver Required\",\n              \"description\": \"A flag that may be used to indicate that an intent resolver is or is not required. Set to `false` if no intents, or only targeted intents, are raised.\",\n              \"type\": \"boolean\"\n            },\n            \"channelSelector\": {\n              \"title\": \"Channel Selector Required\",\n              \"description\": \"A flag that may be used to indicate that a channel selector user interface is or is not required. Set to `false` if the app includes its own interface for selecting channels or does not work with user channels.\",\n              \"type\": \"boolean\"\n            }\n          },\n          \"required\": [\"identityUrl\",\"actualUrl\",\"fdc3Version\"]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [ \"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP2LoadUrl.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP2LoadUrl.schema.json\",\n  \"title\": \"Web Connection Protocol 2 Load Url\",\n  \"description\": \"Response from a Desktop Agent to an application requesting access to it indicating that it should load a specified URL into a hidden iframe in order to establish connectivity to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP2LoadUrlBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP2LoadUrlBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP2LoadUrl Message Type\",\n          \"const\": \"WCP2LoadUrl\"\n        },\n        \"payload\": {\n          \"title\": \"WCP2LoadUrl Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"iframeUrl\": {\n              \"title\": \"iframe URL\",\n              \"type\": \"string\",\n              \"description\": \"A URL which can be used to establish communication with the Desktop Agent, via loading the URL into an iframe and restarting the Web Connection protocol with the iframe as the target.\",\n              \"format\": \"uri\"\n            }\n          },\n          \"required\": [\n            \"iframeUrl\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP3Handshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP3Handshake.schema.json\",\n  \"title\": \"Web Connection Protocol 3 Handshake\",\n  \"description\": \"Handshake message sent by the Desktop Agent to the app (with a MessagePort appended) that should be used for subsequent communication steps.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP3HandshakeBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP3HandshakeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP3Handshake Message Type\",\n          \"const\": \"WCP3Handshake\"\n        },\n        \"payload\": {\n          \"title\": \"WCP3Handshake Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"type\": \"string\",\n              \"description\": \"The version of FDC3 API that the Desktop Agent will provide support for.\"\n            },\n            \"intentResolverUrl\": {\n              \"title\": \"Resolver URL\",\n              \"description\": \"Indicates whether an intent resolver user interface is required and the URL to use to do so. Set to `true` to use the default or `false` to disable the intent resolver (as the Desktop Agent will handle it another way).\",\n              \"oneOf\": [\n                {\n                  \"type\": \"string\",\n                  \"format\": \"uri\"\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"channelSelectorUrl\": {\n              \"title\": \"Channel Selector URL\",\n              \"description\": \"Indicates whether a channel selector user interface is required and the URL to use to do so. Set to `true` to use the default or `false` to disable the channel selector (as the Desktop Agent will handle it another way).\",\n              \"oneOf\": [\n                {\n                  \"type\": \"string\",\n                  \"format\": \"uri\"\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"messageExchangeTimeout\": {\n              \"title\": \"Message Exchange Timeout\",\n              \"description\": \"Indicates a custom timeout (in milliseconds) that should be used for the majority of API message exchanges instead of the default 10,000 millisecond timeout.\",\n              \"type\": \"number\",\n              \"minimum\": 100\n            },\n            \"appLaunchTimeout\": {\n              \"title\": \"App Launch Timeout\",\n              \"description\": \"Indicates a custom timeout (in milliseconds) that should be used for API message exchanges that may involve launching an application, instead of the default 100,000 millisecond timeout.\",\n              \"type\": \"number\",\n              \"minimum\": 15000\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"fdc3Version\",\n            \"intentResolverUrl\",\n            \"channelSelectorUrl\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP4ValidateAppIdentity.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP4ValidateAppIdentity.schema.json\",\n  \"title\": \"Web Connection Protocol 4 Validate App Identity\",\n  \"description\": \"Identity Validation request from an app attempting to connect to a Desktop Agent.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP4ValidateAppIdentityBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP4ValidateAppIdentityBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP4ValidateAppIdentity Message Type\",\n          \"const\": \"WCP4ValidateAppIdentity\"\n        },\n        \"payload\": {\n          \"title\": \"WCP4ValidateAppIdentity Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"identityUrl\": {\n              \"title\": \"Identity URL\",\n              \"description\": \"URL to use for the identity of the application. Desktop Agents MUST validate that the origin of the message matches the URL, but MAY implement custom comparison logic.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"actualUrl\": {\n              \"title\": \"Actual URL\",\n              \"description\": \"The current URL of the page attempting to connect. This may differ from the identityUrl, but the origins MUST match.\",\n              \"type\": \"string\",\n              \"format\": \"uri\"\n            },\n            \"instanceId\": {\n              \"title\": \"instanceId\",\n              \"description\": \"If an application has previously connected to the Desktop Agent, it may specify its prior instance id and associated instance UUID to request the same same instance Id be assigned.\",\n              \"type\": \"string\"\n            },\n            \"instanceUuid\": {\n              \"title\": \"instanceUuid\",\n              \"description\": \"Instance UUID associated with the requested instanceId.\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"identityUrl\", \"actualUrl\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP5ValidateAppIdentityFailedResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP5ValidateAppIdentityFailedResponse.schema.json\",\n  \"title\": \"Web Connection Protocol 5 Validate App Identity Failed Response\",\n  \"description\": \"Message sent by the Desktop Agent to an app if their identity validation fails.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP5ValidateAppIdentityFailedResponseBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP5ValidateAppIdentityFailedResponseBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP5ValidateAppIdentityFailedResponse Message Type\",\n          \"const\": \"WCP5ValidateAppIdentityFailedResponse\"\n        },\n        \"payload\": {\n          \"title\": \"WCP5ValidateAppIdentityFailedResponse Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"message\": {\n              \"title\": \"Identity Validation failed message\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json\",\n  \"title\": \"Web Connection Protocol 5 Validate App Identity Success Response\",\n  \"description\": \"Message sent by the Desktop Agent to an app after successful identity validation.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP5ValidateAppIdentityResponseBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP5ValidateAppIdentityResponseBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP5ValidateAppIdentityResponse Message Type\",\n          \"const\": \"WCP5ValidateAppIdentityResponse\"\n        },\n        \"payload\": {\n          \"title\": \"WCP5ValidateAppIdentityResponse Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"appId\": {\n              \"title\": \"appId\",\n              \"description\": \"The appId that the app's identity was validated against.\",\n              \"type\": \"string\"\n            },\n            \"instanceId\": {\n              \"title\": \"instanceId\",\n              \"description\": \"The instance Id granted to the application by the Desktop Agent.\",\n              \"type\": \"string\"\n            },\n            \"instanceUuid\": {\n              \"title\": \"instanceUuid\",\n              \"description\": \"Instance UUID associated with the instanceId granted, which may be used to retrieve the same instanceId if the app is reloaded or navigates.\",\n              \"type\": \"string\"\n            },\n            \"implementationMetadata\": {\n              \"title\": \"ImplementationMetadata\",\n              \"description\": \"Implementation metadata for the Desktop Agent, which includes an appMetadata element containing a copy of the app's own metadata.\",\n              \"$ref\": \"api.schema.json#/definitions/ImplementationMetadata\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"appId\",\n            \"instanceId\",\n            \"instanceUuid\",\n            \"implementationMetadata\"\n          ]\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/ConnectionStepMeta\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCP6Goodbye.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCP6Goodbye.schema.json\",\n  \"title\": \"Web Connection Protocol 6 Goodbye\",\n  \"description\": \"Goodbye message to be sent to the Desktop Agent when disconnecting (e.g. when closing the window or navigating). Desktop Agents should close the MessagePort after receiving this message, but retain instance details in case the application reconnects (e.g. after a navigation event).\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/WCP6GoodbyeBase\"\n    },\n    {\n      \"$ref\": \"WCPConnectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"WCP6GoodbyeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"WCP6Goodbye Message Type\",\n          \"const\": \"WCP6Goodbye\"\n        },\n        \"meta\": {\n          \"$ref\": \"WCPConnectionStep.schema.json#/$defs/DisconnectStepMeta\"\n        }\n      },\n      \"required\": [ \"type\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/WCPConnectionStep.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/WCPConnectionStep.schema.json\",\n  \"title\": \"Web Connection Protocol Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used during the connection flow for an application to a Desktop Agent in a browser window. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Connection Step Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"WCP1Hello\",\n        \"WCP2LoadUrl\",\n        \"WCP3Handshake\",\n        \"WCP4ValidateAppIdentity\",\n        \"WCP5ValidateAppIdentityFailedResponse\",\n        \"WCP5ValidateAppIdentityResponse\",\n        \"WCP6Goodbye\"\n      ],\n      \"description\": \"Identifies the type of the connection step message.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload, containing data pertaining to this connection step.\",\n      \"additionalProperties\": true\n    },\n    \"meta\": {\n      \"title\": \"Connection Step Metadata\",\n      \"description\": \"Metadata for a Web Connection Protocol message.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"#/$defs/DisconnectStepMeta\"\n        },\n        {\n          \"$ref\": \"#/$defs/ConnectionStepMeta\"\n        }\n      ]\n    }\n  },\n  \"required\": [\n    \"type\",\n    \"meta\"\n  ],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"ConnectionStepMeta\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"connectionAttemptUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ConnectionAttemptUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\n        \"timestamp\",\n        \"connectionAttemptUuid\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"DisconnectStepMeta\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\n        \"timestamp\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addContextListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addContextListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddContextListener Request\",\n\t\"description\": \"A request to add a context listener to a specified Channel OR to the current user channel. Where the listener is added to the current user channel (channelId == null), and this app has already been added to a user channel, client code should make a subsequent request to get the current context of that channel for this listener and then call its handler with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddContextListenerRequestType\": {\n\t\t\t\"title\": \"AddContextListener Request Message Type\",\n\t\t\t\"const\": \"addContextListenerRequest\"\n\t\t},\n\t\t\"AddContextListenerRequestPayload\": {\n\t\t\t\"title\": \"AddContextListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to add the listener to or `null` indicating that it should listen to the current user channel (at the time of broadcast).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of context to listen for OR `null` indicating that it should listen to all context types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\", \"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addContextListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addContextListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddContextListener Response\",\n\t\"description\": \"A response to a addContextListener request. Where the listener was added to the current user channel (channelId == null), and this app has already been added to a user channel, client code should make a subsequent request to get the current context of that channel for this listener and then call its handler with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddContextListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddContextListenerResponseType\": {\n\t\t\t\"title\": \"AddContextListener Response Message Type\",\n\t\t\t\"const\": \"addContextListenerResponse\"\n\t\t},\n\t\t\"AddContextListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddContextListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"AddContextListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddContextListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddEventListener Request\",\n\t\"description\": \"A request to add an event listener for a specified event type to the Desktop Agent.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddEventListenerRequestType\": {\n\t\t\t\"title\": \"AddEventListener Request Message Type\",\n\t\t\t\"const\": \"addEventListenerRequest\"\n\t\t},\n\t\t\"AddEventListenerRequestPayload\": {\n\t\t\t\"title\": \"AddEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"title\": \"Event type\",\n\t\t\t\t\t\"description\": \"The type of the event to be listened to or `null` to listen to all event types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/FDC3EventType\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"type\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddEventListener Response\",\n\t\"description\": \"A response to an addEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddEventListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddEventListenerResponseType\": {\n\t\t\t\"title\": \"AddEventListener Response Message Type\",\n\t\t\t\"const\": \"addEventListenerResponse\"\n\t\t},\n\t\t\"AddEventListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddEventListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"AddEventListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddEventListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addIntentListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addIntentListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddIntentListener Request\",\n\t\"description\": \"A request to add an Intent listener for a specified intent type.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddIntentListenerRequestType\": {\n\t\t\t\"title\": \"AddIntentListener Request Message Type\",\n\t\t\t\"const\": \"addIntentListenerRequest\"\n\t\t},\n\t\t\"AddIntentListenerRequestPayload\": {\n\t\t\t\"title\": \"AddIntentListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent name\",\n\t\t\t\t\t\"description\": \"The name of the intent to listen for.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/addIntentListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/addIntentListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"AddIntentListener Response\",\n\t\"description\": \"A response to a addIntentListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/AddIntentListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"AddIntentListenerResponseType\": {\n\t\t\t\"title\": \"AddIntentListener Response Message Type\",\n\t\t\t\"const\": \"addIntentListenerResponse\"\n\t\t},\n\t\t\"AddIntentListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"AddIntentListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t]\n\t\t},\n\t\t\"AddIntentListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"AddIntentListener Response Error Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/agentEvent.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/agentEvent.schema.json\",\n  \"title\": \"Agent Event Message\",\n  \"type\": \"object\",\n  \"description\": \"A message from a Desktop Agent to an FDC3-enabled app representing an event.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Event Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addEventListenerEvent\",\n        \"broadcastEvent\",\n        \"channelChangedEvent\",\n        \"heartbeatEvent\",\n        \"intentEvent\",\n        \"privateChannelOnAddContextListenerEvent\",\n        \"privateChannelOnDisconnectEvent\",\n        \"privateChannelOnUnsubscribeEvent\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Event Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload contains details of the event that the app is being notified about.\",\n      \"additionalProperties\": true\n    },\n    \"meta\": {\n      \"title\": \"Event Metadata\",\n      \"description\": \"Metadata for messages sent by a Desktop Agent to an app notifying it of an event.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"eventUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/EventUuid\"\n        }\n      },\n      \"required\": [\"timestamp\", \"eventUuid\"],\n      \"additionalProperties\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/api/agentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/agentResponse.schema.json\",\n  \"title\": \"Agent Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A message from a Desktop Agent to an FDC3-enabled app responding to an API call. If the payload contains an `error` property, the request was unsuccessful.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addContextListenerResponse\",\n        \"addEventListenerResponse\",\n        \"addIntentListenerResponse\",\n        \"broadcastResponse\",\n        \"contextListenerUnsubscribeResponse\",\n        \"createPrivateChannelResponse\",\n        \"eventListenerUnsubscribeResponse\",\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"getCurrentChannelResponse\",\n        \"getCurrentContextResponse\",\n        \"getInfoResponse\",\n        \"getOrCreateChannelResponse\",\n        \"getUserChannelsResponse\",\n        \"intentListenerUnsubscribeResponse\",\n        \"intentResultResponse\",\n        \"joinUserChannelResponse\",\n        \"leaveCurrentChannelResponse\",\n        \"openResponse\",\n        \"privateChannelAddEventListenerResponse\",\n        \"privateChannelDisconnectResponse\",\n        \"privateChannelUnsubscribeEventListenerResponse\",\n        \"raiseIntentForContextResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\",\n        \"clearContextResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Payload\",\n      \"type\": \"object\",\n      \"description\": \"A payload for a response to an API call that will contain any return values or an `error` property containing a standardized error message indicating that the request was unsuccessful.\",\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {},\n          \"additionalProperties\": true\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n            }\n          },\n          \"required\": [\n            \"error\"\n          ],\n          \"additionalProperties\": false\n        }\n      ]\n    },\n    \"meta\": {\n      \"title\": \"Agent Response Message Metadata\",\n      \"description\": \"Metadata for messages sent by a Desktop Agent to an app in response to an API call.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"source\": {\n          \"title\": \"Original Source AppIdentifier\",\n          \"description\": \"Field that represents the source application that the request being responded to was received from, for debugging purposes.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\n        \"timestamp\",\n        \"requestUuid\",\n        \"responseUuid\"\n      ],\n      \"additionalProperties\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\n    \"type\",\n    \"payload\",\n    \"meta\"\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/api.schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/api.schema.json\",\n    \"title\": \"FDC3 Desktop Agent API Schemas\",\n    \"definitions\": {\n        \"AppIdentifier\": {\n            \"description\": \"Identifies an application, or instance of an application, and is used to target FDC3 API calls, such as `fdc3.open` or `fdc3.raiseIntent` at specific applications or application instances.\\n\\nWill always include at least an `appId` field, which uniquely identifies a specific app.\\n\\nIf the `instanceId` field is set then the `AppMetadata` object represents a specific instance of the application that may be addressed using that Id.\",\n            \"title\": \"AppIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"Icon\": {\n            \"description\": \"Describes an Icon image that may be used to represent the application.\",\n            \"title\": \"Icon\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The icon url.\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The icon dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Icon media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"Image\": {\n            \"description\": \"Describes an image file, typically a screenshot, that often represents the application in a common usage scenario.\",\n            \"title\": \"Image\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"src\": {\n                    \"description\": \"The image url.\",\n                    \"type\": \"string\",\n                    \"title\": \"src\"\n                },\n                \"size\": {\n                    \"description\": \"The image dimension, formatted as `<height>x<width>`.\",\n                    \"type\": \"string\",\n                    \"title\": \"size\"\n                },\n                \"type\": {\n                    \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\",\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"label\": {\n                    \"description\": \"Caption for the image.\",\n                    \"type\": \"string\",\n                    \"title\": \"label\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"src\"\n            ]\n        },\n        \"AppMetadata\": {\n            \"description\": \"Extends an `AppIdentifier`, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the Desktop Agent connects to.\\n\\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\\n\\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc.\",\n            \"title\": \"AppMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The 'friendly' app name. \\nThis field was used with the `open` and `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier` wth `appId` set. \\nNote that for display purposes the `title` field should be used, if set, in preference to this field.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"version\": {\n                    \"description\": \"The Version of the application.\",\n                    \"type\": \"string\",\n                    \"title\": \"version\"\n                },\n                \"instanceMetadata\": {\n                    \"description\": \"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.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true,\n                    \"title\": \"instanceMetadata\"\n                },\n                \"title\": {\n                    \"description\": \"A more user-friendly application title that can be used to render UI elements.\",\n                    \"type\": \"string\",\n                    \"title\": \"title\"\n                },\n                \"tooltip\": {\n                    \"description\": \"A tooltip for the application that can be used to render UI elements.\",\n                    \"type\": \"string\",\n                    \"title\": \"tooltip\"\n                },\n                \"description\": {\n                    \"description\": \"A longer, multi-paragraph description for the application that could include markup.\",\n                    \"type\": \"string\",\n                    \"title\": \"description\"\n                },\n                \"icons\": {\n                    \"description\": \"A list of icon URLs for the application that can be used to render UI elements.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Icon\"\n                    },\n                    \"title\": \"icons\"\n                },\n                \"screenshots\": {\n                    \"description\": \"Images representing the app in common usage scenarios that can be used to render UI elements.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Image\"\n                    },\n                    \"title\": \"screenshots\"\n                },\n                \"resultType\": {\n                    \"description\": \"The type of output 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 (e.g. \\\"channel<fdc3.instrument>\\\").\",\n                    \"type\": [\n                        \"null\",\n                        \"string\"\n                    ],\n                    \"title\": \"resultType\"\n                },\n                \"appId\": {\n                    \"description\": \"The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\",\n                    \"type\": \"string\",\n                    \"title\": \"appId\"\n                },\n                \"instanceId\": {\n                    \"description\": \"An optional instance identifier, indicating that this object represents a specific instance of the application described.\",\n                    \"type\": \"string\",\n                    \"title\": \"instanceId\"\n                },\n                \"desktopAgent\": {\n                    \"description\": \"The Desktop Agent that the app is available on. Used in Desktop Agent Bridging to identify the Desktop Agent to target.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"appId\"\n            ]\n        },\n        \"IntentMetadata\": {\n            \"description\": \"Metadata describing an Intent.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"The unique name of the intent that can be invoked by the raiseIntent call.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"displayName\": {\n                    \"description\": \"Display name for the intent.\",\n                    \"type\": \"string\",\n                    \"title\": \"displayName\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"name\"\n            ]\n        },\n        \"AppIntent\": {\n            \"description\": \"An interface that relates an intent to apps.\",\n            \"title\": \"AppIntent\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"intent\": {\n                    \"$ref\": \"#/definitions/IntentMetadata\",\n                    \"description\": \"Details of the intent whose relationship to resolving applications is being described.\",\n                    \"title\": \"intent\"\n                },\n                \"apps\": {\n                    \"description\": \"Details of applications that can resolve the intent.\",\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/AppMetadata\"\n                    },\n                    \"title\": \"apps\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"apps\",\n                \"intent\"\n            ]\n        },\n        \"DisplayMetadata\": {\n            \"description\": \"A system channel will be global enough to have a presence across many apps. This gives us some hints\\nto render them in a standard way. It is assumed it may have other properties too, but if it has these,\\nthis is their meaning.\",\n            \"title\": \"DisplayMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"A user-readable name for this channel, e.g: `\\\"Red\\\"`.\",\n                    \"type\": \"string\",\n                    \"title\": \"name\"\n                },\n                \"color\": {\n                    \"description\": \"The color that should be associated within this channel when displaying this channel in a UI, e.g: `0xFF0000`.\",\n                    \"type\": \"string\",\n                    \"title\": \"color\"\n                },\n                \"glyph\": {\n                    \"description\": \"A URL of an image that can be used to display this channel.\",\n                    \"type\": \"string\",\n                    \"title\": \"glyph\"\n                }\n            },\n            \"additionalProperties\": false\n        },\n        \"Channel\": {\n            \"description\": \"Represents a context channel that applications can use to send and receive\\ncontext data.\\n\\nPlease note that There are differences in behavior when you interact with a\\nUser channel via the `DesktopAgent` interface and the `Channel` interface.\\nSpecifically, when 'joining' a User channel or adding a context listener\\nwhen already joined to a channel via the `DesktopAgent` interface, existing\\ncontext (matching the type of the context listener) on the channel is\\nreceived by the context listener immediately. Whereas, when a context\\nlistener is added via the Channel interface, context is not received\\nautomatically, but may be retrieved manually via the `getCurrentContext()`\\nfunction.\",\n            \"title\": \"Channel\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"id\": {\n                    \"description\": \"Constant that uniquely identifies this channel.\",\n                    \"type\": \"string\",\n                    \"title\": \"id\"\n                },\n                \"type\": {\n                    \"description\": \"Uniquely defines each channel type.\\nCan be \\\"user\\\", \\\"app\\\" or \\\"private\\\".\",\n                    \"enum\": [\n                        \"app\",\n                        \"private\",\n                        \"user\"\n                    ],\n                    \"type\": \"string\",\n                    \"title\": \"type\"\n                },\n                \"displayMetadata\": {\n                    \"description\": \"Channels may be visualized and selectable by users. DisplayMetadata may be used to provide hints on how to see them.\\nFor App channels, displayMetadata would typically not be present.\",\n                    \"$ref\": \"#/definitions/DisplayMetadata\",\n                    \"title\": \"displayMetadata\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"id\",\n                \"type\"\n            ]\n        },\n        \"ContextMetadata\": {\n            \"description\": \"Metadata relating to a context or intent and context received through the\\n`addContextListener` and `addIntentListener` functions.\",\n            \"title\": \"ContextMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that sent the context and/or intent.\",\n                    \"title\": \"source\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"source\"\n            ]\n        },\n        \"DesktopAgentIdentifier\": {\n            \"description\": \"Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios\\nwhere a request needs to be directed to a Desktop Agent rather than a specific app, or a\\nresponse message is returned by the Desktop Agent (or more specifically its resolver)\\nrather than a specific app. Used as a substitute for `AppIdentifier` in cases where no\\napp details are available or are appropriate.\",\n            \"title\": \"DesktopAgentIdentifier\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"desktopAgent\": {\n                    \"description\": \"Used in Desktop Agent Bridging to attribute or target a message to a\\nparticular Desktop Agent.\",\n                    \"type\": \"string\",\n                    \"title\": \"desktopAgent\"\n                }\n            },\n            \"unevaluatedProperties\": false,\n            \"required\": [\n                \"desktopAgent\"\n            ]\n        },\n        \"OpenError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`).\",\n            \"title\": \"OpenError\",\n            \"enum\": [\n                \"AppNotFound\",\n                \"AppTimeout\",\n                \"DesktopAgentNotFound\",\n                \"ErrorOnLaunch\",\n                \"MalformedContext\",\n                \"ResolverUnavailable\",\n                \"ApiTimeout\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResolveError\": {\n            \"description\": \"Constants representing the errors that can be encountered when calling the `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`).\",\n            \"title\": \"ResolveError\",\n            \"enum\": [\n                \"DesktopAgentNotFound\",\n                \"IntentDeliveryFailed\",\n                \"MalformedContext\",\n                \"NoAppsFound\",\n                \"ResolverTimeout\",\n                \"ResolverUnavailable\",\n                \"TargetAppUnavailable\",\n                \"TargetInstanceUnavailable\",\n                \"UserCancelledResolution\",\n                \"ApiTimeout\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ResultError\": {\n            \"title\": \"ResultError\",\n            \"enum\": [\n                \"IntentHandlerRejected\",\n                \"NoResultReturned\",\n                \"ApiTimeout\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ChannelError\": {\n            \"title\": \"ChannelError\",\n            \"enum\": [\n                \"AccessDenied\",\n                \"CreationFailed\",\n                \"MalformedContext\",\n                \"NoChannelFound\",\n                \"ApiTimeout\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BridgingError\": {\n            \"title\": \"BridgingError\",\n            \"enum\": [\n                \"AgentDisconnected\",\n                \"NotConnectedToBridge\",\n                \"ResponseToBridgeTimedOut\",\n                \"MalformedMessage\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BaseImplementationMetadata\": {\n            \"description\": \"Metadata relating to the FDC3 Desktop Agent implementation and its provider.\",\n            \"title\": \"BaseImplementationMetadata\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"fdc3Version\": {\n                    \"description\": \"The version number of the FDC3 specification that the implementation provides.\\nThe string must be a numeric semver version, e.g. 1.2 or 1.2.1.\",\n                    \"type\": \"string\",\n                    \"title\": \"fdc3Version\"\n                },\n                \"provider\": {\n                    \"description\": \"The name of the provider of the Desktop Agent implementation (e.g. Finsemble, Glue42, OpenFin etc.).\",\n                    \"type\": \"string\",\n                    \"title\": \"provider\"\n                },\n                \"providerVersion\": {\n                    \"description\": \"The version of the provider of the Desktop Agent implementation (e.g. 5.3.0).\",\n                    \"type\": \"string\",\n                    \"title\": \"providerVersion\"\n                },\n                \"optionalFeatures\": {\n                    \"description\": \"Metadata indicating whether the Desktop Agent implements optional features of\\nthe Desktop Agent API.\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"OriginatingAppMetadata\": {\n                            \"description\": \"Used to indicate whether the exposure of 'originating app metadata' for\\ncontext and intent messages is supported by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"OriginatingAppMetadata\"\n                        },\n                        \"UserChannelMembershipAPIs\": {\n                            \"description\": \"Used to indicate whether the optional `fdc3.joinUserChannel`,\\n`fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\\nthe Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"UserChannelMembershipAPIs\"\n                        },\n                        \"DesktopAgentBridging\": {\n                            \"description\": \"Used to indicate whether the experimental Desktop Agent Bridging\\nfeature is implemented by the Desktop Agent.\",\n                            \"type\": \"boolean\",\n                            \"title\": \"DesktopAgentBridging\"\n                        }\n                    },\n                    \"additionalProperties\": false,\n                    \"required\": [\n                        \"DesktopAgentBridging\",\n                        \"OriginatingAppMetadata\",\n                        \"UserChannelMembershipAPIs\"\n                    ],\n                    \"title\": \"optionalFeatures\"\n                }\n            },\n            \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\"\n            ]\n        },\n        \"ImplementationMetadata\": {\n            \"description\": \"Includes Metadata for the current application.\",\n            \"title\": \"ImplementationMetadata\",\n            \"type\": \"object\",\n            \"allOf\": [\n                {\n                    \"$ref\": \"#/definitions/BaseImplementationMetadata\"\n                },\n                {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"appMetadata\": {\n                            \"$ref\": \"#/definitions/AppMetadata\",\n                            \"description\": \"The calling application instance's own metadata, according to the Desktop Agent (MUST include at least the `appId` and `instanceId`).\",\n                            \"title\": \"appMetadata\"\n                        }\n                    }\n                }\n            ],\n            \"properties\": {\n                \"fdc3Version\": true,\n                \"provider\": true,\n                \"providerVersion\": true,\n                \"optionalFeatures\": true,\n                \"appMetadata\": true\n            },\n            \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\",\n                \"appMetadata\"\n            ],\n            \"additionalProperties\": false\n        },\n        \"IntentResolution\": {\n            \"description\": \"IntentResolution provides a standard format for data returned upon resolving an intent.\\n\\n```javascript\\n//resolve a \\\"Chain\\\" type intent\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\n\\n//resolve a \\\"Client-Service\\\" type intent with a data response or a Channel\\nlet resolution = await agent.raiseIntent(\\\"intentName\\\", context);\\ntry {\\n\\t   const result = await resolution.getResult();\\n    if (result && result.broadcast) {\\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\\n    } else if (result){\\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\\n    } else {\\n        console.error(`${resolution.source} didn't return data`\\n    }\\n} catch(error) {\\n    console.error(`${resolution.source} returned an error: ${error}`);\\n}\\n\\n// Use metadata about the resolving app instance to target a further intent\\nawait agent.raiseIntent(\\\"intentName\\\", context, resolution.source);\\n```\",\n            \"title\": \"IntentResolution\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"source\": {\n                    \"$ref\": \"#/definitions/AppIdentifier\",\n                    \"description\": \"Identifier for the app instance that was selected (or started) to resolve the intent.\\n`source.instanceId` MUST be set, indicating the specific app instance that\\nreceived the intent.\",\n                    \"title\": \"source\"\n                },\n                \"intent\": {\n                    \"description\": \"The intent that was raised. May be used to determine which intent the user\\nchose in response to `fdc3.raiseIntentForContext()`.\",\n                    \"type\": \"string\",\n                    \"title\": \"intent\"\n                }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\n                \"intent\",\n                \"source\"\n            ]\n        },\n        \"IntentResult\": {\n            \"title\": \"IntentResult\",\n            \"anyOf\": [\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Context\",\n                    \"properties\": {\n                        \"context\": {\n                            \"$ref\": \"../context/context.schema.json\"\n                        }\n                    },\n                    \"required\": [\n                        \"context\"\n                    ],\n                    \"additionalProperties\": false\n                },\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Channel\",\n                    \"properties\": {\n                        \"channel\": {\n                            \"$ref\": \"#/definitions/Channel\"\n                        }\n                    },\n                    \"required\": [\n                        \"channel\"\n                    ],\n                    \"additionalProperties\": false\n                },\n                {\n                    \"type\": \"object\",\n                    \"title\": \"IntentResult Void\",\n                    \"properties\": {},\n                    \"additionalProperties\": false\n                }\n            ]\n        },\n        \"FDC3EventType\": {\n            \"title\": \"FDC3 Event Type\",\n            \"description\": \"The type of a (non-context and non-intent) event that may be received via the FDC3 API's addEventListener function.\",\n            \"type\": \"string\",\n            \"enum\": [\n                \"USER_CHANNEL_CHANGED\"\n            ]\n        },\n        \"FDC3Event\": {\n            \"title\": \"FDC3 Event\",\n            \"description\": \"An event object received via the FDC3 API's addEventListener function. Will always include both type and details, which describe type of the event and any additional details respectively.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"type\": {\n                    \"$ref\": \"#/definitions/FDC3EventType\"\n                },\n                \"details\": {\n                    \"title\": \"Event details\",\n                    \"description\": \"Additional details of the event, such as the `currentChannelId` for a CHANNEL_CHANGED event.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true\n                }\n            },\n            \"required\":[\"type\",\"details\"],\n            \"additionalProperties\": false\n        },\n        \"PrivateChannelEventType\": {\n            \"title\": \"PrivateChannel Event Type\",\n            \"description\": \"Type defining valid type strings for Private Channel events.\",\n            \"type\": \"string\",\n            \"enum\": [\n                \"addContextListener\",\n                \"unsubscribe\",\n                \"disconnect\"\n            ]\n        },\n        \"PrivateChannelEvent\": {\n            \"description\": \"Type defining the format of event objects that may be received via a PrivateChannel's addEventListener function.\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"type\": {\n                    \"$ref\": \"#/definitions/PrivateChannelEventType\"\n                },\n                \"details\": {\n                    \"title\": \"Event details\",\n                    \"description\": \"Additional details of the event, such as the `currentChannelId` for a CHANNEL_CHANGED event.\",\n                    \"type\": \"object\",\n                    \"additionalProperties\": true\n                }\n            },\n            \"required\":[\"type\",\"details\"],\n            \"additionalProperties\": false\n        }\n    }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/appRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/appRequest.schema.json\",\n  \"title\": \"App Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message from an FDC3-enabled app to a Desktop Agent.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Request Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"addContextListenerRequest\",\n        \"addEventListenerRequest\",\n        \"addIntentListenerRequest\",\n        \"broadcastRequest\",\n        \"contextListenerUnsubscribeRequest\",\n        \"createPrivateChannelRequest\",\n        \"eventListenerUnsubscribeRequest\",\n        \"findInstancesRequest\",\n        \"findIntentRequest\",\n        \"findIntentsByContextRequest\",\n        \"getAppMetadataRequest\",\n        \"getCurrentChannelRequest\",\n        \"getCurrentContextRequest\",\n        \"getInfoRequest\",\n        \"getOrCreateChannelRequest\",\n        \"getUserChannelsRequest\",\n        \"heartbeatAcknowledgementRequest\",\n        \"intentListenerUnsubscribeRequest\",\n        \"intentResultRequest\",\n        \"joinUserChannelRequest\",\n        \"leaveCurrentChannelRequest\",\n        \"openRequest\",\n        \"privateChannelAddEventListenerRequest\",\n        \"privateChannelDisconnectRequest\",\n        \"privateChannelUnsubscribeEventListenerRequest\",\n        \"raiseIntentForContextRequest\",\n        \"raiseIntentRequest\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Request payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"title\": \"Request Metadata\",\n      \"description\": \"Metadata for a request message sent by an FDC3-enabled app to a Desktop Agent.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Source AppIdentifier\",\n          \"description\": \"Field that represents the source application that a request or response was received from. Please note that this may be set by an app or Desktop Agent proxy for debugging purposes but a Desktop Agent should make its own determination of the source of a message to avoid spoofing.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/api/broadcastEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/broadcastEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"broadcast Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that context has been broadcast on a channel it is listening to, or specifically to this app instance if it was launched via `fdc3.open` and context was passed.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastEventType\": {\n\t\t\t\"title\": \"Broadcast Event Message Type\",\n\t\t\t\"const\": \"broadcastEvent\"\n\t\t},\n\t\t\"BroadcastEventPayload\": {\n\t\t\t\"title\": \"broadcast Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the channel that the broadcast was sent on. May be `null` if the context is being broadcast due to a call `fdc3.open` that passed context.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object that was broadcast.\"\n\t\t\t\t},\n\t\t\t\t\"originatingApp\": {\n\t\t\t\t\t\"title\": \"Originating AppIdentifier\",\n\t\t\t\t\t\"description\": \"Details of the application instance that broadcast the context.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\", \"context\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/broadcastRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/broadcastRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Broadcast Request\",\n\t\"description\": \"A request to broadcast context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastRequestType\": {\n\t\t\t\"title\": \"Broadcast Request Message Type\",\n\t\t\t\"const\": \"broadcastRequest\"\n\t\t},\n\t\t\"BroadcastRequestPayload\": {\n\t\t\t\"title\": \"broadcast Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the Channel that the broadcast was sent on.\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object that is to be broadcast.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"channelId\",\n\t\t\t\t\"context\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/broadcastResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/broadcastResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Broadcast Response\",\n\t\"description\": \"A response to a request to broadcast context on a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/BroadcastResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"BroadcastResponseType\": {\n\t\t\t\"title\": \"Broadcast Response Message Type\",\n\t\t\t\"const\": \"broadcastResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/channelChangedEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/channelChangedEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"channelChanged Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that its current user channel has changed.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ChannelChangedEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ChannelChangedEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ChannelChangedEventType\": {\n\t\t\t\"title\": \"ChannelChanged Event Message Type\",\n\t\t\t\"const\": \"channelChangedEvent\"\n\t\t},\n\t\t\"ChannelChangedEventPayload\": {\n\t\t\t\"title\": \"channelChanged Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"newChannelId\": {\n\t\t\t\t\t\"title\": \"New Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the channel that the app was added to or `null` if it was removed from a channel.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"newChannelId\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/common.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/common.schema.json\",\n  \"title\": \"Common definitions\",\n  \"type\": \"object\",\n  \"description\": \"Common definitions that are referenced in the API and Bridging Wire Protocol schemas.\",\n  \"$defs\": {\n    \"ConnectionAttemptUuid\": {\n      \"title\": \"Connection Attempt UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a for an attempt to connect to a Desktop Agent. A Unique UUID should be used in the first (WCP1Hello) message and should be quoted in all subsequent messages to link them to the same connection attempt.\"\n    },\n    \"RequestUuid\": {\n      \"title\": \"Request UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a request or event message. Required in all message types.\"\n    },\n    \"ResponseUuid\": {\n      \"title\": \"Response UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a response to a specific message and must always be accompanied by a RequestUuid.\"\n    },\n    \"EventUuid\": {\n      \"title\": \"Event UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for an event message sent from a Desktop Agent to an app.\"\n    },\n    \"ListenerUuid\": {\n      \"title\": \"Listener UUID\",\n      \"type\": \"string\",\n      \"description\": \"Unique identifier for a `listener` object returned by a Desktop Agent to an app in response to addContextListener, addIntentListener or one of the PrivateChannel event listeners and used to identify it in messages (e.g. when unsubscribing).\"\n    },\n    \"Timestamp\": {\n      \"title\": \"Timestamp\",\n      \"type\": \"string\",\n      \"format\": \"date-time\",\n      \"description\": \"Timestamp at which the message was generated.\"\n    },\n    \"ErrorMessages\": {\n      \"oneOf\": [\n        {\n          \"$ref\": \"api.schema.json#/definitions/ChannelError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/OpenError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/ResolveError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/ResultError\"\n        },\n        {\n          \"$ref\": \"api.schema.json#/definitions/BridgingError\"\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/contextListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/contextListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"ContextListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ContextListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"contextListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"ContextListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/contextListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/contextListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"ContextListenerUnsubscribe Response\",\n\t\"description\": \"A response to a contextListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/ContextListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"ContextListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"ContextListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"contextListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/createPrivateChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/createPrivateChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"CreatePrivateChannel Request\",\n\t\"description\": \"Request to return a Channel with an auto-generated identity that is intended for private communication between applications.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"CreatePrivateChannelRequestType\": {\n\t\t\t\"title\": \"CreatePrivateChannel Request Message Type\",\n\t\t\t\"const\": \"createPrivateChannelRequest\"\n\t\t},\n\t\t\"CreatePrivateChannelRequestPayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/createPrivateChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/createPrivateChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"CreatePrivateChannel Response\",\n\t\"description\": \"A response to a createPrivateChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/CreatePrivateChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"CreatePrivateChannelResponseType\": {\n\t\t\t\"title\": \"CreatePrivateChannel Response Message Type\",\n\t\t\t\"const\": \"createPrivateChannelResponse\"\n\t\t},\n\t\t\"CreatePrivateChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannel\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"CreatePrivateChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"CreatePrivateChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/eventListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/eventListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"EventListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe an event listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"EventListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"eventListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"EventListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/eventListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/eventListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"EventListenerUnsubscribe Response\",\n\t\"description\": \"A response to an eventListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/EventListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"EventListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"EventListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"eventListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceChannelSelected.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceChannelSelected.schema.json\",\n  \"title\": \"Fdc3 UserInterface Channel Selected\",\n  \"description\": \"Message from a channel selector UI to the DA proxy sent when the channel selection changes.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceChannelSelectedBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceChannelSelectedBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface ChannelSelected Message Type\",\n          \"const\": \"Fdc3UserInterfaceChannelSelected\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface ChannelSelected Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"selected\": {\n              \"title\": \"Selected Channel\",\n              \"description\": \"The id of the channel that should be currently selected, or `null` if none should be selected.\",\n              \"oneOf\": [\n                {\"type\": \"string\"}, {\"type\": \"null\"}\n              ]\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"selected\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceChannels.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceChannels.schema.json\",\n  \"title\": \"Fdc3 UserInterface Channels\",\n  \"description\": \"Setup message sent by the DA proxy code in getAgent() to a channel selector UI in an iframe with the channel definitions and current channel selection.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceChannelsBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceChannelsBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Channels Message Type\",\n          \"const\": \"Fdc3UserInterfaceChannels\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Channels Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"userChannels\": {\n              \"title\": \"User Channels\",\n              \"description\": \"User Channel definitions.```````s\",\n              \"type\": \"array\",\n              \"items\": {\n                \"$ref\": \"api.schema.json#/definitions/Channel\"\n              }\n            },\n            \"selected\": {\n              \"title\": \"Selected Channel\",\n              \"description\": \"The id of the channel that should be currently selected, or `null` if none should be selected.\",\n              \"oneOf\": [\n                {\"type\": \"string\"}, {\"type\": \"null\"}\n              ]\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"userChannels\", \"selected\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceDrag.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceDrag.schema.json\",\n  \"title\": \"Fdc3 UserInterface Drag\",\n  \"description\": \"Message from a UI iframe to the DA proxy (setup by `getAgent()`) indicating that the user is dragging the UI to a new location and providing the offset to apply to the location. The DA proxy implementation should limit the location to the current bounds of the window's viewport.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceDragBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceDragBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Drag Message Type\",\n          \"const\": \"Fdc3UserInterfaceDrag\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Drag Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"mouseOffsets\": {\n              \"title\": \"Mouse Offsets\",\n              \"description\": \"The offset to move the frame by.\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"x\": {\n                  \"type\": \"integer\"\n                },\n                \"y\": {\n                  \"type\": \"integer\"\n                }\n              },\n              \"required\": [\"x\", \"y\"],\n              \"additionalProperties\": false\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"mouseOffsets\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceHandshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceHandshake.schema.json\",\n  \"title\": \"Fdc3 UserInterface Handshake\",\n  \"description\": \"Handshake message sent back to a user interface from the DA proxy code (setup by `getAgent()`) over the `MessagePort` provided in the preceding Fdc3UserInterfaceHello message, confirming that it is listening to the `MessagePort` for further communication.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceHandshakeBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceHandshakeBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Handshake Message Type\",\n          \"const\": \"Fdc3UserInterfaceHandshake\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Handshake Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"fdc3Version\": {\n              \"title\": \"FDC3 version\",\n              \"type\": \"string\",\n              \"description\": \"The version of FDC3 API that the Desktop Agent will provide support for.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"fdc3Version\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceHello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceHello.schema.json\",\n  \"title\": \"Fdc3 UserInterface Hello\",\n  \"description\": \"Hello message sent by a UI to the Desktop Agent proxy setup by `getAgent()` to indicate it is ready to communicate, containing initial CSS to set on the iframe, and including an appended `MessagePort` to be used for further communication.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceHelloBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceHelloBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Hello Message Type\",\n          \"const\": \"Fdc3UserInterfaceHello\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Hello Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"implementationDetails\": {\n              \"title\": \"Implementation Details\",\n              \"type\": \"string\",\n              \"description\": \"Details about the UI implementation, such as vendor and version, for logging purposes.\"\n            },\n            \"initialCSS\": {\n              \"title\": \"Initial CSS\",\n              \"type\": \"object\",\n              \"description\": \"A constrained set of styling properties that should be set on the user interface before it is displayed. Note `position` cannot be specified and should always be set to `fixed`.\",\n              \"properties\": {\n                \"height\": {\"type\": \"string\", \"title\": \"height\", \"description\": \"The initial height of the iframe.\"},\n                \"width\": {\"type\": \"string\", \"title\": \"width\", \"description\": \"The initial width of the iframe.\"},\n                \"zIndex\": {\"type\": \"string\", \"title\": \"zIndex\", \"description\": \"The initial zindex to apply to the iframe.\"},\n                \"left\": {\"type\": \"string\", \"title\": \"left\", \"description\": \"The initial left property to apply to the iframe.\"},\n                \"top\": {\"type\": \"string\", \"title\": \"top\", \"description\": \"The initial top property to apply to the iframe.\"},\n                \"bottom\": {\"type\": \"string\", \"title\": \"bottom\", \"description\": \"The initial bottom property to apply to the iframe.\"},\n                \"right\": {\"type\": \"string\", \"title\": \"right\", \"description\": \"The initial right property to apply to the iframe.\"},\n                \"transition\": {\"type\": \"string\", \"title\": \"transition\", \"description\": \"The transition property to apply to the iframe.\"},\n                \"maxHeight\": {\"type\": \"string\", \"title\": \"maxHeight\", \"description\": \"The maximum height to apply to the iframe.\"},\n                \"maxWidth\": {\"type\": \"string\", \"title\": \"maxWidth\", \"description\": \"The maximum with to apply to the iframe.\"}\n              },\n              \"required\": []\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"implementationDetails\",\"initialCSS\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceMessage.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceMessage.schema.json\",\n  \"title\": \"Fdc3 UserInterface Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used to communicate with user interface frames injected by `getAgent()` for displaying UI elements such as the intent resolver or channel selector. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Fdc3 UserInterface Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"Fdc3UserInterfaceHello\",\n        \"Fdc3UserInterfaceHandshake\",\n        \"Fdc3UserInterfaceRestyle\",\n        \"Fdc3UserInterfaceDrag\",\n        \"Fdc3UserInterfaceResolve\",\n        \"Fdc3UserInterfaceResolveAction\",\n        \"Fdc3UserInterfaceChannels\",\n        \"Fdc3UserInterfaceChannelSelected\"\n      ],\n      \"description\": \"Identifies the type of the message to or from the user interface frame.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload.\",\n      \"additionalProperties\": true\n    }\n  },\n  \"required\": [\n    \"type\"\n  ],\n  \"additionalProperties\": false\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceResolve.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceResolve.schema.json\",\n  \"title\": \"Fdc3 UserInterface Resolve\",\n  \"description\": \"Setup message sent by the DA proxy code in getAgent() to an intent resolver UI with the resolver data to setup the UI.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceResolveBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Resolve Message Type\",\n          \"const\": \"Fdc3UserInterfaceResolve\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Resolve Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\"\n            },\n            \"appIntents\": {\n              \"title\": \"Resolution options\",\n              \"type\": \"array\",\n              \"description\": \"An array of AppIntent objects defining the resolution options.\",\n              \"items\": {\n                \"$ref\": \"api.schema.json#/definitions/AppIntent\"\n              },\n              \"additionalProperties\": false\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"context\", \"appIntents\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceResolveAction.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceResolveAction.schema.json\",\n  \"title\": \"Fdc3 UserInterface Resolve Action\",\n  \"description\": \"Message from an intent resolver UI to DA proxy code in getAgent() reporting a user action.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveActionBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceResolveActionBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface ResolveAction Message Type\",\n          \"const\": \"Fdc3UserInterfaceResolveAction\"\n        },\n        \"payload\": {\n          \"oneOf\": [\n            { \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveActionPayload\"},\n            { \"$ref\": \"#/$defs/Fdc3UserInterfaceResolveCancelPayload\"}\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"Fdc3UserInterfaceResolveActionPayload\": {\n      \"title\": \"Fdc3 UserInterface Resolve Action Payload\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"intent\": {\n          \"title\": \"Intent name\",\n          \"type\": \"string\",\n          \"description\": \"The intent resolved.\"\n        },\n        \"appIdentifier\": {\n          \"title\": \"AppIdentifier\",\n          \"description\": \"The App resolution option chosen.\",\n          \"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n        },\n        \"action\": {\n          \"oneOf\": [\n            {\n              \"type\": \"string\",\n              \"const\": \"hover\"\n            },\n            {\n              \"type\": \"string\",\n              \"const\": \"click\"\n            }\n          ]\n        }\n      },\n      \"required\": [\n        \"intent\",\n        \"appIdentifier\",\n        \"action\"\n      ],\n      \"additionalProperties\": false\n    },\n    \"Fdc3UserInterfaceResolveCancelPayload\": {\n      \"title\": \"Fdc3 UserInterface Resolve Cancel Payload\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"action\": {\n          \"type\": \"string\",\n          \"const\": \"cancel\"\n        }\n      },\n      \"required\": [\n        \"action\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/fdc3UserInterfaceRestyle.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/api/fdc3UserInterfaceRestyle.schema.json\",\n  \"title\": \"Fdc3 UserInterface Restyle\",\n  \"description\": \"Message from a UI frame to the DA proxy code (setup by `getAgent()`) with updated styling information to apply to it. Can be used to implement a pop-open or close interaction or other transition needed by a UI implementation.\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/Fdc3UserInterfaceRestyleBase\"\n    },\n    {\n      \"$ref\": \"fdc3UserInterfaceMessage.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"Fdc3UserInterfaceRestyleBase\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Fdc3 UserInterface Restyle Message Type\",\n          \"const\": \"Fdc3UserInterfaceRestyle\"\n        },\n        \"payload\": {\n          \"title\": \"Fdc3 UserInterface Restyle Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"updatedCSS\": {\n              \"title\": \"Updated CSS\",\n              \"type\": \"object\",\n              \"description\": \"A constrained set of styling properties that should be applied to the frame. Note `position` cannot be set, and should always be `fixed`.\",\n              \"properties\": {\n                \"height\": {\"type\": \"string\", \"title\": \"height\", \"description\": \"The updated height of the iframe.\"},\n                \"width\": {\"type\": \"string\", \"title\": \"width\", \"description\": \"The updated width of the iframe.\"},\n                \"zIndex\": {\"type\": \"string\", \"title\": \"zIndex\", \"description\": \"The updated zIndex to apply to the iframe.\"},\n                \"left\": {\"type\": \"string\", \"title\": \"left\", \"description\": \"The initial left property to apply to the iframe.\"},\n                \"top\": {\"type\": \"string\", \"title\": \"top\", \"description\": \"The initial top property to apply to the iframe.\"},\n                \"bottom\": {\"type\": \"string\", \"title\": \"bottom\", \"description\": \"The initial bottom property to apply to the iframe.\"},\n                \"right\": {\"type\": \"string\", \"title\": \"right\", \"description\": \"The initial right property to apply to the iframe.\"},\n                \"transition\": {\"type\": \"string\", \"title\": \"transition\", \"description\": \"The updated transition property to apply to the iframe.\"},\n                \"maxHeight\": {\"type\": \"string\", \"title\": \"maxHeight\", \"description\": \"The updated maximum height to apply to the iframe.\"},\n                \"maxWidth\": {\"type\": \"string\", \"title\": \"maxWidth\", \"description\": \"The updated maximum with to apply to the iframe.\"}\n              },\n              \"required\": []\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"updatedCSS\"]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}\n\n"
  },
  {
    "path": "website/static/schemas/2.2/api/findInstancesRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findInstancesRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindInstances Request\",\n\t\"description\": \"A request for details of instances of a particular app.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindInstancesRequestType\": {\n\t\t\t\"title\": \"FindInstances Request Message Type\",\n\t\t\t\"const\": \"findInstancesRequest\"\n\t\t},\n\t\t\"FindInstancesRequestPayload\": {\n\t\t\t\"type\": \"object\",\n\t\t\t\"title\": \"FindInstances Request Payload\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"app\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/findInstancesResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findInstancesResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindInstances Response\",\n\t\"description\": \"A response to a findInstances request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindInstancesErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindInstancesResponseType\": {\n\t\t\t\"title\": \"FindInstances Response Message Type\",\n\t\t\t\"const\": \"findInstancesResponse\"\n\t\t},\n\t\t\"FindInstancesSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindInstances Response Message Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"description\": \"The message payload contains a flag indicating whether the API call was successful, plus any return values for the FDC3 API function called, or indicating that the request resulted in an error and including a standardized error message.\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIdentifiers\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppMetadata\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIdentifiers\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindInstancesErrorResponsePayload\": {\n\t\t\t\"title\": \"FindInstances Error Response Message Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"findInstances Errors\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/findIntentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findIntentRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntent Request\",\n\t\"description\": \"A request for details of apps available to resolve a particular intent and context pair.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentRequestType\": {\n\t\t\t\"title\": \"FindIntent Request Message Type\",\n\t\t\t\"const\": \"findIntentRequest\"\n\t\t},\n\t\t\"FindIntentRequestPayload\": {\n\t\t\t\"title\": \"FindIntent Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent name\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"title\": \"Context argument\",\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"resultType\": {\n\t\t\t\t\t\"title\": \"Result type argument\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/findIntentResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findIntentResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntent Response\",\n\t\"description\": \"A response to a findIntent request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentResponseType\": {\n\t\t\t\"title\": \"FindIntent Response Message Type\",\n\t\t\t\"const\": \"findIntentResponse\"\n\t\t},\n\t\t\"FindIntentSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindIntent Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntent\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntent\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindIntentErrorResponsePayload\": {\n\t\t\t\"title\": \"FindIntent Response Error Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"findIntent Errors\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/findIntentsByContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findIntentsByContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntentsByContext Request\",\n\t\"description\": \"A request for details of intents and apps available to resolve them for a particular context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentsByContextRequestType\": {\n\t\t\t\"title\": \"FindIntentsByContext Request Message Type\",\n\t\t\t\"const\": \"findIntentsByContextRequest\"\n\t\t},\n\t\t\"FindIntentsByContextRequestPayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"resultType\": {\n\t\t\t\t  \"title\": \"Result type argument\",\n\t\t\t\t  \"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/findIntentsByContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/findIntentsByContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"FindIntentsByContext Response\",\n\t\"description\": \"A response to a findIntentsByContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/FindIntentsByContextErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"FindIntentsByContextResponseType\": {\n\t\t\t\"title\": \"FindIntentsByContext Response Message Type\",\n\t\t\t\"const\": \"findIntentsByContextResponse\"\n\t\t},\n\t\t\"FindIntentsByContextSuccessResponsePayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntents\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntents\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"FindIntentsByContextErrorResponsePayload\": {\n\t\t\t\"title\": \"FindIntentsByContext Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"FindIntentsByContext Error Message\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getAppMetadataRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getAppMetadataRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetAppMetadata Request\",\n\t\"description\": \"A request for metadata about an app.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetAppMetadataRequestType\": {\n\t\t\t\"title\": \"GetAppMetadata Request Message Type\",\n\t\t\t\"const\": \"getAppMetadataRequest\"\n\t\t},\n\t\t\"GetAppMetadataRequestPayload\": {\n\t\t\t\"title\": \"GetAppMetadata Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"app\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getAppMetadataResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getAppMetadataResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetAppMetadata Response\",\n\t\"description\": \"A response to a getAppMetadata request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetAppMetadataErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetAppMetadataResponseType\": {\n\t\t\t\"title\": \"GetAppMetadata Response Message Type\",\n\t\t\t\"const\": \"getAppMetadataResponse\"\n\t\t},\n\t\t\"GetAppMetadataSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetAppMetadata Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appMetadata\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppMetadata\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appMetadata\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetAppMetadataErrorResponsePayload\": {\n\t\t\t\"title\": \"GetAppMetadata Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"GetAppMetadata Error Message\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getCurrentChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getCurrentChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentChannel Request\",\n\t\"description\": \"A request to return the Channel object for the current User channel membership. Returns `null` if the app is not joined to a channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentChannelRequestType\": {\n\t\t\t\"title\": \"GetCurrentChannel Request Message Type\",\n\t\t\t\"const\": \"getCurrentChannelRequest\"\n\t\t},\n\t\t\"GetCurrentChannelRequestPayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getCurrentChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getCurrentChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentChannel Response\",\n\t\"description\": \"A response to a getCurrentChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentChannelResponseType\": {\n\t\t\t\"title\": \"GetCurrentChannel Response Message Type\",\n\t\t\t\"const\": \"getCurrentChannelResponse\"\n\t\t},\n\t\t\"GetCurrentChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channel\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{ \"$ref\": \"api.schema.json#/definitions/Channel\" },\n\t\t\t\t\t\t{ \"type\": \"null\" }\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"channel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetCurrentChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getCurrentContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getCurrentContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentContext Request\",\n\t\"description\": \"A request to return the current context (either of a specified type or most recent broadcast) of a specified Channel. Returns `null` if no context (of the requested type if one was specified) is available in the channel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentContextRequestType\": {\n\t\t\t\"title\": \"GetCurrentContext Request Message Type\",\n\t\t\t\"const\": \"getCurrentContextRequest\"\n\t\t},\n\t\t\"GetCurrentContextRequestPayload\": {\n\t\t\t\"title\": \"GetCurrentContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to return the current context of.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of context to return for OR `null` indicating that the most recently broadcast context on the channel should be returned.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"channelId\", \"contextType\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getCurrentContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getCurrentContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetCurrentContext Response\",\n\t\"description\": \"A response to a getCurrentContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetCurrentContextErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetCurrentContextResponseType\": {\n\t\t\t\"title\": \"GetCurrentContext Response Message Type\",\n\t\t\t\"const\": \"getCurrentContextResponse\"\n\t\t},\n\t\t\"GetCurrentContextSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentContext Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"title\": \"Current Context\",\n\t\t\t\t\t\"description\": \"The most recently broadcast context object (of the specified type, if one was specified), or `null` if none was available in the channel.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{ \"$ref\": \"../context/context.schema.json\" },\n\t\t\t\t\t\t{ \"type\": \"null\" }\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetCurrentContextErrorResponsePayload\": {\n\t\t\t\"title\": \"GetCurrentContext Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getInfoRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getInfoRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetInfo Request\",\n\t\"description\": \"Request to retrieve information about the FDC3 Desktop Agent implementation and the metadata of the calling application according to the Desktop Agent.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetInfoRequestType\": {\n\t\t\t\"title\": \"GetInfo Request Message Type\",\n\t\t\t\"const\": \"getInfoRequest\"\n\t\t},\n\t\t\"GetInfoRequestPayload\": {\n\t\t\t\"title\": \"GetInfo Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getInfoResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getInfoResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetInfo Response\",\n\t\"description\": \"A response to a getInfo request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetInfoErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetInfoResponseType\": {\n\t\t\t\"title\": \"GetInfo Response Message Type\",\n\t\t\t\"const\": \"getInfoResponse\"\n\t\t},\n\t\t\"GetInfoSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetInfo Success Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"implementationMetadata\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ImplementationMetadata\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"implementationMetadata\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetInfoErrorResponsePayload\": {\n\t\t\t\"title\": \"GetInfo Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getOrCreateChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getOrCreateChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetOrCreateChannel Request\",\n\t\"description\": \"Request to return a Channel with an auto-generated identity that is intended for private communication between applications.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetOrCreateChannelRequestType\": {\n\t\t\t\"title\": \"GetOrCreateChannel Request Message Type\",\n\t\t\t\"const\": \"getOrCreateChannelRequest\"\n\t\t},\n\t\t\"GetOrCreateChannelRequestPayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to return\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\"channelId\"]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getOrCreateChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getOrCreateChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetOrCreateChannel Response\",\n\t\"description\": \"A response to a getOrCreateChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetOrCreateChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetOrCreateChannelResponseType\": {\n\t\t\t\"title\": \"GetOrCreateChannel Response Message Type\",\n\t\t\t\"const\": \"getOrCreateChannelResponse\"\n\t\t},\n\t\t\"GetOrCreateChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channel\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"channel\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetOrCreateChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"GetOrCreateChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getUserChannelsRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getUserChannelsRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetUserChannels Request\",\n\t\"description\": \"Request to retrieve a list of the User Channels available for the app to join.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetUserChannelsRequestType\": {\n\t\t\t\"title\": \"GetUserChannels Request Message Type\",\n\t\t\t\"const\": \"getUserChannelsRequest\"\n\t\t},\n\t\t\"GetUserChannelsRequestPayload\": {\n\t\t\t\"title\": \"GetUserChannels Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/getUserChannelsResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/getUserChannelsResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"GetUserChannels Response\",\n\t\"description\": \"A response to a getUserChannels request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/GetUserChannelsErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"GetUserChannelsResponseType\": {\n\t\t\t\"title\": \"GetUserChannels Response Message Type\",\n\t\t\t\"const\": \"getUserChannelsResponse\"\n\t\t},\n\t\t\"GetUserChannelsSuccessResponsePayload\": {\n\t\t\t\"title\": \"GetUserChannels Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"userChannels\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/Channel\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"userChannels\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"GetUserChannelsErrorResponsePayload\": {\n\t\t\t\"title\": \"GetUserChannels Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/heartbeatAcknowledgmentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/heartbeatAcknowledgementRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"HeartbeatAcknowledgement Request\",\n\t\"description\": \"A request that serves as an acknowledgement of a heartbeat event from the Desktop Agent and indicates that an application window or frame is still alive.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatAcknowledgementRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatAcknowledgementRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"HeartbeatAcknowledgementRequestType\": {\n\t\t\t\"title\": \"HeartbeatAcknowledgement Request Message Type\",\n\t\t\t\"const\": \"heartbeatAcknowledgementRequest\"\n\t\t},\n\t\t\"HeartbeatAcknowledgementRequestPayload\": {\n\t\t\t\"title\": \"heartbeatAcknowledgement Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"heartbeatEventUuid\": {\n\t\t\t\t\t\"title\": \"Heartbeat Event Uuid\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The eventUuid value of the HeartbeatEvent that the acknowledgement being sent relates to.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"heartbeatEventUuid\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/heartbeatEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/heartbeatEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Heartbeat Event\",\n\t\"description\": \"A heartbeat message from the Desktop Agent to an app indicating that the Desktop Agent is alive and that the application should send a heartbeatResponseRequest to the agent in response.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/HeartbeatEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"HeartbeatEventType\": {\n\t\t\t\"title\": \"Heartbeat Event Message Type\",\n\t\t\t\"const\": \"heartbeatEvent\"\n\t\t},\n\t\t\"HeartbeatEventPayload\": {\n\t\t\t\"title\": \"heartbeat Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": []\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/intentEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/intentEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"intent Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that it has been selected to resolve a raised intent and context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentEventType\": {\n\t\t\t\"title\": \"Intent Event Message Type\",\n\t\t\t\"const\": \"intentEvent\"\n\t\t},\n\t\t\"IntentEventPayload\": {\n\t\t\t\"title\": \"Intent Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"title\": \"Intent\",\n\t\t\t\t\t\"description\": \"The intent that was raised.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"The context object passed with the raised intent.\"\n\t\t\t\t},\n\t\t\t\t\"originatingApp\": {\n\t\t\t\t\t\"title\": \"Originating AppIdentifier\",\n\t\t\t\t\t\"description\": \"Details of the application instance that raised the intent.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t},\n\t\t\t\t\"raiseIntentRequestUuid\": {\n\t\t\t\t\t\"title\": \"raiseIntentRequest UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The requestUuid value of the raiseIntentRequest that the intentEvent being sent relates to.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"intent\", \"context\", \"raiseIntentRequestUuid\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/intentListenerUnsubscribeRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/intentListenerUnsubscribeRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentListenerUnsubscribe Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentListenerUnsubscribeRequestType\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Request Message Type\",\n\t\t\t\"const\": \"intentListenerUnsubscribeRequest\"\n\t\t},\n\t\t\"IntentListenerUnsubscribeRequestPayload\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/intentListenerUnsubscribeResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/intentListenerUnsubscribeResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentListenerUnsubscribe Response\",\n\t\"description\": \"A response to a intentListenerUnsubscribe request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentListenerUnsubscribeResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentListenerUnsubscribeResponseType\": {\n\t\t\t\"title\": \"IntentListenerUnsubscribe Response Message Type\",\n\t\t\t\"const\": \"intentListenerUnsubscribeResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/intentResultRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/intentResultRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentResult Request\",\n\t\"description\": \"A request to deliver a result for an intent (which may include a `void` result that just indicates that the handler has run, returning no result). The result is tied to the intentEvent it relates to by quoting the `eventUuid` of the intentEvent in its payload.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentResultRequestType\": {\n\t\t\t\"title\": \"IntentResult Request Message Type\",\n\t\t\t\"const\": \"intentResultRequest\"\n\t\t},\n\t\t\"IntentResultRequestPayload\": {\n\t\t\t\"title\": \"IntentResult Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentEventUuid\": {\n\t\t\t\t\t\"title\": \"IntentEvent UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The eventUuid value of the intentEvent that the result being sent relates to.\"\n\t\t\t\t},\n\t\t\t\t\"raiseIntentRequestUuid\": {\n\t\t\t\t\t\"title\": \"raiseIntentRequest UUID\",\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The requestUuid value of the raiseIntentRequest that the result being sent relates to.\"\n\t\t\t\t},\n\t\t\t\t\"intentResult\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResult\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentEventUuid\", \"raiseIntentRequestUuid\", \"intentResult\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/intentResultResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/intentResultResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"IntentResult Response\",\n\t\"description\": \"A response to a request to deliver an intent result.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/IntentResultResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"IntentResultResponseType\": {\n\t\t\t\"title\": \"IntentResult Response Message Type\",\n\t\t\t\"const\": \"intentResultResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/joinUserChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/joinUserChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"JoinUserChannel Request\",\n\t\"description\": \"Request to join the app to the specified User channel. On successfully joining a channel, client code should make subsequent requests to get the current context of that channel for all registered context listeners and then call their handlers with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"JoinUserChannelRequestType\": {\n\t\t\t\"title\": \"JoinUserChannel Request Message Type\",\n\t\t\t\"const\": \"joinUserChannelRequest\"\n\t\t},\n\t\t\"JoinUserChannelRequestPayload\": {\n\t\t\t\"title\": \"JoinUserChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The id of the channel to join.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\"channelId\"]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/joinUserChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/joinUserChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"JoinUserChannel Response\",\n\t\"description\": \"A response to a joinUserChannel request. On receipt of this response, client code should make subsequent requests to get the current context of that channel for all registered context listeners and then call their handlers with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/JoinUserChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"JoinUserChannelResponseType\": {\n\t\t\t\"title\": \"JoinUserChannel Response Message Type\",\n\t\t\t\"const\": \"joinUserChannelResponse\"\n\t\t},\n\t\t\"JoinUserChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"JoinUserChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"JoinUserChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"JoinUserChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/leaveCurrentChannelRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/leaveCurrentChannelRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"LeaveCurrentChannel Request\",\n\t\"description\": \"Request to remove the app from any User channel membership.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"LeaveCurrentChannelRequestType\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Request Message Type\",\n\t\t\t\"const\": \"leaveCurrentChannelRequest\"\n\t\t},\n\t\t\"LeaveCurrentChannelRequestPayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/leaveCurrentChannelResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/leaveCurrentChannelResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"LeaveCurrentChannel Response\",\n\t\"description\": \"A response to a leaveCurrentChannel request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/LeaveCurrentChannelErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"LeaveCurrentChannelResponseType\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Response Message Type\",\n\t\t\t\"const\": \"leaveCurrentChannelResponse\"\n\t\t},\n\t\t\"LeaveCurrentChannelSuccessResponsePayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"LeaveCurrentChannelErrorResponsePayload\": {\n\t\t\t\"title\": \"LeaveCurrentChannel Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/openRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/openRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Open Request\",\n\t\"description\": \"A request to open an application.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"OpenRequestType\": {\n\t\t\t\"title\": \"Open Request Message Type\",\n\t\t\t\"const\": \"openRequest\"\n\t\t},\n\t\t\"OpenRequestPayload\": {\n\t\t\t\"title\": \"Open Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\",\n\t\t\t\t\t\"title\": \"Context\",\n\t\t\t\t\t\"description\": \"If a Context object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"app\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/openResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/openResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Open Response\",\n\t\"description\": \"A response to a open request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/OpenResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/OpenSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/OpenErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"OpenResponseType\": {\n\t\t\t\"title\": \"Open Response Message Type\",\n\t\t\t\"const\": \"openResponse\"\n\t\t},\n\t\t\"OpenSuccessResponsePayload\": {\n\t\t\t\"title\": \"Open Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIdentifier\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIdentifier\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"OpenErrorResponsePayload\": {\n\t\t\t\"title\": \"Open Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"Open Error Response Payload\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/OpenError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelAddEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelAddEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelAddEventListener Request\",\n\t\"description\": \"A request to add an event listener to a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelAddEventListenerRequestType\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Request Message Type\",\n\t\t\t\"const\": \"privateChannelAddEventListenerRequest\"\n\t\t},\n\t\t\"PrivateChannelAddEventListenerRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener should be added to.\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"listenerType\": {\n\t\t\t\t\t\"title\": \"Event listener type\",\n\t\t\t\t\t\"description\": \"The type of PrivateChannel event that the listener should be applied to, or null for all event types.\",\n\t\t\t\t\t\"oneOf\" : [\n\t\t\t\t\t\t{ \"$ref\": \"api.schema.json#/definitions/PrivateChannelEventType\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"listenerType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelAddEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelAddEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelAddEventListener Response\",\n\t\"description\": \"A response to a privateChannelAddEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelAddEventListenerErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelAddEventListenerResponseType\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Response Message Type\",\n\t\t\t\"const\": \"privateChannelAddEventListenerResponse\"\n\t\t},\n\t\t\"PrivateChannelAddEventListenerSuccessResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"PrivateChannelAddEventListenerErrorResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelAddEventListener Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelDisconnectRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelDisconnectRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelDisconnect Request\",\n\t\"description\": \"Request that indicates that a participant will no longer interact with a specified `PrivateChannel`.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelDisconnectRequestType\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Request Message Type\",\n\t\t\t\"const\": \"privateChannelDisconnectRequest\"\n\t\t},\n\t\t\"PrivateChannelDisconnectRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"channelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the Channel that should be disconnected from\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\"channelId\"],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelDisconnectResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelDisconnectResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelDisconnect Response\",\n\t\"description\": \"A response to a privateChannelDisconnect request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelDisconnectErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelDisconnectResponseType\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Response Message Type\",\n\t\t\t\"const\": \"privateChannelDisconnectResponse\"\n\t\t},\n\t\t\"PrivateChannelDisconnectSuccessResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {},\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"PrivateChannelDisconnectErrorResponsePayload\": {\n\t\t\t\"title\": \"PrivateChannelDisconnect Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ChannelError\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelOnAddContextListenerEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelOnAddContextListenerEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"privateChannelOnAddContextListener Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has added a context listener to a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnAddContextListenerEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnAddContextListener Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnAddContextListenerEvent\"\n\t\t},\n\t\t\"PrivateChannelOnAddContextListenerEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnAddContextListener Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener was added to.\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of the context listener added to the channel by another app, or null if it will listen to all types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelOnDisconnectEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelOnDisconnectEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"privateChannelOnDisconnect Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has disconnected from a specific PrivateChannel and will no longer interact with it.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnDisconnectEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnDisconnectEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnDisconnectEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnDisconnect Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnDisconnectEvent\"\n\t\t},\n\t\t\"PrivateChannelOnDisconnectEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnDisconnect Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the app has disconnected from.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelOnUnsubscribeEvent.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelOnUnsubscribeEvent.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelOnUnsubscribe Event\",\n\t\"description\": \"An event message from the Desktop Agent to an app indicating that another app has unsubscribed a context listener from a specific PrivateChannel.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentEvent.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeEventType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeEventPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelOnUnsubscribeEventType\": {\n\t\t\t\"title\": \"PrivateChannelOnUnsubscribe Event Message Type\",\n\t\t\t\"const\": \"privateChannelOnUnsubscribeEvent\"\n\t\t},\n\t\t\"PrivateChannelOnUnsubscribeEventPayload\": {\n\t\t\t\"title\": \"privateChannelOnUnsubscribe Event Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"privateChannelId\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Private Channel Id\",\n\t\t\t\t\t\"description\": \"The Id of the PrivateChannel that the listener was unsubscribed from.\"\n\t\t\t\t},\n\t\t\t\t\"contextType\": {\n\t\t\t\t\t\"title\": \"Context type\",\n\t\t\t\t\t\"description\": \"The type of the context listener unsubscribed from the channel by another app, or null if it was listening to all types.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"null\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"additionalProperties\": false,\n\t\t\t\"required\": [\n\t\t\t\t\"privateChannelId\",\n\t\t\t\t\"contextType\"\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelUnsubscribeEventListenerRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelUnsubscribeEventListenerRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelUnsubscribeEventListener Request\",\n\t\"description\": \"A request to unsubscribe a context listener.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelUnsubscribeEventListenerRequestType\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Request Message Type\",\n\t\t\t\"const\": \"privateChannelUnsubscribeEventListenerRequest\"\n\t\t},\n\t\t\"PrivateChannelUnsubscribeEventListenerRequestPayload\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"listenerUUID\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ListenerUuid\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"listenerUUID\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/privateChannelUnsubscribeEventListenerResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/privateChannelUnsubscribeEventListenerResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"PrivateChannelUnsubscribeEventListener Response\",\n\t\"description\": \"A response to a privateChannelUnsubscribeEventListener request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/PrivateChannelUnsubscribeEventListenerResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": true,\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"PrivateChannelUnsubscribeEventListenerResponseType\": {\n\t\t\t\"title\": \"PrivateChannelUnsubscribeEventListener Response Message Type\",\n\t\t\t\"const\": \"privateChannelUnsubscribeEventListenerResponse\"\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/raiseIntentForContextRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/raiseIntentForContextRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentForContext Request\",\n\t\"description\": \"A request to raise an unspecified intent for a specified context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentForContextRequestType\": {\n\t\t\t\"title\": \"RaiseIntentForContext Request Message Type\",\n\t\t\t\"const\": \"raiseIntentForContextRequest\"\n\t\t},\n\t\t\"RaiseIntentForContextRequestPayload\": {\n\t\t\t\"title\": \"RaiseIntentForContext Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/raiseIntentForContextResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/raiseIntentForContextResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentForContext Response\",\n\t\"description\": \"A response to a raiseIntentForContext request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"title\": \"RaiseIntentForContext Response Payload\",\n\t\t\t\t\t\"description\": \"There are 3 possible responses to a raiseIntentForContext request, each of which sets a single property in the payload: Success (`intentResolution`), Needs further resolution (`appIntents`) or Error (`error`).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"raiseIntentResponse.schema.json#/$defs/RaiseIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentForContextNeedsResolutionResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"raiseIntentResponse.schema.json#/$defs/RaiseIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentForContextResponseType\": {\n\t\t\t\"title\": \"RaiseIntentForContext Response Message Type\",\n\t\t\t\"const\": \"raiseIntentForContextResponse\"\n\t\t},\n\t\t\"RaiseIntentForContextNeedsResolutionResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntentForContext NeedsResolution Response Payload\",\n\t\t\t\"description\": \"Response to a raiseIntentForContext request that needs additional resolution (i.e. show an intent resolver UI).\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntents\": {\n\t\t\t\t\t\"title\": \"AppIntents\",\n\t\t\t\t\t\"description\": \"Used if a raiseIntentForContext request requires additional resolution (e.g. by showing an intent resolver) before it can be handled.\",\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntents\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/raiseIntentRequest.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/raiseIntentRequest.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntent Request\",\n\t\"description\": \"A request to raise an intent for a context.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"appRequest.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentRequestType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentRequestPayload\"\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentRequestType\": {\n\t\t\t\"title\": \"RaiseIntent Request Message Type\",\n\t\t\t\"const\": \"raiseIntentRequest\"\n\t\t},\n\t\t\"RaiseIntentRequestPayload\": {\n\t\t\t\"title\": \"RaiseIntent Request Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intent\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"context\": {\n\t\t\t\t\t\"$ref\": \"../context/context.schema.json\"\n\t\t\t\t},\n\t\t\t\t\"app\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIdentifier\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intent\", \"context\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/raiseIntentResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/raiseIntentResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntent Response\",\n\t\"description\": \"A response to a raiseIntent request.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"title\": \"RaiseIntent Response Payload\",\n\t\t\t\t\t\"description\": \"There are 3 possible responses to a raiseIntent request, each of which sets a single property in the payload: Success (`intentResolution`), Needs further resolution (`appIntent`) or Error (`error`).\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentNeedsResolutionResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentResponseType\": {\n\t\t\t\"title\": \"RaiseIntent Response Message Type\",\n\t\t\t\"const\": \"raiseIntentResponse\"\n\t\t},\n\t\t\"RaiseIntentSuccessResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Success Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentResolution\": {\n\t\t\t\t\t\"title\": \"Intent Resolution\",\n\t\t\t\t\t\"description\": \"Used if the raiseIntent request was successfully resolved.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResolution\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentResolution\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentNeedsResolutionResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent NeedsResolution Response Payload\",\n\t\t\t\"description\": \"Response to a raiseIntent request that needs additional resolution (i.e. show an intent resolver UI).\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"appIntent\": {\n\t\t\t\t\t\"title\": \"AppIntent\",\n\t\t\t\t\t\"description\": \"Used if a raiseIntent request requires additional resolution (e.g. by showing an intent resolver) before it can be handled.\",\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/AppIntent\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"appIntent\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentErrorResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Error Response Payload\",\n\t\t\t\"description\": \"Used if a raiseIntent request resulted in an error.\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"title\": \"RaiseIntent Error\",\n\t\t\t\t\t\"description\": \"Should be set if the raiseIntent request returned an error.\",\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/ResolveError\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/BridgingError\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/raiseIntentResultResponse.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/api/raiseIntentResultResponse.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"RaiseIntentResult Response\",\n\t\"description\": \"A secondary response to a request to raise an intent used to deliver the intent result. This message should quote the original requestUuid of the raiseIntentRequest message in its `meta.requestUuid` field.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"$ref\": \"agentResponse.schema.json\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultResponseType\"\n\t\t\t\t},\n\t\t\t\t\"payload\": {\n\t\t\t\t\t\"oneOf\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultSuccessResponsePayload\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"$ref\": \"#/$defs/RaiseIntentResultErrorResponsePayload\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"meta\": true\n\t\t\t},\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t],\n\t\"$defs\": {\n\t\t\"RaiseIntentResultResponseType\": {\n\t\t\t\"title\": \"RaiseIntentResult Response Message Type\",\n\t\t\t\"const\": \"raiseIntentResultResponse\"\n\t\t},\n\t\t\"RaiseIntentResultSuccessResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntent Result Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"intentResult\": {\n\t\t\t\t\t\"$ref\": \"api.schema.json#/definitions/IntentResult\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"intentResult\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t},\n\t\t\"RaiseIntentResultErrorResponsePayload\": {\n\t\t\t\"title\": \"RaiseIntentResult Error Response Payload\",\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"error\": {\n\t\t\t\t\t\"$ref\": \"common.schema.json#/$defs/ErrorMessages\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"error\"\n\t\t\t],\n\t\t\t\"additionalProperties\": false\n\t\t}\n\t}\n}"
  },
  {
    "path": "website/static/schemas/2.2/api/t2sQuicktypeUtil.js",
    "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n * Copyright FINOS FDC3 contributors - see NOTICE file\n */\n\n/** Utility for preparing arguments to quicktype, which workaround a specific\n * quicktype bug in command line argument handling (where a directory is used\n * as input the source language argument is ignored which causes our schemas\n * to be interpreted as JSON input, rather than JSONSchema).\n * Bug issue:\n *  */\n\nconst path = require('path');\nconst fs = require('fs');\nconst exec = require('child_process').exec;\n\nconst args = process.argv.slice(2);\nconst outputPath = args.pop();\nconst inputs = args;\n\nconsole.log('Inputs: ' + inputs.join(' | '));\nconsole.log('Output path argument: ' + outputPath);\n\nlet source = '';\n\nlet dirIndex = 0;\n\nconst excludedTypes = [\n  'DesktopAgent.ts',\n  'Listener.ts',\n  'Methods.ts',\n  'PrivateChannel.ts',\n  'Types.ts',\n  'RecommendedChannels.ts',\n];\n\nlet sources = '';\n\nwhile (dirIndex < inputs.length) {\n  if (inputs[dirIndex].endsWith('.ts')) {\n    sources += `--src ${path.join(inputs[dirIndex])} `;\n  } else {\n    fs.readdirSync(inputs[dirIndex], { withFileTypes: true }).forEach(file => {\n      if (file.isDirectory()) {\n        inputs.push(path.join(inputs[dirIndex], file.name));\n      } else {\n        if (!excludedTypes.includes(file.name)) {\n          sources += `--src ${path.join(inputs[dirIndex], file.name)} `;\n        }\n      }\n    });\n  }\n  dirIndex++;\n}\n\n// Normalise path to local quicktype executable.\nconst quicktypeExec = ['.', 'node_modules', '.bin', 'quicktype'].join(path.sep);\n\nconst command = `${quicktypeExec} -l schema -o ${outputPath} ${sources}`;\nconsole.log('command to run: ' + command);\n\nexec(command, function (error, stdout, stderr) {\n  if (stdout) {\n    console.log(stdout);\n  }\n  if (stderr) {\n    console.log(stderr);\n  }\n});\n"
  },
  {
    "path": "website/static/schemas/2.2/app-directory.html",
    "content": "<link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n<style>\n  body {\n    margin: 0;\n    padding: 0;\n  }\n</style>\n<redoc spec-url='/schemas/next/appd.schema.json'></redoc>\n<script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"></script>"
  },
  {
    "path": "website/static/schemas/2.2/appd.schema.json",
    "content": "{\n\t\"openapi\": \"3.0.0\",\n\t\"info\": {\n\t  \"title\": \"FDC3 Application Directory\",\n\t  \"version\": \"next\",\n\t  \"description\": \"Application Directory specification providing both interface definition and objects necessary to construct an application directory service.\",\n\t  \"x-logo\": {\n\t\t\"url\": \"/img/fdc3-logo-2019-color.png\",\n\t\t\"altText\": \"FDC3 logo\"\n\t  }\n\t},\n\t\"security\": [\n\t  {\n\t\t\"bearerAuth\": []\n\t  }\n\t],\n\t\"paths\": {\n\t  \"/v2/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"MyAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/MyAppDefinition\"\n\t\t\t\t\t},\n\t\t\t\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/FDC3WorkbenchAppDefinition\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v2/apps\": {\n\t\t\"get\": {\n\t\t  \"summary\": \"Retrieve all application definitions\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/AllApplicationsResponse\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"AllAppsResponse\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/AllAppsResponse\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error400Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error400Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error403Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error403Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  },\n\t\t\t\t  \"examples\": {\n\t\t\t\t\t\"Error500Example\": {\n\t\t\t\t\t  \"$ref\": \"#/components/examples/Error500Example\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps/{appId}\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve an application definition\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"in\": \"path\",\n\t\t\t  \"required\": true,\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"*/*\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  },\n\t  \"/v1/apps\": {\n\t\t\"post\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Create a new application definition\",\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ],\n\t\t  \"requestBody\": {\n\t\t\t\"content\": {\n\t\t\t  \"application/json\": {\n\t\t\t\t\"schema\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"required\": true\n\t\t  }\n\t\t}\n\t  },\n\t  \"/v1/apps/search\": {\n\t\t\"get\": {\n\t\t  \"deprecated\": true,\n\t\t  \"summary\": \"Retrieve a list of applications based on parameters provided.  Depending on implementation, parameter values should self describe search format and type (e.g. Regex)\",\n\t\t  \"parameters\": [\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"appId\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"version\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"title\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"tooltip\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"description\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_name\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"name of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_displayName\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"displayName of intent\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"in\": \"query\",\n\t\t\t  \"name\": \"intent_context\",\n\t\t\t  \"schema\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"required\": false,\n\t\t\t  \"description\": \"search contexts list\"\n\t\t\t}\n\t\t  ],\n\t\t  \"responses\": {\n\t\t\t\"200\": {\n\t\t\t  \"description\": \"OK\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationSearchResponseV1\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"400\": {\n\t\t\t  \"description\": \"Bad request.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"403\": {\n\t\t\t  \"description\": \"Forbidden: Certificate authentication is not allowed for the requested user.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"500\": {\n\t\t\t  \"description\": \"Server error, see response body for further details.\",\n\t\t\t  \"content\": {\n\t\t\t\t\"application/json\": {\n\t\t\t\t  \"schema\": {\n\t\t\t\t\t\"$ref\": \"#/components/schemas/ErrorDTO\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"tags\": [\n\t\t\t\"Application\"\n\t\t  ]\n\t\t}\n\t  }\n\t},\n\t\"servers\": [\n\t  {\n\t\t\"url\": \"/appd\"\n\t  }\n\t],\n\t\"components\": {\n\t  \"securitySchemes\": {\n\t\t\"bearerAuth\": {\n\t\t  \"type\": \"http\",\n\t\t  \"scheme\": \"bearer\",\n\t\t  \"bearerFormat\": \"JWT\"\n\t\t}\n\t  },\n\t  \"schemas\": {\n\t\t\"ErrorDTO\": {\n\t\t  \"type\": \"object\",\n\t\t  \"properties\": {\n\t\t\t\"code\": {\n\t\t\t  \"type\": \"integer\",\n\t\t\t  \"format\": \"int32\"\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"BaseApplication\": {\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Title for the application, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Type\"\n\t\t\t},\n\t\t\t\"details\": {\n\t\t\t  \"$ref\": \"#/components/schemas/LaunchDetails\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Deprecated in favour of using `appId` to identify apps and `title` for their display names. The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"lang\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"pattern\": \"^[a-z]{2}(-[a-zA-Z0-9]{2,8}){0,1}$\",\n\t\t\t  \"description\": \"A language tag that specifies the primary language of both the application and its AppD entry, as defined by IETF RFC 5646.\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. \"\n\t\t\t},\n\t\t\t\"categories\": {\n\t\t\t  \"description\": \"An array of string categories that describe the application. These are meant as a hint to catalogs or stores listing FDC3-enabled apps and it is expected that these will make a best effort to find appropriate categories (or category) under which to list the app. AppD record authors are encouraged to use lower-case and, where possible, to select categories from the following list:\\n\\n- allocations\\n- analytics\\n- charts\\n- chat\\n- communication\\n- compliance\\n- crm\\n- developer tools\\n- events\\n- execution management\\n- file sharing\\n- market data\\n- news\\n- networking\\n- office apps\\n- order management\\n- other\\n- portfolio management\\n- presentation\\n- pricing\\n- productivity\\n- research\\n- risk\\n- screen sharing\\n- security\\n- spreadsheet\\n- trade cost analysis\\n- trading system\\n- training\\n- travel\\n- video\\n- visualization\\n- weather\\n\",\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Icon\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"screenshots\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Screenshot\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"moreInfo\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Optional URL that provides more information about the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher. Deprecated due to a lack of a standard means of retrieval via the Desktop Agent API. To be replaced in a future version with an `applicationConfig` element and standard API to retrieve it. See issue  [#1006](https://github.com/finos/FDC3/issues/1006) for details.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"$ref\": \"#/components/schemas/HostManifests\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"$ref\": \"#/components/schemas/Interop\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Application\": {\n\t\t  \"description\": \"Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"title\",\n\t\t\t\"type\",\n\t\t\t\"details\"\n\t\t  ],\n\t\t  \"allOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"$ref\": \"#/components/schemas/LocalizedVersions\"\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"AllApplicationsResponse\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/Application\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"NameValuePair\": {\n\t\t  \"description\": \"Simple name value pair\",\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"name\"\n\t\t\t},\n\t\t\t\"value\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"value\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Icon\": {\n\t\t  \"description\": \"Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Icon dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t    \"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Screenshot\": {\n\t\t  \"description\": \"Images representing the app in common usage scenarios\",\n\t\t  \"properties\": {\n\t\t\t\"src\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t},\n\t\t\t\"size\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image dimension formatted as `<height>x<width>`\"\n\t\t\t},\n\t\t\t\"type\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Image media type. If not present the Desktop Agent may use the src file extension.\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional caption for the image\"\n\t\t\t}\n\t\t  },\n\t\t  \"required\": [\n\t\t\t\"src\"\n\t\t  ],\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"Type\": {\n\t\t  \"type\": \"string\",\n\t\t  \"description\": \"The technology type that is used to launch and run the application. Each application type implies a particular set of launch `details`.\\nThe supported types include:\\n\\n- `web`: Web applications launched via a URL\\n- `native`: Native applications pre-installed on a device and launch via a filesystem path\\n- `citrix`: Apps virtualized via Citrix\\n- `onlineNative`: Native apps that have an online launcher, e.g. online ClickOnce app deployments.\\n- `other`: Used to represent apps that do not conform to or cannot be launched via the other types, and are likely to be defined solely by a hostManifest.\\n\\nFDC3 Desktop Agents MUST support at least the `web` application type and MAY support any or all of the other types.\",\n\t\t  \"enum\": [\n\t\t\t\"web\",\n\t\t\t\"native\",\n\t\t\t\"citrix\",\n\t\t\t\"onlineNative\",\n\t\t\t\"other\"\n\t\t  ]\n\t\t},\n\t\t\"LaunchDetails\": {\n\t\t  \"description\": \"The type specific launch details of the application. These details are intended to be vendor-agnostic and MAY be duplicated or overridden by details provided in the hostManifests object for a specific host.\",\n\t\t  \"oneOf\": [\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/WebAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/NativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/CitrixAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OnlineNativeAppDetails\"\n\t\t\t},\n\t\t\t{\n\t\t\t  \"$ref\": \"#/components/schemas/OtherAppDetails\"\n\t\t\t}\n\t\t  ]\n\t\t},\n\t\t\"WebAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps with `type: web`.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application start URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"NativeAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps with `type: native` that are already installed on the device.\",\n\t\t  \"required\": [\n\t\t\t\"path\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"path\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The path on disk from which the application is launched.\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"CitrixAppDetails\": {\n\t      \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch apps virtualized apps with `type: citrix`.\",\n\t\t  \"required\": [\n\t\t\t\"alias\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"alias\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The Citrix alias / name of the virtual app (passed to the Citrix SelfService qlaunch parameter).\"\n\t\t\t},\n\t\t\t\"arguments\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Arguments that must be passed on the command line to launch the app in the expected configuration.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OnlineNativeAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Properties used to launch a native apps with `type: onlineNative` that have an online launcher, e.g. online ClickOnce app deployments.\",\n\t\t  \"required\": [\n\t\t\t\"url\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Application URL.\"\n\t\t\t}\n\t\t  },\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"OtherAppDetails\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Apps with `type: other` are defined by a hostManifest and do not require other details.\",\n\t\t  \"properties\": {},\n\t\t  \"additionalProperties\": false\n\t\t},\n\t\t\"HostManifests\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"A mapping from host name to a host-specific application manifest object or URI from which that manifest can be retrieved. The manifest should provide details required to launch and use the application within the specified host. The manifest _MAY_ duplicate or  override information provided in the `details` field.\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Host name\",\n\t\t\t\"oneOf\": [\n\t\t\t  {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"format\": \"uri\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"$ref\": \"#/components/schemas/HostManifest\"\n\t\t\t  }\n\t\t\t]\n\t\t  }\n\t\t},\n\t\t\"HostManifest\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Object containing all host specific properties.\"\n\t\t},\n\t\t\"LocalizedVersions\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Provides localized alternatives to any field of the AppD record, which may also refer to an alternative version of the application that is also localized (e.g. by providing an alternative URL).  The keys to this object should be language tags as defined by IETF RFC 5646, e.g. en, en-GB or fr-FR.\\n\",\n\t\t  \"additionalProperties\": {\n\t\t\t\"x-additionalPropertiesName\": \"Language tag\",\n\t\t\t\"$ref\": \"#/components/schemas/BaseApplication\"\n\t\t  }\n\t\t},\n\t\t\"Intent\": {\n\t\t  \"description\": \"Definition of an intent that an app listens for\",\n\t\t  \"required\": [\n\t\t\t\"contexts\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional display name for the intent. Deprecated in favour of the intent name, which is common amongst all apps that support it, where the display name may vary as it is defined in the app's AppD record.\",\n\t\t\t  \"deprecated\": true\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"resultType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional type for output returned by the application, if any, when resolving this intent. May indicate a context type by type name (e.g. \\\"fdc3.instrument\\\"), a channel (e.g. \\\"channel\\\") or a combination that indicates a channel that returns a particular context type (e.g. \\\"channel<fdc3.instrument>\\\").\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"Interop\": {\n\t\t  \"type\": \"object\",\n\t\t  \"description\": \"Metadata that describes how the application uses FDC3 APIs. This metadata serves multiple purposes:\\n\\n- It supports intent resolution by a desktop agent, by declaring what intents an app listens for.\\n- It may be used, for example in an app catalog UI, to find apps that 'interoperate with' other apps. \\n- It provides a standard location to document how the app interacts with user channels, app channels, and intents, for use by other app developers and desktop assemblers.\",\n\t\t  \"properties\": {\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the app's interactions with intents.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intents names that an app listens for via `fdc3.addIntentListener()` to their configuration. \\n\\nUsed to support intent resolution by desktop agents. Replaces the `intents` element used in appD records prior to FDC3 2.0.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"$ref\": \"#/components/schemas/Intent\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"type\": \"object\",\n\t\t\t\t  \"description\": \"A mapping of Intent names that an app raises (via `fdc3.raiseIntent`) to an array of context type names that it may be raised with.\\n\\nUse the intent name \\\"any\\\" to represent use of the `fdc3.raiseIntentForContext` and `fdc3.findIntentForContext` functions, which allow the user to select from intents available for a specified context type.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t\t  \"additionalProperties\": {\n\t\t\t\t\t\"x-additionalPropertiesName\": \"Intent name\",\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the intent may be raised with.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"userChannels\": {\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Describes the application's use of context types on User Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"properties\": {\n\t\t\t\t\"broadcasts\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that are broadcast by the application.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"type\": \"array\",\n\t\t\t\t  \"description\": \"Context type names that the application listens for.\",\n\t\t\t\t  \"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t},\n\t\t\t\"appChannels\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Describes the application's use of App Channels.\\n\\nThis metadata is not currently used by the desktop agent, but is provided to help find apps that will interoperate with this app and to document API interactions for use by other app developers.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": [\n\t\t\t\t  \"id\"\n\t\t\t\t],\n\t\t\t\t\"properties\": {\n\t\t\t\t  \"id\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"The id of the App Channel. N.b. in FDC3 2.0 this field was incorrectly called `name`.\"\n\t\t\t\t  },\n\t\t\t\t  \"description\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"description\": \"A description of how the channel is used.\"\n\t\t\t\t  },\n\t\t\t\t  \"broadcasts\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that are broadcast by the application on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"listensFor\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"description\": \"Context type names that the application listens for on the channel.\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t  \"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"AppImageV1\": {\n\t\t  \"description\": \"App Image holder\",\n\t\t  \"properties\": {\n\t\t\t\"url\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"App Image URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IconV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Icon holder\",\n\t\t  \"properties\": {\n\t\t\t\"icon\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"uri\",\n\t\t\t  \"description\": \"Icon URL\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"IntentV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) An intent definition as defined by spec https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t  \"required\": [\n\t\t\t\"name\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the intent to 'launch'. In this case the name of an Intent supported by an application.\"\n\t\t\t},\n\t\t\t\"displayName\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"An optional display name for the intent that may be used in UI instead of the name.\"\n\t\t\t},\n\t\t\t\"contexts\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t  },\n\t\t\t  \"description\": \"A comma separated list of the types of contexts the intent offered by the application can process, where the first part of the context type is the namespace e.g.\\\"fdc3.contact, org.symphony.contact\\\"\"\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"object\",\n\t\t\t  \"description\": \"Custom configuration for the intent that may be required for a particular desktop agent. Deprecated due to a lack of defined use cases.\"\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationV1\": {\n\t\t  \"description\": \"(Deprecated v1 API version) Defines an application retrieved from an FDC3 App Directory, which can then be launched. Launching typically means running for a user on a desktop. The details around 'launching' including who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3 App Directory spec.\",\n\t\t  \"required\": [\n\t\t\t\"appId\",\n\t\t\t\"name\",\n\t\t\t\"manifest\",\n\t\t\t\"manifestType\"\n\t\t  ],\n\t\t  \"properties\": {\n\t\t\t\"appId\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The unique application identifier located within a specific application directory instance.\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the application. The name should be unique within an FDC3 App Directory instance. The exception to the uniqueness constraint is that an App Directory can hold definitions for multiple versions of the same app. The same appName could occur in other directories. We are not currently specifying app name conventions in the document.\"\n\t\t\t},\n\t\t\t\"manifest\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"URI or full JSON of the application manifest providing all details related to launch and use requirements as described by the vendor. The format of this manifest is vendor specific, but can be identified by the manifestType attribute.\"\n\t\t\t},\n\t\t\t\"manifestType\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The manifest type which relates to the format and structure of the manifest content. The definition is based on the vendor specific format and definition outside of this specification.\"\n\t\t\t},\n\t\t\t\"version\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Version of the application. This allows multiple app versions to be defined using the same app name. This can be a triplet but can also include things like 1.2.5 (BETA)\"\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional title for the application, if missing use appName, typically used in a launcher UI.\"\n\t\t\t},\n\t\t\t\"tooltip\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Optional tooltip description e.g. for a launcher\"\n\t\t\t},\n\t\t\t\"description\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Description of the application. This will typically be a 1-2 paragraph style blurb about the application. Allow mark up language\"\n\t\t\t},\n\t\t\t\"images\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/AppImageV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"contactEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive queries about the application\"\n\t\t\t},\n\t\t\t\"supportEmail\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"format\": \"email\",\n\t\t\t  \"description\": \"Optional e-mail to receive support requests for the application\"\n\t\t\t},\n\t\t\t\"publisher\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"The name of the company that owns the application. The publisher has control over their namespace/app/signature.\"\n\t\t\t},\n\t\t\t\"icons\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IconV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"customConfig\": {\n\t\t\t  \"deprecated\": true,\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/NameValuePair\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"intents\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"The list of intents implemented by the application as defined by https://github.com/FDC3/Intents/blob/main/src/Intent.yaml\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/IntentV1\"\n\t\t\t  }\n\t\t\t}\n\t\t  }\n\t\t},\n\t\t\"ApplicationSearchResponseV1\": {\n\t\t  \"properties\": {\n\t\t\t\"applications\": {\n\t\t\t  \"type\": \"array\",\n\t\t\t  \"description\": \"List of applications\",\n\t\t\t  \"items\": {\n\t\t\t\t\"$ref\": \"#/components/schemas/ApplicationV1\"\n\t\t\t  }\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t  \"type\": \"string\",\n\t\t\t  \"description\": \"Response message providing status of query\"\n\t\t\t}\n\t\t  }\n\t\t}\n\t  },\n\t  \"examples\": {\n\t\t\"FDC3WorkbenchAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\"categories\": [\n\t\t\t  \"developer tools\",\n\t\t\t  \"training\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"https://fdc3.finos.org\",\n\t\t\t\"publisher\": \"FDC3\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 640,\n\t\t\t\t  \"width\": 560,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 800,\n\t\t\t\t  \"height\": 750,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition for the FDC3 Workbench\"\n\t\t},\n\t\t\"MyAppDefinition\": {\n\t\t  \"value\": {\n\t\t\t\"appId\": \"my-application\",\n\t\t\t\"title\": \"My Application\",\n\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\"categories\": [\n\t\t\t  \"market data\",\n\t\t\t  \"research\",\n\t\t\t  \"news\"\n\t\t\t],\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\"lang\": \"en-US\",\n\t\t\t\"icons\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\"type\": \"image/png\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"screenshots\": [\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\"size\": \"800x600\"\n\t\t\t  }\n\t\t\t],\n\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\"type\": \"web\",\n\t\t\t\"details\": {\n\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t},\n\t\t\t\"hostManifests\": {\n\t\t\t  \"Finsemble\": {\n\t\t\t\t\"window\": {\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"options\": {\n\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"foreign\": {\n\t\t\t\t  \"components\": {\n\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t}\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"autoConnect\": true\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Glue42\": {\n\t\t\t\t\"type\": \"window\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"height\": 800,\n\t\t\t\t  \"width\": 600,\n\t\t\t\t  \"left\": 120,\n\t\t\t\t  \"top\": 120,\n\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t  \"loader\": {\n\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"customProperties\": {\n\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t},\n\t\t\t\"interop\": {\n\t\t\t  \"intents\": {\n\t\t\t\t\"listensFor\": {\n\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t],\n\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t\"raises\": {\n\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t  ],\n\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"userChannels\": {\n\t\t\t\t\"broadcasts\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t],\n\t\t\t\t\"listensFor\": [\n\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t]\n\t\t\t  },\n\t\t\t  \"appChannels\": [\n\t\t\t\t{\n\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t  ],\n\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t  ]\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"localizedVersions\": {\n\t\t\t  \"fr-FR\": {\n\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t  \"summary\": \"A sample app definition that describes the app's use of interop.\"\n\t\t},\n\t\t\"AllAppsResponse\": {\n\t\t  \"value\": {\n\t\t\t\"applications\": [\n\t\t\t  {\n\t\t\t\t\"appId\": \"my-application\",\n\t\t\t\t\"title\": \"My Application\",\n\t\t\t\t\"description\": \"An example application that uses FDC3 and fully describes itself in an AppD record.\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"market data\",\n\t\t\t\t  \"research\",\n\t\t\t\t  \"news\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"My example application definition\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-icon.png\",\n\t\t\t\t\t\"size\": \"256x256\",\n\t\t\t\t\t\"type\": \"image/png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-1.png\",\n\t\t\t\t\t\"label\": \"The first screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  },\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"http://example.domain.com/assets/my-app-screenshot-2.png\",\n\t\t\t\t\t\"label\": \"The second screenshot of my example app\",\n\t\t\t\t\t\"type\": \"image/png\",\n\t\t\t\t\t\"size\": \"800x600\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"moreInfo\": \"http://example.domain.com/\",\n\t\t\t\t\"publisher\": \"Example App, Inc.\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"http://example.domain.com/app.html\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 800,\n\t\t\t\t\t  \"width\": 600,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"http://example.domain.com/my-app.json\"\n\t\t\t\t},\n\t\t\t\t\"interop\": {\n\t\t\t\t  \"intents\": {\n\t\t\t\t\t\"listensFor\": {\n\t\t\t\t\t  \"ViewChart\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t]\n\t\t\t\t\t  },\n\t\t\t\t\t  \"myApp.GetPrice\": {\n\t\t\t\t\t\t\"contexts\": [\n\t\t\t\t\t\t  \"fdc3.instrument\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"resultType\": \"myApp.quote\"\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"raises\": {\n\t\t\t\t\t  \"ViewOrders\": [\n\t\t\t\t\t\t\"fdc3.instrument\",\n\t\t\t\t\t\t\"fdc3.organization\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"StartEmail\": [\n\t\t\t\t\t\t\"fdc3.email\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"userChannels\": {\n\t\t\t\t\t\"broadcasts\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t],\n\t\t\t\t\t\"listensFor\": [\n\t\t\t\t\t  \"fdc3.instrument\",\n\t\t\t\t\t  \"fdc3.organization\"\n\t\t\t\t\t]\n\t\t\t\t  },\n\t\t\t\t  \"appChannels\": [\n\t\t\t\t\t{\n\t\t\t\t\t  \"id\": \"myApp.quotes,\",\n\t\t\t\t\t  \"description\": \"Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,\",\n\t\t\t\t\t  \"broadcasts\": [\n\t\t\t\t\t\t\"myApp.quote\"\n\t\t\t\t\t  ],\n\t\t\t\t\t  \"listensFor\": [\n\t\t\t\t\t\t\"fdc3.instrument\"\n\t\t\t\t\t  ]\n\t\t\t\t\t}\n\t\t\t\t  ]\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"Mon application,\",\n\t\t\t\t\t\"description\": \"Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD.\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  {\n\t\t\t\t\"appId\": \"fdc3-workbench\",\n\t\t\t\t\"title\": \"FDC3 Workbench\",\n\t\t\t\t\"description\": \"Development and test tool for FDC3 desktop agents and apps\",\n\t\t\t\t\"categories\": [\n\t\t\t\t  \"developer tools\",\n\t\t\t\t  \"training\"\n\t\t\t\t],\n\t\t\t\t\"version\": \"1.0.0\",\n\t\t\t\t\"tooltip\": \"FDC3 Workbench\",\n\t\t\t\t\"lang\": \"en-US\",\n\t\t\t\t\"icons\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"screenshots\": [\n\t\t\t\t  {\n\t\t\t\t\t\"src\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png,\",\n\t\t\t\t\t\"label\": \"FDC3 logo\"\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"contactEmail\": \"fdc3@finos.org\",\n\t\t\t\t\"supportEmail\": \"fdc3-maintainers@finos.org\",\n\t\t\t\t\"publisher\": \"FDC3,\",\n\t\t\t\t\"type\": \"web\",\n\t\t\t\t\"details\": {\n\t\t\t\t  \"url\": \"https://fdc3.finos.org/toolbox/fdc3-workbench/\"\n\t\t\t\t},\n\t\t\t\t\"hostManifests\": {\n\t\t\t\t  \"Glue42\": {\n\t\t\t\t\t\"type\": \"window\",\n\t\t\t\t\t\"icon\": \"https://fdc3.finos.org/docs/assets/fdc3-logo.png\",\n\t\t\t\t\t\"details\": {\n\t\t\t\t\t  \"height\": 640,\n\t\t\t\t\t  \"width\": 560,\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"mode\": \"tab\",\n\t\t\t\t\t  \"allowChannels\": true,\n\t\t\t\t\t  \"loader\": {\n\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\"hideOnLoad\": true\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"customProperties\": {\n\t\t\t\t\t  \"folder\": \"FDC3 Toolbox\"\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Finsemble\": {\n\t\t\t\t\t\"window\": {\n\t\t\t\t\t  \"left\": 120,\n\t\t\t\t\t  \"top\": 120,\n\t\t\t\t\t  \"width\": 800,\n\t\t\t\t\t  \"height\": 750,\n\t\t\t\t\t  \"options\": {\n\t\t\t\t\t\t\"minWidth\": 75\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"foreign\": {\n\t\t\t\t\t  \"components\": {\n\t\t\t\t\t\t\"App Launcher\": {\n\t\t\t\t\t\t  \"launchableByUser\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Toolbar\": {\n\t\t\t\t\t\t  \"iconURL\": \"http://fdc3.finos.org/toolbox/fdc3-workbench/fdc3-icon-256.png\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Window Manager\": {\n\t\t\t\t\t\t  \"FSBLHeader\": true,\n\t\t\t\t\t\t  \"persistWindowState\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t  }\n\t\t\t\t\t},\n\t\t\t\t\t\"interop\": {\n\t\t\t\t\t  \"autoConnect\": true\n\t\t\t\t\t}\n\t\t\t\t  },\n\t\t\t\t  \"Web App Manifest\": \"https://example.com/fdc3-workbench.json\"\n\t\t\t\t},\n\t\t\t\t\"localizedVersions\": {\n\t\t\t\t  \"fr-FR\": {\n\t\t\t\t\t\"title\": \"FDC3 Table de travail\",\n\t\t\t\t\t\"description\": \"Outil de développement et de test pour les desktop agents et applications FDC3\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t],\n\t\t\t\"message\": \"OK\"\n\t\t  },\n\t\t  \"summary\": \"A sample 'all applications' listing response\"\n\t\t},\n\t\t\"Error400Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 400,\n\t\t\t\"message\": \"There was an error in your request.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Bad Request error.\"\n\t\t},\n\t\t\"Error403Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 403,\n\t\t\t\"message\": \"Certificate authentication failed for the requested user.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Forbidden error.\"\n\t\t},\n\t\t\"Error500Example\": {\n\t\t  \"value\": {\n\t\t\t\"code\": 500,\n\t\t\t\"message\": \"An internal server error occurred. See the response body for further details.\"\n\t\t  },\n\t\t  \"summary\": \"A sample Server error.\"\n\t\t}\n\t  }\n\t}\n  }"
  },
  {
    "path": "website/static/schemas/2.2/bridging/agentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/agentErrorResponse.schema.json\",\n  \"title\": \"Agent Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge containing an error, to be used in preference to the standard response when an error needs to be returned.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Error Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"Error message payload containing an standardized error string.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n        }\n      },\n      \"unevaluatedProperties\": false,\n      \"required\": [\"error\"]\n    },\n    \"meta\": {\n      \"$ref\": \"agentResponse.schema.json#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/agentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/agentRequest.schema.json\",\n  \"title\": \"Agent Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Request Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"broadcastRequest\",\n        \"findInstancesRequest\",\n        \"findIntentRequest\",\n        \"findIntentsByContextRequest\",\n        \"getAppMetadataRequest\",\n        \"openRequest\",\n        \"PrivateChannel.broadcast\",\n        \"PrivateChannel.eventListenerAdded\",\n        \"PrivateChannel.eventListenerRemoved\",\n        \"PrivateChannel.onAddContextListener\",\n        \"PrivateChannel.onDisconnect\",\n        \"PrivateChannel.onUnsubscribe\",\n        \"raiseIntentRequest\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"AgentRequestMeta\": {\n      \"title\": \"Agent Request Metadata\",\n      \"description\": \"Metadata for a request message sent by Desktop Agents to the Bridge.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself.\",\n          \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/agentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/agentResponse.schema.json\",\n  \"title\": \"Agent Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from a Desktop Agent to the Bridge.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"findInstancesResponse\",\n        \"findIntentResponse\",\n        \"findIntentsByContextResponse\",\n        \"getAppMetadataResponse\",\n        \"openResponse\",\n        \"raiseIntentResponse\",\n        \"raiseIntentResultResponse\"\n      ],\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/AgentResponseMeta\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"$defs\": {\n    \"AgentResponseMeta\": {\n      \"title\": \"Agent Response Metadata\",\n      \"description\": \"Metadata for a response messages sent by a Desktop Agent to the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/bridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/bridgeErrorResponse.schema.json\",\n  \"title\": \"Bridge Error Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request, used where all connected agents returned errors.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Error Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The error message payload contains details of an error return to the app or agent that raised the original request.\",\n      \"properties\": {\n        \"error\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n        }\n      }\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeErrorResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeErrorResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\", \"errorSources\", \"errorDetails\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/bridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/bridgeRequest.schema.json\",\n  \"title\": \"Bridge Request Message\",\n  \"type\": \"object\",\n  \"description\": \"A request message forwarded from the Bridge onto a Desktop Agent connected to it.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Message type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains the arguments to FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeRequestMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeRequestMeta\": {\n      \"title\": \"Bridge Request Metadata\",\n      \"description\": \"Metadata required in a request message forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"source\": {\n          \"title\": \"Bridge Source identifier\",\n          \"description\": \"Field that represents the source application that the request was received from, or the source Desktop Agent if it issued the request itself. The Desktop Agent identifier MUST be set by the bridge.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        },\n        \"destination\": {\n          \"title\": \"Destination identifier\",\n          \"description\": \"Optional field that represents the destination that the request should be routed to. Must be set by the Desktop Agent for API calls that include a target app parameter and must include the name of the Desktop Agent hosting the target application.\",\n          \"$ref\": \"common.schema.json#/$defs/BridgeParticipantIdentifier\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"timestamp\", \"source\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/bridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/bridgeResponse.schema.json\",\n  \"title\": \"Bridge Response Message\",\n  \"type\": \"object\",\n  \"description\": \"A response message from the Bridge back to the original Desktop Agent that raised the request.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Response Message Type\",\n      \"type\": \"string\",\n      \"description\": \"Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended.\"\n    },\n    \"payload\": {\n      \"title\": \"Response Message Payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload typically contains return values for FDC3 API functions.\"\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/BridgeResponseMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"BridgeResponseMeta\": {\n      \"title\": \"Bridge Response Metadata\",\n      \"description\": \"Metadata required in a response message collated and/or forwarded on by the Bridge\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"sources\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseSources\"\n        },\n        \"errorSources\": {\n         \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorSources\"\n        },\n        \"errorDetails\": {\n          \"$ref\": \"common.schema.json#/$defs/BridgeResponseErrorDetails\"\n        }\n      },\n      \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/broadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/broadcastAgentRequest.schema.json\",\n  \"title\": \"Broadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"BroadcastRequestBase\": {\n      \"title\": \"Broadcast Request\",\n      \"type\":\"object\",\n      \"description\": \"A request to broadcast context on a channel.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/broadcastRequest.schema.json#/$defs/BroadcastRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/broadcastRequest.schema.json#/$defs/BroadcastRequestPayload\"\n        },\n        \"meta\": {\n          \"type\": \"object\",\n          \"title\": \"broadcast request metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/broadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/broadcastBridgeRequest.schema.json\",\n  \"title\": \"Broadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"broadcastAgentRequest.schema.json#/$defs/BroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/common.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/common.schema.json\",\n  \"title\": \"Bridge Common definitions\",\n  \"type\": \"object\",\n  \"description\": \"Common definitions that are referenced only in the Bridging wire protocol schemas\",\n  \"$defs\": {\n    \"RequestSource\": {\n      \"title\": \"Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from, or the source Desktop Agent if it issued the request or response itself.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ]\n    },\n    \"AppRequestSource\": {\n      \"title\": \"App Source identifier\",\n      \"description\": \"Field that represents the source application that a request or response was received from.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n    },\n    \"AgentDestination\": {\n      \"title\": \"Agent Destination identifier\",\n      \"description\": \"Field that represents a destination Desktop Agent that a request is to be sent to.\",\n      \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n    },\n    \"AppDestination\": {\n      \"title\": \"App Destination identifier\",\n      \"description\": \"Field that represents a destination App on a remote Desktop Agent that a request is to be sent to.\",\n      \"allOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        }\n      ]\n    },\n    \"BridgeParticipantIdentifier\": {\n      \"title\": \"Bridge Participant Identifier\",\n      \"description\": \"Represents identifiers that MUST include the Desktop Agent name and MAY identify a specific app or instance.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        },\n        {\n          \"allOf\": [\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n            },\n            {\n              \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n            }\n          ]\n        }\n      ]\n    },\n    \"BridgeResponseSources\": {\n      \"title\": \"Desktop Agents that responded\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for the sources that generated responses to the request. Will contain a single value for individual responses and multiple values for responses that were collated by the bridge. May be omitted if all sources errored. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"BridgeResponseErrorSources\": {\n      \"title\": \"Desktop Agents that errored\",\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n        }\n      ],\n      \"description\": \"Array of DesktopAgentIdentifiers for responses that were not returned to the bridge before the timeout or because an error occurred. May be omitted if all sources responded without errors. MUST include the `desktopAgent` field when returned by the bridge.\"\n    },\n    \"BridgeResponseErrorDetails\": {\n      \"title\": \"Response Error Details\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"../api/common.schema.json#/$defs/ErrorMessages\"\n      },\n      \"description\": \"Array of error message strings for responses that were not returned to the bridge before the timeout or because an error occurred. Should be the same length as the `errorSources` array and ordered the same. May be omitted if all sources responded without errors.\"\n    },\n    \"DesktopAgentImplementationMetadata\": {\n      \"description\": \"Includes the name assigned to the Desktop Agent by the Bridge.\",\n      \"title\": \"DesktopAgentImplementationMetadata\",\n      \"type\": \"object\",\n      \"allOf\": [\n        {\n          \"$ref\": \"../api/api.schema.json#/definitions/BaseImplementationMetadata\"\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"desktopAgent\": {\n              \"description\": \"Used in Desktop Agent Bridging to attribute or target a message to a particular Desktop Agent.\",\n              \"type\": \"string\",\n              \"title\": \"desktopAgent\"\n            }\n          }\n        }\n      ],\n      \"properties\": {\n        \"fdc3Version\": true,\n        \"provider\": true,\n        \"providerVersion\": true,\n        \"optionalFeatures\": true,\n        \"desktopAgent\": true\n      },\n      \"required\": [\n        \"fdc3Version\",\n        \"optionalFeatures\",\n        \"provider\",\n        \"desktopAgent\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/connectionStep.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/connectionStep.schema.json\",\n  \"title\": \"Connection Step Message\",\n  \"type\": \"object\",\n  \"description\": \"A message used during the connection flow for a Desktop Agent to the Bridge. Used for messages sent in either direction.\",\n  \"properties\": {\n    \"type\": {\n      \"title\": \"Connection Step Message type\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"hello\",\n        \"handshake\",\n        \"authenticationFailed\",\n        \"connectedAgentsUpdate\"\n      ],\n      \"description\": \"Identifies the type of the connection step message.\"\n    },\n    \"payload\": {\n      \"title\": \"Message payload\",\n      \"type\": \"object\",\n      \"description\": \"The message payload, containing data pertaining to this connection step.\",\n      \"unevaluatedProperties\": false\n    },\n    \"meta\": {\n      \"$ref\": \"#/$defs/ConnectionStepMeta\"\n    }\n  },\n  \"required\": [\"type\", \"payload\", \"meta\"],\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"ConnectionStepMeta\": {\n      \"title\": \"Connection Step Metadata\",\n      \"description\": \"Metadata for this connection step message.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"requestUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n        },\n        \"timestamp\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n        },\n        \"responseUuid\": {\n          \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n        }\n      },\n      \"required\": [\"timestamp\"],\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/connectionStep2Hello.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/connectionStep2Hello.schema.json\",\n  \"title\": \"ConnectionStep2Hello\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep2HelloBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep2HelloBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep2Hello\",\n      \"description\": \"Hello message sent by the Bridge to anyone connecting to the Bridge (enables identification as a bridge and confirmation of whether authentication is required)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 2 Message Type\",\n          \"const\": \"hello\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 2 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"desktopAgentBridgeVersion\": {\n              \"title\": \"Desktop Agent Bridge Version Number\",\n              \"description\": \"The version of the Bridge\",\n              \"type\": \"string\"\n            },\n            \"supportedFDC3Versions\": {\n              \"title\": \"Supported FDC3 Versions\",\n              \"type\": \"array\",\n              \"description\": \"The FDC3 versions supported by the Bridge\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"authRequired\": {\n              \"title\": \"Authentication Required\",\n              \"type\": \"boolean\",\n              \"description\": \"A flag indicating whether the Desktop Agent Bridge requires authentication or not.\"\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\",\n              \"description\": \"An optional Desktop Agent Bridge JWT authentication token if the Desktop Agent want to authenticate a bridge.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"desktopAgentBridgeVersion\", \"supportedFDC3Versions\", \"authRequired\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 2 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/connectionStep3Handshake.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/connectionStep3Handshake.schema.json\",\n  \"title\": \"ConnectionStep3Handshake\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep3HandshakeBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep3HandshakeBase\": {\n      \"type\": \"object\",\n      \"title\": \"ConnectionStep3Handshake\",\n      \"description\": \"Handshake message sent by the Desktop Agent to the Bridge (including requested name, channel state and authentication data)\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 3 Message Type\",\n          \"const\": \"handshake\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 3 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"implementationMetadata\": {\n              \"title\": \"Connecting Agent ImplementationMetadata\",\n              \"description\": \"Desktop Agent ImplementationMetadata trying to connect to the bridge.\",\n              \"type\": \"object\",\n              \"allOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/BaseImplementationMetadata\"\n                }\n              ],\n              \"properties\": {\n                \"fdc3Version\": true,\n                \"provider\": true,\n                \"providerVersion\": true,\n                \"optionalFeatures\": true\n              },\n              \"required\": [\n                \"fdc3Version\",\n                \"optionalFeatures\",\n                \"provider\"\n              ],\n              \"additionalProperties\": false\n            },\n            \"requestedName\": {\n              \"title\": \"Requested name\",\n              \"description\": \"The requested Desktop Agent name\",\n              \"type\": \"string\"\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The current state of the Desktop Agent's App and User channels (exclude any Private channels), as a mapping of channel id to an array of Context objects, one per type found in the channel, most recent first.\",\n              \"additionalProperties\": {\n                \"title\": \"Channel \",\n                \"type\": \"array\",\n                \"items\": {\n                  \"$ref\": \"../context/context.schema.json\"\n                }\n              }\n            },\n            \"authToken\": {\n              \"title\": \"Authentication Token\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"implementationMetadata\",\n            \"requestedName\",\n            \"channelsState\"\n          ]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 3 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\n            \"requestUuid\",\n            \"timestamp\"\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"payload\",\n        \"meta\"\n      ],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/connectionStep4AuthenticationFailed.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/connectionStep4AuthenticationFailed.schema.json\",\n  \"title\": \"ConnectionStep4AuthenticationFailed\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep4AuthenticationFailedBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep4AuthenticationFailedBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep4AuthenticationFailed\",\n      \"description\": \"Message sent by Bridge to Desktop Agent if their authentication fails.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 4 Message Type\",\n          \"const\": \"authenticationFailed\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 4 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"message\": {\n              \"title\": \"Authentication failed message\",\n              \"type\": \"string\"\n            }\n          },\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 4 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/connectionStep6ConnectedAgentsUpdate.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/connectionStep6ConnectedAgentsUpdate.schema.json\",\n  \"title\": \"ConnectionStep6ConnectedAgentsUpdate\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/ConnectionStep6ConnectedAgentsUpdateBase\"\n    },\n    {\n      \"$ref\": \"connectionStep.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"ConnectionStep6ConnectedAgentsUpdateBase\": {\n      \"type\":\"object\",\n      \"title\": \"ConnectionStep6ConnectedAgentsUpdateBase\",\n      \"description\": \"Message sent by Bridge to all Desktop Agent when an agent joins or leaves the bridge, includes the details of all agents, the change made and the expected channel state for all agents.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Connection Step 6 Message Type\",\n          \"const\": \"connectedAgentsUpdate\"\n        },\n        \"payload\": {\n          \"title\": \"Connection Step 6 Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"addAgent\": {\n              \"title\": \"Agents To Add\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent first connects to the bridge and provide its assigned name.\"\n            },\n            \"removeAgent\": {\n              \"title\": \"Agents To Remove\",\n              \"type\": \"string\",\n              \"description\": \"Should be set when an agent disconnects from the bridge and provide the name that no longer is assigned.\"\n            },\n            \"allAgents\": {\n              \"title\": \"All Connected Agents\",\n              \"type\": \"array\",\n              \"description\": \"Desktop Agent Bridge implementation metadata of all connected agents.\",\n              \"items\": {\n                \"$ref\": \"common.schema.json#/$defs/DesktopAgentImplementationMetadata\"\n              }\n            },\n            \"channelsState\": {\n              \"title\": \"Channel State\",\n              \"type\": \"object\",\n              \"description\": \"The updated state of channels that should be adopted by the agents. Should only be set when an agent is connecting to the bridge.\",\n              \"additionalProperties\": {\n                \"type\": \"array\",\n                  \"items\": {\n                    \"$ref\": \"../context/context.schema.json\"\n                  }\n              }\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"allAgents\"]\n        },\n        \"meta\": {\n          \"title\": \"Connection Step 6 Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/RequestUuid\"\n            },\n            \"responseUuid\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/ResponseUuid\"\n            },\n            \"timestamp\": {\n              \"$ref\": \"../api/common.schema.json#/$defs/Timestamp\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"requestUuid\", \"responseUuid\", \"timestamp\"]\n        }\n      },\n      \"required\": [\"type\", \"payload\", \"meta\"],\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentErrorResponse.schema.json\",\n  \"title\": \"FindInstances Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesErrorResponseBase\": {\n      \"title\": \"FindInstances Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindInstances Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentRequest.schema.json\",\n  \"title\": \"FindInstances Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesRequestBase\": {\n      \"title\": \"FindInstances Request\",\n      \"type\": \"object\",\n      \"description\": \"A request for details of instances of a particular app\",\n      \"properties\":{\n        \"type\": {\n          \"$ref\": \"../api/findInstancesRequest.schema.json#/$defs/FindInstancesRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesRequest.schema.json#/$defs/FindInstancesRequestPayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindInstances request metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"oneOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentResponse.schema.json\",\n  \"title\": \"FindInstances Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindInstancesResponseBase\": {\n      \"title\": \"FindInstances Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findInstances request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findInstancesResponse.schema.json#/$defs/FindInstancesSuccessResponsePayload\"\n        },\n        \"meta\": true\n      },\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeErrorResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentErrorResponse.schema.json#/$defs/FindInstancesErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeRequest.schema.json\",\n  \"title\": \"FindInstances Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentRequest.schema.json#/$defs/FindInstancesRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findInstancesBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeResponse.schema.json\",\n  \"title\": \"FindInstances Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findInstancesAgentResponse.schema.json#/$defs/FindInstancesResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentErrorResponseBase\": {\n      \"title\": \"FindIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentRequest.schema.json\",\n  \"title\": \"FindIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentRequestBase\": {\n      \"title\": \"FindIntent Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of apps available to resolve a particular intent and context pair.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentRequest.schema.json#/$defs/FindIntentRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentRequest.schema.json#/$defs/FindIntentRequestPayload\"\n        },\n        \"meta\": {\n          \"title\" : \"FindIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": true\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentResponse.schema.json\",\n  \"title\": \"FindIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentResponseBase\": {\n      \"title\": \"FindIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntent request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentResponse.schema.json#/$defs/FindIntentSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentErrorResponse.schema.json#/$defs/FindIntentErrorResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeRequest.schema.json\",\n  \"title\": \"FindIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentRequest.schema.json#/$defs/FindIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeResponse.schema.json\",\n  \"title\": \"FindIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentAgentResponse.schema.json#/$defs/FindIntentResponseBase\"\n    },\n\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextErrorResponseBase\": {\n      \"title\": \"FindIntentsByContext Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextRequestBase\": {\n      \"title\": \"FindIntentsByContext Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for details of intents and apps available to resolve them for a particular context.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextRequest.schema.json#/$defs/FindIntentsByContextRequestType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextRequest.schema.json#/$defs/FindIntentsByContextRequestPayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"FindIntentsByContextResponseBase\": {\n      \"title\": \"FindIntentsByContext Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a findIntentsByContext request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/findIntentsByContextResponse.schema.json#/$defs/FindIntentsByContextSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"FindIntentsByContext Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeErrorResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentErrorResponse.schema.json#/$defs/FindIntentsByContextErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeRequest.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentRequest.schema.json#/$defs/FindIntentsByContextRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/findIntentsByContextBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeResponse.schema.json\",\n  \"title\": \"FindIntentsByContext Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"findIntentsByContextAgentResponse.schema.json#/$defs/FindIntentsByContextResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataErrorResponseBase\": {\n      \"title\": \"GetAppMetadata Error Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentRequest.schema.json\",\n  \"title\": \"GetAppMetadata Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataRequestBase\": {\n      \"title\": \"GetAppMetadata Request\", \n      \"type\": \"object\",\n      \"description\": \"A request for metadata about an app\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataRequest.schema.json#/$defs/GetAppMetadataRequestType\"\n        },\n        \"payload\": {\n          \"type\": \"object\",\n          \"allOf\": [{\n            \"properties\": {\n              \"app\": {\n                \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n              }\n            },\n            \"required\": [\n              \"app\"\n            ]\n          },{\n            \"$ref\": \"../api/getAppMetadataRequest.schema.json#/$defs/GetAppMetadataRequestPayload\"\n          }]\n        },\n        \"meta\": {\n          \"title\" : \"GetAppMetadata Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/RequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentResponse.schema.json\",\n  \"title\": \"GetAppMetadata Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"GetAppMetadataResponseBase\": {\n      \"title\": \"GetAppMetadata Response\", \n      \"type\": \"object\",\n      \"description\": \"A response to a getAppMetadata request.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/getAppMetadataResponse.schema.json#/$defs/GetAppMetadataSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"GetAppMetadata Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeErrorResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentErrorResponse.schema.json#/$defs/GetAppMetadataErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeRequest.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentRequest.schema.json#/$defs/GetAppMetadataRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/getAppMetadataBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeResponse.schema.json\",\n  \"title\": \"GetAppMetadata Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"getAppMetadataAgentResponse.schema.json#/$defs/GetAppMetadataResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openAgentErrorResponse.schema.json\",\n  \"title\": \"Open Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenErrorResponseBase\": {\n      \"title\": \"Open Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request that contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openAgentRequest.schema.json\",\n  \"title\": \"Open Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenRequestBase\": {\n      \"title\": \"Open Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to open an application\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openRequest.schema.json#/$defs/OpenRequestType\"\n        },\n        \"payload\": {\n          \"title\": \"Open Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"app\": {\n              \"type\": \"object\",\n              \"title\": \"App to open\",\n              \"description\": \"The application to open on the specified Desktop Agent\",\n              \"allOf\": [\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/DesktopAgentIdentifier\"\n                },\n                {\n                  \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n                }\n              ]\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            }\n          },\n          \"required\": [\"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\":  {\n          \"title\": \"Open Request Metadata\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AgentDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"required\": [\"source\"],\n          \"additionalProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openAgentResponse.schema.json\",\n  \"title\": \"Open Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"OpenResponseBase\": {\n      \"title\": \"Open Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to an open request\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/openResponse.schema.json#/$defs/OpenSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"Open Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openBridgeErrorResponse.schema.json\",\n  \"title\": \"Open Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentErrorResponse.schema.json#/$defs/OpenErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openBridgeRequest.schema.json\",\n  \"title\": \"Open Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentRequest.schema.json#/$defs/OpenRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/openBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/openBridgeResponse.schema.json\",\n  \"title\": \"Open Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"openAgentResponse.schema.json#/$defs/OpenResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelBroadcastAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelBroadcastAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelBroadcastRequestBase\": {\n      \"title\": \"PrivateChannelBroadcast Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to broadcast on a PrivateChannel.\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel Broadcast Message type\",\n          \"const\": \"PrivateChannel.broadcast\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelBroadcast Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The Id of the PrivateChannel that the broadcast was sent on\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\",\n              \"title\": \"Context\",\n              \"description\": \"The context object that was the payload of a broadcast message.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"context\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelBroadcast Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelBroadcastBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelBroadcastBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelBroadcast Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelBroadcastAgentRequest.schema.json#/$defs/PrivateChannelBroadcastRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelEventListenerAddedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerAddedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerAddedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerAdded Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerAdded event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerAdded Message type\",\n          \"const\": \"PrivateChannel.eventListenerAdded\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the event listener was added to.\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/PrivateChannelEventType\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerAdded Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerAdded Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerAddedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerAddedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelEventListenerRemovedRequestBase\": {\n      \"title\": \"PrivateChannelEventListenerRemoved Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an EventListenerRemoved event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel EventListenerRemoved Message type\",\n          \"const\": \"PrivateChannel.eventListenerRemoved\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the event listener was removed from.\"\n            },\n            \"listenerType\": {\n              \"$ref\": \"../api/api.schema.json#/definitions/PrivateChannelEventType\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"listenerType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelEventListenerRemoved Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelEventListenerRemoved Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelEventListenerRemovedAgentRequest.schema.json#/$defs/PrivateChannelEventListenerRemovedRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnAddContextListenerRequestBase\": {\n      \"title\": \"PrivateChannelOnAddContextListener Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an AddContextListener event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnAddContextListener Message type\",\n          \"const\": \"PrivateChannel.onAddContextListener\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the context listener was added to.\"\n            },\n            \"contextType\": {\n              \"oneOf\": [\n                { \"type\": \"string\" },\n                { \"type\": \"null\" }\n              ],\n              \"title\": \"Context Type\",\n              \"description\": \"The type of the context listener added. Should be null for an untyped listener.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnAddContextListener Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnAddContextListener Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnAddContextListenerAgentRequest.schema.json#/$defs/PrivateChannelOnAddContextListenerRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnDisconnectAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnDisconnectAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnDisconnectRequestBase\": {\n      \"title\": \"PrivateChannelOnDisconnect Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on a Disconnect event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnDisconnect Message type\",\n          \"const\": \"PrivateChannel.onDisconnect\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the agent discconnected from.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnDisconnect Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnDisconnectBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnDisconnectBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnDisconnect Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnDisconnectAgentRequest.schema.json#/$defs/PrivateChannelOnDisconnectRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"PrivateChannelOnUnsubscribeRequestBase\": {\n      \"title\": \"PrivateChannelOnUnsubscribe Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to forward on an Unsubscribe event, relating to a PrivateChannel\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"Private Channel OnUnsubscribe Message type\",\n          \"const\": \"PrivateChannel.onUnsubscribe\"\n        },\n        \"payload\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"channelId\": {\n              \"type\": \"string\",\n              \"title\": \"Channel Id\",\n              \"description\": \"The id of the PrivateChannel that the context listener was unsubscribed from.\"\n            },\n            \"contextType\": {\n              \"oneOf\": [\n                { \"type\": \"string\" },\n                { \"type\": \"null\" }\n              ],\n              \"title\": \"Context Type\",\n              \"description\": \"The type of the context listener that was unsubscribed. Should be null for an untyped listener.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"channelId\", \"contextType\"]\n        },\n        \"meta\": {\n          \"title\": \"PrivateChannelOnUnsubscribe Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            },\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"unevaluatedProperties\": false\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json\",\n  \"title\": \"PrivateChannelOnUnsubscribe Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"privateChannelOnUnsubscribeAgentRequest.schema.json#/$defs/PrivateChannelOnUnsubscribeRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentErrorResponseBase\": {\n      \"title\": \"RaiseIntent Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent that contains an error.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentErrorResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentAgentRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentRequest.schema.json\",\n  \"title\": \"RaiseIntent Agent Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"agentRequest.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentRequestBase\": {\n      \"title\": \"RaiseIntent Request\",\n      \"type\": \"object\",\n      \"description\": \"A request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentRequest.schema.json#/$defs/RaiseIntentRequestType\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Request Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"intent\": {\n              \"type\": \"string\"\n            },\n            \"context\": {\n              \"$ref\": \"../context/context.schema.json\"\n            },\n            \"app\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            }\n          },\n          \"required\": [\"intent\", \"context\", \"app\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Request Metadata\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"requestUuid\": true,\n            \"timestamp\": true,\n            \"destination\": {\n              \"$ref\": \"common.schema.json#/$defs/AppDestination\"\n            },\n            \"source\": {\n              \"$ref\": \"common.schema.json#/$defs/AppRequestSource\"\n            }\n          },\n          \"unevaluatedProperties\": false,\n          \"required\": [\"requestUuid\",\"timestamp\",\"destination\",\"source\"] \n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResponseBase\": {\n      \"title\": \"RaiseIntent Response\",\n      \"type\": \"object\",\n      \"description\": \"A response to a request to raise an intent.\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResponse.schema.json#/$defs/RaiseIntentSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentErrorResponse.schema.json#/$defs/RaiseIntentErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentBridgeRequest.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeRequest.schema.json\",\n  \"title\": \"RaiseIntent Bridge Request\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentRequest.schema.json#/$defs/RaiseIntentRequestBase\"\n    },\n    {\n      \"$ref\": \"bridgeRequest.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentAgentResponse.schema.json#/$defs/RaiseIntentResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentResultAgentErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultAgentErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"agentErrorResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultErrorResponseBase\": {\n      \"title\": \"RaiseIntent Result Error Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result, which contains an error\",\n      \"properties\": {\n        \"type\": {\n          \"title\": \"RaiseIntent Result Response Message type\",\n          \"const\": \"raiseIntentResultResponse\"\n        },\n        \"payload\": {\n          \"title\": \"RaiseIntent Result Error Response Payload\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"error\": {\n              \"title\": \"RaiseIntent Result Error Message\",\n              \"oneOf\": [\n                { \"$ref\": \"../api/api.schema.json#/definitions/ResultError\" },\n                { \"$ref\": \"../api/api.schema.json#/definitions/BridgingError\" }\n              ]\n            }\n          },\n          \"required\": [\"error\"],\n          \"additionalProperties\": false\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentResultAgentResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultAgentResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Agent Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"agentResponse.schema.json\"\n    }\n  ],\n  \"$defs\": {\n    \"RaiseIntentResultResponseBase\": {\n      \"title\": \"RaiseIntent Result Response\",\n      \"type\": \"object\",\n      \"description\": \"A secondary response to a request to raise an intent used to deliver the intent result\",\n      \"properties\": {\n        \"type\": {\n          \"$ref\": \"../api/raiseIntentResultResponse.schema.json#/$defs/RaiseIntentResultResponseType\"\n        },\n        \"payload\": {\n          \"$ref\": \"../api/raiseIntentResultResponse.schema.json#/$defs/RaiseIntentResultSuccessResponsePayload\"\n        },\n        \"meta\": {\n          \"title\": \"RaiseIntent Result Response Metadata\",\n          \"type\": \"object\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentResultBridgeErrorResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultBridgeErrorResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Error Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentErrorResponse.schema.json#/$defs/RaiseIntentResultErrorResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeErrorResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridging/raiseIntentResultBridgeResponse.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultBridgeResponse.schema.json\",\n  \"title\": \"RaiseIntent Result Bridge Response\",\n  \"type\": \"object\",\n  \"allOf\": [\n    {\n      \"$ref\": \"raiseIntentResultAgentResponse.schema.json#/$defs/RaiseIntentResultResponseBase\"\n    },\n    {\n      \"$ref\": \"bridgeResponse.schema.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/bridgingAsyncAPI/README.md",
    "content": "# Agent Bridging AsyncAPI schema\n\nThis folder contains an AsyncAPI schema that may be used to generate clients and server stubs for Desktop Agent Bridging. It is based on references to the JSON schema files that define the various messages in the adjacent schemas/bridging folder.\n\nExample commands to generate code from the AsyncAPI schema:\n(run from the root of your FDC3 checkout)\n\nFirst run:\n\n```ps\nnpm install -g @asyncapi/generator\n```\n\nThen:\n\n- .NET\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/dotnet-nats-template -o ../some/path/outside/FDC3/folder\n    ```\n\n- Node.js\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/nodejs-ws-template -o ../some/path/outside/FDC3/folder -p server=local\n     ```\n\n- Markdown\n\n     ```ps\n     ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/markdown-template -o ../some/path/outside/FDC3/folder \n     ```\n\n- HTML\n\n    ```ps\n    ag --install schemas/bridgingAsyncAPI/bridgingAsyncAPI.json @asyncapi/html-template -o ../some/path/outside/FDC3/folder \n    ```\n"
  },
  {
    "path": "website/static/schemas/2.2/bridgingAsyncAPI/bridgingAsyncAPI.json",
    "content": "{\n    \"asyncapi\": \"2.6.0\",\n    \"info\": {\n        \"title\": \"Desktop Agent Bridge\",\n        \"version\": \"1.0.0\",\n        \"description\": \"API for an FDC3 Desktop Agent to communicate with an FDC3 Desktop Agent Bridge and through it, other Desktop Agents.\",\n        \"license\": {\n            \"name\": \"Apache 2.0\",\n            \"url\": \"https://www.apache.org/licenses/LICENSE-2.0\"\n        }\n    },\n    \"servers\": {\n        \"local\": {\n            \"url\": \"ws://localhost:4475\",\n            \"description\": \"Desktop agent bridge server exposing websocket connection\",\n            \"protocol\": \"ws\"\n        }\n    },\n    \"defaultContentType\": \"application/json\",\n    \"channels\": {\n        \"/\": {\n            \"publish\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/handshake\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/broadcastRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentRequest-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelBroadcast-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerAdded-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelEventListenerRemoved-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnAddContextListener-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnUnsubscribe-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/privateChannelOnDisconnect-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Agent\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Agent\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by A Desktop Agent to a Bridge\",\n                \"operationId\": \"Send\"\n            },\n            \"subscribe\": {\n                \"message\": {\n                    \"oneOf\": [\n                        {\n                            \"$ref\": \"#/components/messages/hello\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/authenticationFailed\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/connectedAgentsUpdate\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findInstancesErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/findIntentsByContextErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/getAppMetadataErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/openErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentErrorResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultResponse-Bridge\"\n                        },\n                        {\n                            \"$ref\": \"#/components/messages/raiseIntentResultErrorResponse-Bridge\"\n                        }\n                    ]\n                },\n                \"description\": \"Messages sent by a Bridge to a Desktop Agent\",\n                \"operationId\": \"Receive\"\n            }\n        }\n    },\n    \"components\": {\n        \"messages\": {\n            \"broadcastRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/broadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"hello\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep2Hello.schema.json#\"\n                }\n            },\n            \"handshake\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep3Handshake.schema.json#\"\n                }\n            },\n            \"authenticationFailed\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep4AuthenticationFailed.schema.json#\"\n                }\n            },\n            \"connectedAgentsUpdate\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/connectionStep6ConnectedAgentsUpdate.schema.json#\"\n                }\n            },\n            \"findInstancesRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentRequest.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findInstancesResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeResponse.schema.json#\"\n                }\n            },\n            \"findInstancesErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findInstancesBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentRequest.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeResponse.schema.json#\"\n                }\n            },\n            \"findIntentsByContextErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/findIntentsByContextBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentRequest.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeResponse.schema.json#\"\n                }\n            },\n            \"getAppMetadataErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/getAppMetadataBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"openRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentRequest.schema.json#\"\n                }\n            },\n            \"openResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"openResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeResponse.schema.json#\"\n                }\n            },\n            \"openErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/openBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"privateChannelBroadcast-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelBroadcastAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerAdded-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerAddedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelEventListenerRemoved-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelEventListenerRemovedAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnAddContextListener-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnAddContextListenerAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnDisconnect-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnDisconnectAgentRequest.schema.json#\"\n                }\n            },\n            \"privateChannelOnUnsubscribe-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/privateChannelOnUnsubscribeAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentRequest-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentRequest.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentBridgeErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Agent\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultAgentErrorResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeResponse.schema.json#\"\n                }\n            },\n            \"raiseIntentResultErrorResponse-Bridge\": {\n                \"payload\": {\n                    \"$ref\": \"../bridging/raiseIntentResultBridgeErrorResponse.schema.json#\"\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/action.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/action.schema.json\",\n  \"title\": \"Action\",\n  \"description\": \"A representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\\n\\nThe action may be completed by calling:\\n- `fdc3.raiseIntent()` with the specified Intent and Context\\n- `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\\n- `channel.broadcast()` with the specified Context, if the `broadcast` action has been defined.\\n\\nAccepts an optional `app` parameter in order to specify a specific app.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.action\" },\n        \"action\": {\n          \"title\": \"Action Type\",\n          \"description\": \"The **action** field indicates the type of action:\\n- **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent` or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if given).\\n- **broadcast** : If `broadcast` and a `channelId` are specified then `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the context to it with `channel.broadcast(context)`. If no `channelId` has been specified, the context should be broadcast to the current channel (`fdc3.broadcast()`)\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"broadcast\",\n            \"raiseIntent\"\n          ]\n        },\n        \"title\": {\n          \"title\": \"Action Title\",\n          \"description\": \"A human readable display name for the action\",\n          \"type\": \"string\"\n        },\n        \"intent\": {\n          \"title\": \"Action Intent\",\n          \"description\": \"Optional Intent to raise to perform the actions. Should reference an intent type name, such as those defined in the FDC3 Standard. If intent is not set then `fdc3.raiseIntentForContext` should be used to perform the action as this will usually allow the user to choose the intent to raise.\",\n          \"type\": \"string\"\n        },\n        \"context\": {\n          \"title\": \"Action Context\",\n          \"description\": \"A context object with which the action will be performed\",\n          \"$ref\": \"context.schema.json#\"\n        },\n        \"channelId\": {\n          \"title\": \"Channel ID\",\n          \"description\": \"Optional channel on which to broadcast the context. The `channelId` property is ignored unless the `action` is broadcast.\",\n          \"type\": \"string\"\n        },\n        \"app\": {\n          \"title\": \"Action Target App\",\n          \"description\": \"An optional target application identifier that should perform the action. The `app` property is ignored unless the action is raiseIntent.\",\n          \"$ref\": \"../api/api.schema.json#/definitions/AppIdentifier\"\n        }\n      },\n      \"required\": [\n        \"title\", \"context\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.action\",\n      \"action\": \"raiseIntent\",\n      \"title\": \"Click to view Chart\",\n      \"intent\": \"ViewChart\",\n      \"context\": {\n          \"type\": \"fdc3.chart\",\n          \"instruments\": [\n              {\n                  \"type\": \"fdc3.instrument\",\n                  \"id\": {\n                      \"ticker\": \"EURUSD\"\n                  }\n              }\n          ],\n          \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n          },\n          \"style\": \"candle\"\n      },\n      \"app\" :{\n          \"appId\": \"MyChartViewingApp\",\n          \"instanceId\": \"instance1\"\n      }\n    },\n    {\n      \"type\": \"fdc3.action\",\n      \"action\": \"broadcast\",\n      \"channelId\": \"Channel 1\",\n      \"title\": \"Click to view Chart\",\n      \"context\": {\n          \"type\": \"fdc3.chart\",\n          \"instruments\": [\n              {\n                  \"type\": \"fdc3.instrument\",\n                  \"id\": {\n                      \"ticker\": \"EURUSD\"\n                  }\n              }\n          ],\n          \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n          },\n          \"style\": \"candle\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/chart.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/chart.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Chart\",\n  \"description\": \"A context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\\n\\n- A list of instruments for comparison\\n- The time period to plot the chart over\\n- The style of chart (line, bar, mountain, candle etc.)\\n- Other settings such as indicators to calculate, or data representing drawings and annotations.\\n\\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chart\" },\n        \"instruments\": {\n          \"title\": \"Instruments to plot\",\n          \"description\": \"An array of instrument contexts whose data should be plotted.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        },\n        \"range\": {\n          \"title\": \"Time Range\",\n          \"description\": \"The time range that should be plotted\",\n          \"$ref\": \"timeRange.schema.json#\"\n        },\n        \"style\": {\n          \"title\": \"Chart style\",\n          \"description\": \"The type of chart that should be plotted\",\n          \"type\": \"string\",\n          \"enum\": [\t\"line\", \"bar\", \"stacked-bar\", \"mountain\", \"candle\", \"pie\", \"scatter\", \"histogram\", \"heatmap\", \"custom\"]\n        },\n        \"otherConfig\": {\n          \"title\": \"Other configuration\",\n          \"description\": \"It is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"context.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\"instruments\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chart\",\n      \"instruments\": [\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"AAPL\"\n              }\n          },\n          {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                  \"ticker\": \"GOOG\"\n              }\n          }\n      ],\n      \"range\": {\n          \"type\": \"fdc3.timeRange\",\n          \"startTime\": \"2020-09-01T08:00:00.000Z\",\n          \"endTime\": \"2020-10-31T08:00:00.000Z\"\n      },\n      \"style\": \"line\",\n      \"otherConfig\": [\n          {\n              \"type\": \"somevendor.someproduct.indicator\",\n              \"name\": \"stddev\",\n              \"parameters\": {\n                  \"period\": 10,\n                  \"matype\": \"exponential\"\n              }\n          },\n          {\n              \"type\": \"someothervendor.someotherproduct.formula\",\n              \"formula\": \"standard-deviation\",\n              \"fields\": {\n                  \"lookback\": 10,\n                  \"type\": \"ema\"\n              }\n          }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/chatInitSettings.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/chatInitSettings.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatInitSettings\",\n  \"description\": \"A collection of settings to start a new chat conversation\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.initSettings\" },\n        \"chatName\": {\n          \"title\": \"Chat name\",\n          \"description\": \"Name to apply to the chat created\",\n          \"type\": \"string\"\n        },\n        \"members\": {\n          \"title\": \"Chat members\",\n          \"description\": \"Contacts to add to the chat\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"message\": {\n          \"title\": \"Initial chat message\",\n          \"description\": \"An initial message to post in the chat when created.\",\n          \"oneOf\": [\n            {\n              \"type\": \"string\"\n            },\n            {\n              \"$ref\": \"message.schema.json#\"\n            }\n          ]\n        },\n        \"options\": {\n          \"title\": \"Chat options\",\n          \"description\": \"Option settings that affect the creation of the chat\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"groupRecipients\": {\n              \"title\": \"Group recipients option\",\n              \"description\": \"if false a separate chat will be created for each member\",\n              \"type\": \"boolean\"\n            },\n            \"isPublic\": {\n              \"title\": \"Public chat option\",\n              \"description\": \"if true the room will be visible to everyone in the chat application\",\n              \"type\": \"boolean\"\n            },\n            \"allowHistoryBrowsing\":  {\n              \"title\": \"Allow history browsing option\",\n              \"description\": \"if true members will be allowed to browse past messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowMessageCopy\":  {\n              \"title\": \"Allow message copy option\",\n              \"description\": \"if true members will be allowed to copy/paste messages\",\n              \"type\": \"boolean\"\n            },\n            \"allowAddUser\":  {\n              \"title\": \"All adding users option\",\n              \"description\": \"if true members will be allowed to add other members to the chat\",\n              \"type\": \"boolean\"\n            }\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.initSettings\",\n      \"chatName\": \"Chat ABCD\",\n      \"members\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john@mail.com\"\n            }\n          }\n        ]\n      },\n      \"options\": {\n        \"groupRecipients\": true,\n        \"isPublic\": false,\n        \"allowHistoryBrowsing\": true,\n        \"allowMessageCopy\": true\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n          \"0\": {\n            \"type\": \"fdc3.fileAttachment\",\n            \"data\": {\n              \"name\": \"myImage.png\",\n              \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n            }\n          }\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/chatMessage.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/chatMessage.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatMessage\",\n  \"description\": \"A context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\",\n  \"allOf\": [{\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": { \"const\": \"fdc3.chat.message\" },\n        \"chatRoom\": { \"$ref\": \"chatRoom.schema.json#\" },\n        \"message\": { \"$ref\": \"message.schema.json#\" }\n      },\n      \"required\": [\"type\", \"chatRoom\", \"message\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [{\n      \"type\": \"fdc3.chat.message\",\n      \"chatRoom\": {\n          \"type\": \"fdc3.chat.room\",\n          \"providerName\": \"Symphony\",\n          \"id\": {\n              \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n          }\n      },\n      \"message\": {\n        \"type\": \"fdc3.message\",\n        \"text\": {\n          \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n        },\n        \"entities\": {\n           \"0\": {\n               \"type\": \"fdc3.fileAttachment\",\n                \"data\": {\n                \"name\": \"myImage.png\",\n                      \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n                }\n            }\n        }\n      }\n  }]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/chatRoom.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/chatRoom.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatRoom\",\n  \"description\": \"Reference to the chat room which could be used to send a message to the room\",\n  \"allOf\": [{\n    \"type\": \"object\",\n    \"properties\": {      \n      \"type\": { \"const\": \"fdc3.chat.room\" },\n      \"providerName\": { \n        \"title\": \"Chat provider name\",\n        \"description\": \"The name of the service that hosts the chat\",\n        \"type\": \"string\"\n      },\n      \"id\": { \n        \"title\": \"Chat room id\",\n        \"description\": \"Identifier(s) for the chat - currently unstandardized\",\n        \"type\": \"object\",\n        \"additionalProperties\": {\n          \"type\": \"string\"\n        }\n      },\n      \"url\": { \n        \"title\": \"Chat URL\",\n        \"description\": \"Universal url to access to the room. It could be opened from a browser, a mobile app, etc...\",\n        \"type\": \"string\",\n        \"format\": \"uri\"\n      },\n      \"name\": {\n        \"title\": \"Chat name\",\n        \"description\": \"Display name for the chat room\",\n        \"type\": \"string\"\n      }\n    },\n    \"required\": [\"providerName\", \"id\"]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.room\",\n      \"providerName\": \"Symphony\",\n      \"id\": {\n          \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n      },\n      \"url\": \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n      \"name\": \"My new room\"\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/chatSearchCriteria.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/chatSearchCriteria.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ChatSearchCriteria\",\n  \"description\": \"A context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.chat.searchCriteria\"\n        },\n        \"criteria\": {\n          \"title\": \"Search Criteria array\",\n          \"description\": \"An array of criteria that should match chats returned from by a search.\\n\\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\\n\\nEmpty search criteria can be supported to allow resetting of filters.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/$defs/SearchCriteria\"\n          }\n        }\n      },\n      \"required\": [\n        \"criteria\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"$defs\": {\n    \"SearchCriteria\": {\n      \"title\": \"Search Criteria\",\n      \"description\": \"An individual criteria against which to match chat messages, based on an FDC3 context or free-text string.\",\n      \"oneOf\": [\n        {\n          \"$ref\": \"instrument.schema.json#\"\n        },\n        {\n          \"$ref\": \"organization.schema.json#\"\n        },\n        {\n          \"$ref\": \"contact.schema.json#\"\n        },\n        {\n          \"type\": \"string\",\n          \"title\": \"Free text\",\n          \"description\": \"Free text to be used for a keyword search\"\n        }\n      ]\n    }\n  },\n  \"examples\": [\n    {\n      \"type\": \"fdc3.chat.searchCriteria\",\n      \"criteria\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"TSLA\"\n          },\n          \"name\": \"Tesla, inc.\"\n        },\n        \"annual return\"\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/contact.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/contact.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Contact\",\n  \"description\": \"A person contact that can be engaged with through email, calling, messaging, CMS, etc.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contact\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Contact Identifiers\",\n          \"description\": \"Identifiers that relate to the Contact represented by this context\",\n          \"properties\": {\n            \"email\": {\n              \"type\": \"string\",\n              \"format\": \"email\",\n              \"title\": \"Email address\",\n              \"description\": \"The email address for the contact\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FDS ID\",\n              \"description\": \"FactSet Permanent Identifier representing the contact\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the contact\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/contactList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/contactList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"ContactList\",\n  \"description\": \"A collection of contacts, e.g. for chatting to or calling multiple contacts.\\n\\nThe contact list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.contactList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Contact List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the contact list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the contact list\"\n        },\n        \"contacts\": {\n          \"type\": \"array\",\n          \"title\": \"List of Contacts\",\n          \"description\": \"An array of contact contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"contact.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"contacts\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.contactList\",\n      \"contacts\": [\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"Jane Doe\",\n          \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n          }\n        },\n        {\n          \"type\": \"fdc3.contact\",\n          \"name\": \"John Doe\",\n          \"id\": {\n            \"email\": \"john.doe@mail.com\"\n          }\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/context.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/context.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Context\",\n  \"description\": \"The `fdc3.context` type defines the basic contract or \\\"shape\\\" for all data exchanged by FDC3 operations. As such, it is not really meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\\n\\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the object represents, and what shape it has.\\n\\nThe FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\",\n  \"allOf\": [\n    {\n      \"$ref\": \"#/definitions/DocumentedContext\"\n    },\n    {\n      \"$ref\": \"#/definitions/BaseContext\"\n    }\n  ],\n  \"definitions\": {\n    \"BaseContext\": {\n      \"$comment\": \"Base definition for the Context object WITHOUT documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\"\n        },\n        \"name\": {\n          \"type\": \"string\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"unevaluatedProperties\": {\"type\": \"string\" }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    },\n    \"DocumentedContext\": {\n      \"$comment\": \"Base definition for the Context object WITH documentation (which will be imported into all derived types unless separated).\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"Type\",\n          \"description\": \"The type property is the only _required_ part of the FDC3 context data schema. The FDC3 [API](https://fdc3.finos.org/docs/api/spec) relies on the `type` property being present to route shared context data appropriately.\\n\\nFDC3 [Intents](https://fdc3.finos.org/docs/intents/spec) also register the context data types they support in an FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview), used for intent discovery and routing.\\n\\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. For non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an organization-specific namespace, e.g. `blackrock.fund`.\\n\\nSee the [Context Data Specification](https://fdc3.finos.org/docs/context/spec) for more information about context data types.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"Context data objects may include a name property that can be used for more information, or display purposes. Some derived types may require the name object as mandatory, depending on use case.\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Id\",\n          \"description\": \"Context data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\\n\\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier. Identifier values SHOULD always be of type string.\",\n          \"unevaluatedProperties\": {\"type\": \"string\" }\n        }\n      },\n      \"additionalProperties\": true,\n      \"required\": [\n        \"type\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/country.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/country.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Country\",\n  \"description\": \"A country entity.\\n\\nNotes:\\n\\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement is for at least one standardized identifier to be provided\\n\\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\\n\\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.country\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code\"\n            },\n            \"COUNTRY_ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"COUNTRY_ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code\"\n            },\n            \"ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA2\",\n              \"description\": \"Two-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            },\n            \"ISOALPHA3\": {\n              \"type\": \"string\",\n              \"title\": \"ISOALPHA3\",\n              \"description\": \"Three-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\",\n              \"deprecated\": true\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the country\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.country\",\n      \"name\": \"Sweden\",\n      \"id\": {\n        \"COUNTRY_ISOALPHA2\": \"SE\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/currency.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/currency.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Currency\",\n  \"description\": \"A context representing an individual Currency.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.currency\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Currency name\",\n          \"description\": \"The name of the currency for display purposes\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"CURRENCY_ISOCODE\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[A-Z]{3}$\",\n              \"title\": \"CURRENCY_ISOCODE\",\n              \"description\": \"The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n            }\n          }\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.currency\",\n      \"name\": \"US Dollar\",\n      \"id\": {\n        \"CURRENCY_ISOCODE\": \"USD\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/email.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/email.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Email\",\n  \"description\": \"A collection of information to be used to initiate an email with a Contact or ContactList.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.email\"\n        },\n        \"recipients\": {\n          \"title\": \"Email Recipients\",\n          \"description\": \"One or more recipients for the email.\",\n          \"oneOf\": [\n            {\n              \"$ref\": \"contact.schema.json#\"\n            },\n            {\n              \"$ref\": \"contactList.schema.json#\"\n            }\n          ]\n        },\n        \"subject\": {\n          \"title\": \"Email Subject\",\n          \"description\": \"Subject line for the email.\",\n          \"type\": \"string\"\n        },\n        \"textBody\": {\n          \"title\": \"Email Body\",\n          \"description\": \"Body content for the email.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"recipients\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.email\",\n      \"recipients\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@example.com\"\n        }\n      },\n      \"subject\": \"The information you requested\",\n      \"textBody\": \"Blah, blah, blah ...\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/fileAttachment.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/fileAttachment.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"File Attachment\",\n  \"description\": \"A File attachment encoded in the form of a data URI. Can be added to a Message.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.fileAttachment\"\n        },\n        \"data\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"name\": {\n              \"type\": \"string\",\n              \"title\": \"File name\",\n              \"description\": \"The name of the attached file\"\n            },\n            \"dataUri\": {\n              \"type\": \"string\",\n              \"format\": \"uri\",\n              \"title\": \"\",\n              \"description\": \"A data URI encoding the content of the file to be attached\"\n            }\n          },\n          \"required\": [\n            \"name\",\n            \"dataUri\"\n          ]\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"data\"\n      ]\n    },\n    {\n      \"$ref\": \"context.schema.json#/definitions/BaseContext\"\n    }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.fileAttachment\",\n      \"data\": {\n        \"name\": \"myImage.png\",\n        \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/instrument.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/instrument.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Instrument\",\n  \"description\": \"A financial instrument from any asset class.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrument\"\n        },\n        \"id\": {\n          \"title\": \"Instrument identifiers\",\n          \"description\": \"Any combination of instrument identifiers can be used together to resolve ambiguity, or for a better match. Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified. In general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\\n\\nIt is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement is for at least one instrument identifier to be provided.\\n\\nTry to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define a property that makes it clear what the value represents. Doing so will make interpretation easier for the developers of target applications.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg security\",\n              \"description\": \"https://www.bloomberg.com/\"\n            },\n            \"CUSIP\": {\n              \"type\": \"string\",\n              \"title\": \"CUSIP\",\n              \"description\": \"https://www.cusip.com/\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"FactSet Permanent Security Identifier\",\n              \"description\": \"https://www.factset.com/\"\n            },\n            \"FIGI\": {\n              \"type\": \"string\",\n              \"title\": \"Open FIGI\",\n              \"description\": \"https://www.openfigi.com/\"\n            },\n            \"ISIN\": {\n              \"type\": \"string\",\n              \"title\": \"ISIN\",\n              \"description\": \"https://www.isin.org/\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv PERMID\",\n              \"description\": \"https://permid.org/\"\n            },\n            \"RIC\": {\n              \"type\": \"string\",\n              \"title\": \"Refinitiv Identification Code\",\n              \"description\": \"https://www.refinitiv.com/\"\n            },\n            \"SEDOL\": {\n              \"type\": \"string\",\n              \"title\": \"SEDOL\",\n              \"description\": \"https://www.lseg.com/sedol\"\n            },\n            \"ticker\": {\n              \"type\": \"string\",\n              \"title\": \"Stock ticker\",\n              \"description\": \"Unstandardized stock tickers\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the instrument\"\n        },\n        \"market\": {\n          \"description\": \"The `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"MIC\": {\n              \"type\": \"string\",\n              \"title\": \"Market Identifier Code\",\n              \"description\": \"https://en.wikipedia.org/wiki/Market_Identifier_Code\"\n            },\n            \"name\": {\n              \"type\": \"string\",\n              \"title\": \"Market Name\",\n              \"description\": \"Human readable market name\"\n            },\n            \"COUNTRY_ISOALPHA2\": {\n              \"type\": \"string\",\n              \"title\": \"Country ISO Code\",\n              \"description\": \"https://www.iso.org/iso-3166-country-codes.html\"\n            },\n            \"BBG\": {\n              \"type\": \"string\",\n              \"title\": \"Bloomberg Market Identifier\",\n              \"description\": \"https://www.bloomberg.com/\"\n            }\n          },\n          \"unevaluatedProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"required\": [\n        \"type\",\"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"name\": \"Microsoft\",\n      \"id\": {\n          \"ticker\": \"MSFT\",\n          \"RIC\": \"MSFT.OQ\",\n          \"ISIN\": \"US5949181045\"\n      },\n      \"market\": {\n          \"MIC\": \"XNAS\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/instrumentList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/instrumentList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"InstrumentList\",\n  \"description\": \"A collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist). However, when holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type.\\n\\nThe instrument list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.instrumentList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Instrument List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the instrument list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the instrument list\"\n        },\n        \"instruments\": {\n          \"type\": \"array\",\n          \"title\": \"List of instruments\",\n          \"description\": \"An array of instrument contexts that forms the list.\",\n          \"items\": {\n            \"$ref\": \"instrument.schema.json#\"\n          }\n        }\n      },\n      \"required\": [\n        \"instruments\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.instrumentList\",\n      \"instruments\": [\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"AAPL\"\n          },\n          \"market\": {\n            \"MIC\": \"XNAS\"\n          }\n        },\n        {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ISIN\": \"US5949181045\"\n          }\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/interaction.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/interaction.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Interaction\",\n  \"description\": \"An `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.interaction\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Interaction Id\",\n          \"description\": \"Can be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted. An interaction ID does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\",\n          \"properties\": {\n            \"URI\": {\n              \"type\": \"string\",\n              \"title\": \"Interaction URI\",\n              \"description\": \"Can be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\"\n            },\n            \"SALESFORCE\": {\n              \"type\": \"string\",\n              \"title\": \"Salesforce ID\",\n              \"description\": \"Interactions ID in Salesforce\"\n            },\n            \"SINGLETRACK\": {\n              \"type\": \"string\",\n              \"title\": \"SingleTrack ID\",\n              \"description\": \"Interaction ID in SingleTrack\"\n            }\n          }\n        },\n        \"participants\": {\n          \"title\": \"Interaction Participants\",\n          \"description\": \"A list of contacts involved in the interaction\",\n          \"$ref\": \"contactList.schema.json#\"\n        },\n        \"timeRange\": {\n          \"title\": \"Interaction Time range\",\n          \"description\": \"The time range over which the interaction occurred\",\n          \"$ref\": \"timeRange.schema.json#\"\n        },\n        \"interactionType\": {\n          \"title\": \"Interaction Type\",\n          \"description\": \"`interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\",\n          \"anyOf\": [\n            {\n              \"type\": \"string\",\n              \"enum\": [\n                \"Instant Message\",\n                \"Email\",\n                \"Call\",\n                \"Meeting\"\n              ]\n            },\n            {\n              \"type\": \"string\"\n            }\n          ]\n        },\n        \"description\": {\n          \"title\": \"Interaction Description\",\n          \"description\": \"A human-readable description of the interaction\",\n          \"type\": \"string\"\n        },\n        \"initiator\": {\n          \"title\": \"Interaction Initiator\",\n          \"description\": \"The contact that initiated the interaction\",\n          \"$ref\": \"contact.schema.json#\"\n        },\n        \"origin\": {\n          \"title\": \"Interaction Origin\",\n          \"description\": \"Used to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\",\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\n        \"participants\",\n        \"timeRange\",\n        \"interactionType\",\n        \"description\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.interaction\",\n      \"participants\": {\n        \"type\": \"fdc3.contactList\",\n        \"contacts\": [\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"Jane Doe\",\n            \"id\": {\n              \"email\": \"jane.doe@mail.com\"\n            }\n          },\n          {\n            \"type\": \"fdc3.contact\",\n            \"name\": \"John Doe\",\n            \"id\": {\n              \"email\": \"john.doe@mail.com\"\n            }\n          }\n        ]\n      },\n      \"interactionType\": \"Instant Message\",\n      \"timeRange\": {\n        \"type\": \"fdc3.timeRange\",\n        \"startTime\": \"2022-02-10T15:12:00Z\"\n      },\n      \"description\": \"Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum\",\n      \"initiator\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"origin\": \"Outlook\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/message.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/message.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Message\",\n  \"description\": \"A chat message to be sent through an instant messaging application. Can contain one or several text bodies (organized by mime-type, plaintext or markdown), as well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.message\"\n        },\n        \"text\": {\n          \"type\": \"object\",\n          \"title\": \"Message text\",\n          \"description\": \"A map of string mime-type to string content\",\n          \"properties\": {\n            \"text/plain\": {\n              \"type\": \"string\",\n              \"title\": \"Plain text\",\n              \"description\": \"Plain text encoded content.\"\n            },\n            \"text/markdown\": {\n              \"title\": \"Markdown text\",\n              \"description\": \"Markdown encoded content\",\n              \"type\": \"string\"\n            }\n          }\n        },\n        \"entities\": {\n          \"type\": \"object\",\n          \"title\": \"Message entities\",\n          \"description\": \"A map of string IDs to entities that should be attached to the message, such as an action to perform, a file attachment, or other FDC3 context object.\",\n          \"additionalProperties\": {\n            \"oneOf\": [\n              {\n                \"$ref\": \"action.schema.json#\"\n              },\n              {\n                \"$ref\": \"fileAttachment.schema.json#\"\n              }\n            ]\n          }\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.message\",\n      \"text\": {\n        \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate\"\n      },\n      \"entities\": {\n        \"picture1\": {\n          \"type\": \"fdc3.fileAttachment\",\n          \"data\": {\n            \"name\": \"myImage.png\",\n            \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n          }\n        },\n        \"eurusd_action\": {\n          \"type\": \"fdc3.action\",\n          \"title\": \"Click to view Chart\",\n          \"intent\": \"ViewChart\",\n          \"context\": {\n            \"type\": \"fdc3.chart\",\n            \"instruments\": [\n              {\n                \"type\": \"fdc3.instrument\",\n                \"id\": {\n                  \"ticker\": \"EURUSD\"\n                }\n              }\n            ],\n            \"range\": {\n              \"type\": \"fdc3.dateRange\",\n              \"starttime\": \"2020-09-01T08:00:00.000Z\",\n              \"endtime\": \"2020-10-31T08:00:00.000Z\"\n            },\n            \"style\": \"candle\"\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/nothing.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/nothing.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Nothing\",\n  \"description\": \"A type that explicitly represents a lack of context.\\n\\nNotes:\\n\\n- Intended to be used in situations where no context is desired.\\n- For example:\\n  - Raising an intent without context (e.g. opening a blank order form, or chat interface without a contact selected).\\n  - Resetting context on a channel (e.g. when context is used to set a filter in other applications a null context might release the filter).\\n- An explicit representation of a Null or empty context allows apps to declare support for a lack of context, for example in their intent metadata in an app directory.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.nothing\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.nothing\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/order.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/order.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Order\",\n  \"description\": \"@experimental context type representing an order. To be used with OMS and EMS systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human readable `name` field to be used to summarize the order and an optional `details` field that may be used to provide additional detail about the order, including a context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as a unspecified Context type, but both `details` and `details.product` are expected to be standardized in future.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.order\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Order Identifiers\",\n          \"description\": \"One or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the order.\"\n        },\n        \"details\": {\n          \"type\": \"object\",\n          \"title\": \"Order Details\",\n          \"description\": \"Optional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context\",\n          \"properties\": {\n            \"product\": {\n              \"$ref\": \"product.schema.json\"\n            }\n          },\n          \"additionalProperties\": true\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"id\"\n      ],\n      \"additionalProperties\": true\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.order\",\n      \"name\": \"...\",\n      \"id\": {\n        \"myOMS\": \"12345\"\n      },\n      \"details\": {\n        \"product\": {\n          \"type\": \"fdc3.product\",\n          \"id\": {\n            \"productId\": \"ABC123\"\n          },\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"ABC123\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/orderList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/orderList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"OrderList\",\n  \"description\": \"@experimental A list of orders. Use this type for use cases that require not just a single order, but multiple.\\n\\nThe OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.orderList\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Order List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the order list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable summary of the order list\"\n        },\n        \"orders\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"order.schema.json#\"\n          },\n          \"title\": \"List of Orders\",\n          \"description\": \"An array of order contexts that forms the list.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"orders\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.orderList\",\n      \"orders\": [\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"ABC123\"\n          }\n        },\n        {\n          \"type\": \"fdc3.order\",\n          \"id\": {\n            \"myOMS\": \"DEF456\"\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/organization.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/organization.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Organization\",\n  \"description\": \"An entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\\n\\nIt is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement is for at least one specified identifier to be provided.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.organization\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"title\": \"Organization Identifiers\",\n          \"description\": \"Identifiers for the organization, at least one must be provided.\",\n          \"minProperties\": 1,\n          \"properties\": {\n            \"LEI\": {\n              \"type\": \"string\",\n              \"title\": \"Legal Entity Identifier\",\n              \"description\": \"The Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO 17442 standard developed by the International Organization for Standardization (ISO). It connects to key reference information that enables clear and unique identification of legal entities participating in financial transactions.\"\n            },\n            \"PERMID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"Refinitiv Permanent Identifiers, or PermID for the organization\"\n            },\n            \"FDS_ID\": {\n              \"type\": \"string\",\n              \"title\": \"Organization\",\n              \"description\": \"FactSet Permanent Identifier representing the organization\"\n            }\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name of the organization\"\n        }\n      },\n      \"required\": [\n        \"id\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.organization\",\n      \"name\": \"Cargill, Incorporated\",\n      \"id\": {\n        \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n        \"FDS_ID\": \"00161G-E\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/portfolio.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/portfolio.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Portfolio\",\n  \"description\": \"A financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\\n\\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\\n\\nThe Portfolio type consists of an array of [Position](Position) types, each of which refers to a single [Instrument](Instrument) and a holding amount for that instrument.\\n\\nThe portfolio schema does not explicitly include identifiers in the `id` section, as there bis not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.portfolio\"\n        },\n        \"positions\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"position.schema.json#\"\n          },\n          \"title\": \"Portfolio positions\",\n          \"description\": \"The List of Positions which make up the Portfolio\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Portfolio Identifiers\",\n          \"description\": \"One or more identifiers that refer to the portfolio in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the portfolio\"\n        }\n      },\n      \"required\": [\n        \"positions\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.portfolio\",\n      \"positions\": [\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"AAPL\"\n            }\n          },\n          \"holding\": 2000000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"MSFT\"\n            }\n          },\n          \"holding\": 1500000\n        },\n        {\n          \"type\": \"fdc3.position\",\n          \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"IBM\"\n            }\n          },\n          \"holding\": 3000000\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/position.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/position.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Position\",\n  \"description\": \"A financial position made up of an instrument and a holding in that instrument. This type is a good example of how new context types can be composed from existing types.\\n\\nIn this case, the instrument and the holding amount for that instrument are required values.\\n\\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents multiple holdings in a combination of instruments.\\n\\nThe position schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.position\"\n        },\n        \"instrument\": {\n          \"$ref\": \"instrument.schema.json#\",\n          \"title\": \"The financial instrument that this position relates to\",\n          \"description\": \"\"\n        },\n        \"holding\": {\n          \"type\": \"number\",\n          \"title\": \"The size of the holding represented by this position\",\n          \"description\": \"The amount of the holding, e.g. a number of shares\"\n        },\n        \"id\": {\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          },\n          \"title\": \"Position Identifiers\",\n          \"description\": \"One or more identifiers that refer to the position in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the position\"\n        }\n      },\n      \"required\": [\n        \"instrument\",\n        \"holding\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"AAPL\"\n        }\n      },\n      \"holding\": 2000000\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/product.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/context/product.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Product\",\n\t\"description\": \"@experimental context type representing a tradable product. To be used with OMS and EMS systems.\\n\\nThis type is currently only loosely defined as an extensible context object, with an optional instrument field.\\n\\nThe Product schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.product\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Product Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Product Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the product.\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"$ref\": \"instrument.schema.json\",\n\t\t\t\t\t\"title\": \"Product Instrument\",\n\t\t\t\t\t\"description\": \"A financial instrument that relates to the definition of this product\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\",\n\t\t\t\t\"id\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\"id\": {\n\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t},\n\t\t\t\"instrument\": {\n\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/timeRange.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/timeRange.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TimeRange\",\n  \"description\": \"A context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\\n\\n- A pricing chart\\n- A trade blotter\\n- A record of client contact/activity in a CRM\\n\\nExample use cases:\\n\\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\\n\\nNotes:\\n\\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\\n  - A timezone indicator should be specified, e.g. `\\\"2022-05-12T15:18:03Z\\\"` or `\\\"2022-05-12T16:18:03+01:00\\\"`\\n  - Times MAY be specified with millisecond precision, e.g. `\\\"2022-05-12T15:18:03.349Z\\\"`\",\n  \"allOf\": [\n    {\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.timeRange\"\n        },\n        \"startTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Start Time\",\n          \"description\": \"The start time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        },\n        \"endTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"End Time\",\n          \"description\": \"The end time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\"\n        }\n      }\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"anyOf\": [\n    {\n      \"required\": [\n        \"startTime\",\n        \"endTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"startTime\"\n      ]\n    },\n    {\n      \"required\": [\n        \"endTime\"\n      ]\n    }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44Z\",\n      \"endTime\": \"2022-04-30T23:59:59Z\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"startTime\": \"2022-03-30T15:44:44+00:00\"\n    },\n    {\n      \"type\": \"fdc3.timeRange\",\n      \"endTime\": \"2022-03-30T16:44:44.123Z\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/trade.schema.json",
    "content": "{\n\t\"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\t\"$id\": \"https://fdc3.finos.org/schemas/2.2/context/trade.schema.json\",\n\t\"type\": \"object\",\n\t\"title\": \"Trade\",\n\t\"description\": \"@experimental context type representing a trade. To be used with execution systems.\\n\\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as a unspecified Context type, but `product` is expected to be standardized in future.\\n\\n The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n\t\"allOf\": [\n\t\t{\n\t\t\t\"type\": \"object\",\n\t\t\t\"properties\": {\n\t\t\t\t\"type\": {\n\t\t\t\t\t\"const\": \"fdc3.trade\"\n\t\t\t\t},\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"additionalProperties\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"title\": \"Trade Identifiers\",\n\t\t\t\t\t\"description\": \"One or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\"\n\t\t\t\t},\n\t\t\t\t\"name\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"title\": \"Trade Name\",\n\t\t\t\t\t\"description\": \"A human-readable summary of the trade.\"\n\t\t\t\t},\n\t\t\t\t\"product\": {\n\t\t\t\t\t\"$ref\": \"product.schema.json\",\n\t\t\t\t\t\"title\": \"Traded product\",\n\t\t\t\t\t\"description\": \"A product that is the subject of the trade.\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"required\": [\n\t\t\t\t\"type\", \"id\", \"product\"\n\t\t\t],\n\t\t\t\"additionalProperties\": true\n\t\t},\n\t\t{ \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n\t],\n\t\"examples\": [\n\t\t{\n\t\t\t\"type\": \"fdc3.trade\",\n\t\t\t\"name\": \"...\",\n\t\t\t\"id\": {\n\t\t\t\t\"myEMS\": \"12345\"\n\t\t\t},\n\t\t\t\"product\": {\n\t\t\t\t\"type\": \"fdc3.product\",\n\t\t\t\t\"id\": {\n\t\t\t\t\t\"productId\": \"ABC123\"\n\t\t\t\t},\n\t\t\t\t\"instrument\": {\n\t\t\t\t\t\"type\": \"fdc3.instrument\",\n\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\"ticker\": \"MSFT\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "website/static/schemas/2.2/context/tradeList.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/tradeList.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TradeList\",\n  \"description\": \"@experimental A list of trades. Use this type for use cases that require not just a single trade, but multiple.\\n\\nThe TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.tradeList\"\n        },\n        \"trades\": {\n          \"title\": \"List of Trades\",\n          \"description\": \"An array of trade contexts that forms the list.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"trade.schema.json#\"\n          }\n        },\n        \"id\": {\n          \"title\": \"Trade List Identifiers\",\n          \"description\": \"One or more identifiers that refer to the trade list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\",\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          }\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"Name\",\n          \"description\": \"An optional human-readable name for the trade list\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"trades\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.tradeList\",\n      \"trades\": [\n        {\n          \"type\": \"fdc3.trade\",\n          \"name\": \"...\",\n          \"id\": {\n            \"myEMS\": \"12345\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"ABC123\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"MSFT\"\n              }\n            }\n          }\n        },\n        {\n          \"type\": \"fdc3.trade\",\n          \"id\": {\n            \"myEMS\": \"67890\"\n          },\n          \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"DEF456\"\n            },\n            \"instrument\": {\n              \"type\": \"fdc3.instrument\",\n              \"id\": {\n                \"ticker\": \"TSLA\"\n              }\n            }\n          }\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/transactionresult.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/transactionresult.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"TransactionResult\",\n  \"description\": \"A context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an `IntentResult` by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.transactionResult\"\n        },\n        \"status\": {\n          \"type\": \"string\",\n          \"enum\": [\n            \"Created\",\n            \"Deleted\",\n            \"Updated\",\n            \"Failed\"\n          ],\n          \"title\": \"Transaction Status\",\n          \"description\": \"The status of the transaction being reported.\"\n        },\n        \"context\": {\n          \"$ref\": \"context.schema.json#\",\n          \"title\": \"Transaction Result Context\",\n          \"description\": \"A context object returned by the transaction, possibly with updated data.\"\n        },\n        \"message\": {\n          \"type\": \"string\",\n          \"title\": \"Transaction Message\",\n          \"description\": \"A human readable message describing the outcome of the transaction.\"\n        }\n      },\n      \"required\": [\n        \"type\",\n        \"status\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.transactionResult\",\n      \"status\": \"Updated\",\n      \"context\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n    }\n  ]\n}"
  },
  {
    "path": "website/static/schemas/2.2/context/valuation.schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/valuation.schema.json\",\n  \"type\": \"object\",\n  \"title\": \"Valuation\",\n  \"description\": \"A context type representing the price and value of a holding.\",\n  \"allOf\": [\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"const\": \"fdc3.valuation\"\n        },\n        \"value\": {\n          \"type\": \"number\",\n          \"title\": \"Value\",\n          \"description\": \"The value of the holding, expresses in the nominated currency.\"\n        },\n        \"price\": {\n          \"type\": \"number\",\n          \"title\": \"Price per unit\",\n          \"description\": \"The price per unit the the valuation is based on.\"\n        },\n        \"CURRENCY_ISOCODE\": {\n          \"type\": \"string\",\n          \"pattern\": \"^[A-Z]{3}$\",\n          \"title\": \"Valuation Currency\",\n          \"description\": \"The valuation currency, which should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\"\n        },\n        \"valuationTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Valuation time\",\n          \"description\": \"The time at which the valuation was performed, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        },\n        \"expiryTime\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"title\": \"Expiry Time\",\n          \"description\": \"The time at which this valuation expires, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\"\n        }\n      },\n      \"required\": [\n        \"value\",\n        \"CURRENCY_ISOCODE\"\n      ]\n    },\n    { \"$ref\": \"context.schema.json#/definitions/BaseContext\" }\n  ],\n  \"examples\": [\n    {\n      \"type\": \"fdc3.valuation\",\n      \"value\": 500.0,\n      \"price\": 5.0,\n      \"CURRENCY_ISOCODE\": \"USD\",\n      \"expiryTime\": \"2022-05-13T16:16:24+01:00\"\n    }\n  ]\n}"
  },
  {
    "path": "website/versioned_docs/version-1.0/api/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\n```typescript\ntype Context = object;\n```\n\nThe base object that all contexts should extend.\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/api/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\n## Methods\n\n### `open`\n\n```typescript\nopen(name: string, context?: Context): Promise<void>;\n```\n\nLaunches/links to an app by name.\n\nIf a [`Context`](Context) object is passed in, this object will be provided to the opened application via a contextListener.\nThe Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\nIf opening errors, it returns an `Error` with a string from the [`OpenError`](Errors#openerror) enumeration.\n\n#### Example\n ```javascript\n//no context\nawait agent.open('myApp');\n\n//with context\nawait agent.open('myApp', context);\n```\n\n#### See also\n* [`Context`](Context)\n* [`OpenError`](Errors#openerror)\n\n### `findIntent`\n\n```typescript\nfindIntent(intent: string, context?: Context): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context.\n\n_findIntent_ is effectively granting programmatic access to the Desktop Agent's resolver. \nIt returns a promise resolving to the intent, its metadata and metadata about the apps that are registered to handle it.\nThis can be used to raise the intent against a specific app.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n\n#### Examples\n```javascript\n// I know 'StartChat' exists as a concept, and want to know more about it ...\nconst appIntent = await agent.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }\n\n// raise the intent against a particular app\nawait agent.raiseIntent(appIntent.intent.name, context, appIntent.apps[0].name);\n```\n\n#### See also\n* [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```typescript\nfindIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context.\n_findIntentsByContext_ is effectively granting programmatic access to the Desktop Agent's resolver. \nA promise resolving to all the intents, their metadata and metadata about the apps that registered as handlers is returned, based on the context types the intents have registered.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n \n #### Examples\n ```javascript\n // I have a context object, and I want to know what I can do with it, hence, I look for intents...\n const appIntents = await agent.findIntentsByContext(context);\n \n // returns, for example:\n // [{\n //     intent: { name: \"StartCall\", displayName: \"Call\" },\n //     apps: [{ name: \"Skype\" }]\n // },\n // {\n //     intent: { name: \"StartChat\", displayName: \"Chat\" },\n //     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n // }];\n \n // select a particular intent to raise\n const startChat = appIntents[1];\n \n // target a particular app\n const selectedApp = startChat.apps[0];\n \n // raise the intent, passing the given context, targeting the app\n await agent.raiseIntent(startChat.intent.name, context, selectedApp.name);\n ```\n\n#### See also\n   * [`ResolveError`](Errors#resolveerror)\n\n### `broadcast`\n```typescript\nbroadcast(context: Context): void;\n```\n\nPublishes context to other apps on the desktop.\n\n#### Examples\n```javascript\nagent.broadcast(context);\n```\n#### See also\n* [addContextListener](#addcontextlistener)\n\n### `raiseIntent`\n\n```typescript\nraiseIntent(intent: string, context: Context, target?: string): Promise<IntentResolution>;\n```\nRaises an intent to the desktop agent to resolve.\n#### Examples\n```javascript\n//raise an intent to start a chat with a given contact\nconst intentR = await agent.findIntents(\"StartChat\", context);\n//use the IntentResolution object to target the same chat app with a new context\nagent.raiseIntent(\"StartChat\", newContext, intentR.source);\n```\n#### See also\n* [`IntentResolution`](#intentresolution)\n\n### `addIntentListener`\n```typescript\naddIntentListener(intent: string, handler: (context: Context) => void): Listener;\n```\n Adds a listener for incoming Intents from the Agent.\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n### `addContextListener`\n```typescript\naddContextListener(handler: (context: Context) => void): Listener;\n```\nAdds a listener for incoming context broadcast from the Desktop Agent.\n\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n## Return Types\n\n### `AppIntent`\n\n```typescript\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\nAn interface that represents the binding of an intent to apps\n\n#### See also\n* [`IntentMetadata`](#intentmetadata)\n* [`AppMetadata`](#appmetadata)\n\n### `IntentMetadata`\n\n```typescript\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n### `AppMetadata`\n\n```typescript\ninterface AppMetadata {\n  name: string;\n}\n```\n\nApp metadata is Desktop Agent specific - but should always support a name property.\n\n### `IntentResolution`\n\n```typescript\ninterface IntentResolution {\n  source: string;\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n \n#### Example\n```javascript\n//resolve a \"Chain\" type intent\nvar intentR = await agent.raiseIntent(\"intentName\", context);\n//resolve a \"Client-Service\" type intent with data response\nvar intentR = await agent.raiseIntent(\"intentName\", context);\nvar dataR = intentR.data;\n```\n\n#### See also\n* [`DesktopAgent.raiseIntent`](#raiseintent)\n\n\n### `Listener`\n\n```typescript\ninterface Listener {\n  unsubscribe();\n}\n```\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](#addintentlistener) or [`addContextListener`](#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\nThe `unsubscribe` method on the listener object allows the application to cancel the subscription.\n\n#### See also\n* [`DesktopAgent.addIntentListener`](#addintentlistener)\n* [`DesktopAgent.addContextListener`](#addcontextlistener)\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/api/Errors.md",
    "content": "---\nsidebar_label: Errors\ntitle: Errors\nhide_title: true\noriginal_id: Errors\n---\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n* [`DesktopAgent.open`](DesktopAgent#open)\n\n\n## `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.0/api/api-intro.md",
    "content": "---\nsidebar_label: API Overview\ntitle: API Overview\nhide_title: true\noriginal_id: api-intro\n---\n# API Overview\n\nFDC3 API standards support the following goals:\n- Create a consistent developer interface for working with FDC3 \n- Standardize interfaces for reference implementations\n- Standardize interfaces between Desktop Agents\n\nThe role of FDC3 API standards is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications - standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary its importance.\n\nThe focus on the API working group has been to create a small but consistent API, the following docs go through the components and API's in detail.\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/api/api-spec.md",
    "content": "---\nsidebar_label: API Specification\ntitle: API Specification 1.0\noriginal_id: api-spec\n---\n\n## Components\n### Desktop Agent\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- OpenFin\n- Autobahn\n- ThomsonReuters Eikon\n\nDesktop Agents expose an FDC3 standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n#### Inter-Agent Communication\nA goal of FDC3 standards is that applications running in different Desktop Agent contexts on the same desktop would be able to interoperate.  And that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\nDesktop Agent interop is supported by common standards for APIs for App discovery and launching.  So, an App in one Desktop Agent context would not need to know a different syntax to call an App in another Desktop Agent context.\n\nThe actual connection protocol between Desktop Agents is not currently in scope for FDC3 standards.  Given that there are a relatively small number of Desktop Agents, and that any given desktop will have a finite and relatively static number of Desktop Agents installed at any given time, the connectivity between different Agents can be adequately handled for the time being on a case-by-case basis.\n\n### Application\nAn application is any endpoint on the desktop that is:\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of End Points include:\n- Native Applications\n- PWA/Web Applications\n- Headless “services” running on the desktop\n\n## Functional Use Cases\n### Open an Application by Name\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Raising Intents\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that Intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).   Currently, this is the primary focus in FDC3\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client.  Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n#### Intent Resolution\nRaising an Intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n##### Resolve\n- Intent was resolved unambiguously and the receiving app was launched successfully.\n- Intent was ambiguous, a resolution was chosen by the end user and the chosen application was launched successfully.\n\n##### Reject\n- An app matching the intent was not found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n##### Resolution Object\nIf the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format:\n\n```javascript\n{\n    source: String;\n    data?: Object;\n    version: String;\n}\n```\n- *source* = identifier for the Application resolving the intent (null if the intent could not be resolved)\n- *data* = return data structure - if one is provided for the given intent\n- *version* = the version number of the Intents schema being used\n\nFor example\n\n```javascript\ntry {\n    let result = await agent.raiseIntent('StageOrder');\n    if (result.data){\n        let orderId = result.data.id;\n    }\n}\ncatch (er){\n    console.log(er.message);\n}\n\n```\n\n##### Upgrading to a Remote API Connection\nThere are a wide range of workflows where decoupled intents and/or context passing do not provide rich enough interactivity and applications are better off exposing proprietary APIs.  In these cases, an App can use the *source* property on the resolution of an intent to connect directly to another App and from there, call remote APIs using the methods available in the Desktop Agent context for the App.  For example:\n\n```javascript\n    let chart = await agent.raiseIntent('ViewChart');\n     //construct an OpenFin wrapper for the App\n    let chartApp = fin.Application.wrap(chart.source);\n    //do some OpenFin specific stuff\n```\n![Upgrading Connection to Remote API](/assets/api-3.png)\n\n### Register an Intent\nApplications 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.\n\n#### Compliance with Intent Standards\nIntents 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.\n\nIt is expected that App Directories will also curate listed apps and ensure that they are complying with declared intents.\n\nLike FDC3 Context Data, the Intent schemas need to be versioned.  Desktop Agents will be responsible to declare which version of the Intent schema they are using.   Applications may also assert a specific version requirement when raising an Intent.  Version negotiation may be supported by a given Desktop Agent.\n\n### Send/broadcast context\nOn the financial desktop, applications often want to broadcast context to any number of applications.  Context sharing needs to support concepts of different groupings of applications as well as data privacy concerns.  Each Desktop Agent will have its own rules for supporting these features.\n\n## Resolvers\nIntents functionality is dependent on resolver functionality to map the intent to a specific App.  This will often require end-user input.  Resolution can either be performed by the Desktop Agent (raising UI to pick the desired App for the intent) or by the app launching the intent - in which case the calling App will handle the resolution itself (using the findIntents API below) and then invoke an explicit Intent object.\n\n## APIs\nThe APIs are defined in TypeScript in [src], with the documentation generated in the [docs] folder.\n\n[src]: https://github.com/finos/FDC3/tree/main/src/api\n[docs]: https://github.com/finos/FDC3/tree/main/docs/api\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/appd-discovery.md",
    "content": "---\nsidebar_label: App Directory Discovery\ntitle: App Directory Discovery\nhide_title: true\noriginal_id: appd-discovery\n---\n\n# App Directory Discovery\n\n## Simple Definition\n\nThe App Directory (AppD) is a service that provides a financial application definition that includes a trusted identifier(s) and associated metadata. The information registered as part of an application definition supports discovery, launch configuration, intents and context data supporting the use and interoperability of financial applications.\n\n## Topology\n\nAppD services shall support a distributed or detached model to managing application data servicing, where there are (N) AppD services on a network providing information related to a subset of namespace \"zones\" that align with the financial application identifiers. This approach encourages independence, scale and responsive provisioning of application definitions. This is modeled from a subset of the public name service \"Domain Name System\", which has proven reliable and conceptually fit for discovery.\n\n## Service Discovery Approach\n\nIn order to support the discovery of application data stored in a given directory, name space concepts are introduced to both identify the realm of application definitions and AppD service locations that host data. In simple terms, there has to be a way of discovering the location of the AppD service itself and the associated application definitions that are available from that service.\n\n### Application Identifier\n\n- Application data discovery through nested namespace approach and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n### Resolving host system\n\n- AppD service host discovery implementations should support the following requirements;\n  1. Discovery of the AppD location using the fully qualified application ID domain name. This would be the fqdn part of the email structure.\n  2. Discovery of the AppD location using the fully qualified application ID domain name to lookup DNS SRV records identifying the host server location and access TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782) )\n  3. Statically defined URI records for use within client applications directly. This is similar to #1 above, but provides explicit protocol, port and url definitions as part of the defintion.\n\n**Examples:**\n\n*AppD service through DNS / SRV records:*\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/appd_srv.png?version=1&modificationDate=1530189735237&cacheVersion=1&api=v2&width=958&height=250)\n\nAppD Service distribution visual:\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/AppDServiceDistribution.png?version=1&modificationDate=1526307911273&cacheVersion=1&api=v2&width=498&height=250)\n\n## Application data discovery\n\nApplication data discovery shall be accessible through a unique application identifier (AppId) representing a single application represented by a nested namespace syntax using dot notation and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n**Example:**\n\n```\ngetAppData(\"app@sub.root\")\n\n    Application {\n      \"appId\": \"app@sub.root\",\n      \"name\": \"App Name\",\n      \"manifest\": \"https://sub.root/app_manifest.json\",\n      \"manifestType\": \"vendor_type\",\n      \"version\": \"1\",\n      \"title\": \"A very cool App\",\n      \"tooltip\": \"A very cool app really\",\n      \"description\": \"Yes..this is the coolest app ever..\",\n      \"images\": [\n        {\n          \"url\": \"string\"\n        }\n      ],\n      \"contactEmail\": \"string\",\n      \"supportEmail\": \"string\",\n      \"publisher\": \"string\",\n      \"icons\": [\n        {\n          \"icon\": \"string\"\n        }\n      ],\n      \"customConfig\": [\n        {\n          \"name\": \"string\",\n          \"value\": \"string\"\n        }\n      ],\n      \"intents\": [\n        {\n          \"name\": \"string\",\n          \"displayName\": \"string\",\n          \"contexts\": [\n            \"string\"\n          ],\n          \"customConfig\": {}\n        }\n      ]\n    }\n```\n\n## Service Discovery (Expanded)\n\nThe following represents the three ways AppD service instances should be discovered over a given network. Again, the view is that AppD services are distributed/decoupled based on associated application namespace on a given network. This takes into account the use of the application identifiers described in previous section. A launcher is required to use a URI (e.g. \"https://appd.foo.com/api/appd/app1@appd.foo.com\") to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required. This proposal focuses on the following approaches to achieve this resolution.\n\n### Application ID namespace syntax host resolution\n\nAn application directory URI can be constructed using a fully qualified application ID (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application name \"app1\" with a fully qualified identifier of \"app1@appd.foo.com\" an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" may resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by;\n\n1. URI protocol is defaulted to https, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default https/443, but can be overridden by the launcher\n4. URI url is by default \"/api/**(service)/(version)\" .**  It is recommended that we identify service label as \"**appd**\" with version being optional. Calls that are made without version automatically default to latest \"/api/appd/app1\" vs \"/api/appd/v1/app1\"\n\nThe resulting URI to retrieve application data for \"app1\" would be \"[https://appd.foo.com/api/appd/v1/app1@appd.foo.com](https://appd.foo.com/api/appd/v1/app1.appd.foo.com)\"\n\n###  Application identifiers, Shrinking the URI and AppdD defaults\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record. An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface. Taking the prior example, the fully qualified application ID \"app1@appd.foo.com\" is represented as \"app1\" within the application directory. As a result a launcher can use a shortened URI construct \"[https://appd.foo.com/api/appd/v1/app1](https://appd.foo.com/api/appd/v1/app1)\" to resolve the application data vs \"https://appd.foo.com/api/appd/v1/app1@appd.foo.com\".\n\n### DNS/SRV Records\n\nAnother approach to support AppD service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an AppD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *service*: the symbolic name of the desired service. For AppD service, this must be identified as \"**_appd**\"\n- *proto*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol). For AppD service **_tcp** must be used.\n- *name*: the domain name for which this record is valid, ending in a dot. For AppD service,  the name should directly map to the application identifier domain.\n- *TTL*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *class*: standard DNS class field (this is always *IN*).\n- *priority*: the priority of the target host, lower value means more preferred.\n- *weight*: A relative weight for records with the same priority, higher value means more preferred.\n- *port*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *target*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record **must use** the following definitions:\n\n- service = **_appd**\n- proto = **_tcp**\n- name = must map to the domain of the application identifier . Example:  the **name** for application identifier **\"app1.appd.foo.com\"** would be **\"appd.foo.com\"**\n\n**Known domains:**\n\nAlthough SRV records provide the means of resolving the location of an AppD service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that  the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n\n### Static configuration\n\nAs the name implies, a static configuration for the AppD service location is predefined within the launcher following the same domain:URI model mentioned in previous sections.\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/StaticConfig.png?version=1&modificationDate=1526330937517&cacheVersion=1&api=v2&width=800&height=376)\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/appd-intro.md",
    "content": "---\nsidebar_label: App Directory Overview\ntitle: App Directory Overview\nhide_title: true\noriginal_id: appd-intro\n---\n\n# App Directory Overview\n\nThe FDC3 App Directory provides trusted identity for financial desktop apps. This identity can be used to prevent spoofing and man-in-the-middle attacks when apps communicate with one another and exchange data. The App Directory also enables service discovery. Apps are registered with a declaration of the intents and context data that can be used when interoperating.\n\n## Core features\n\n- Provide verification of identity for an application running on a desktop - whether it is Native, Web, or Hybrid.\n- Resolve human readable names for applications to the location of and instructions for launching\n- Serve as a repository for application metadata supporting discoverability by intent, context, and other workflow driven facets.\n\n## Sections to review\n\n- [Application Directory Discovery](appd-discovery) describes how to resolve the location of the Application Directory using an application identifier.\n- [Application Directory Use](appd-use) provides a simple view on how application directories can be used.  This also includes links to a reference implementation.\n- [API specification](appd-spec) is the interface definition required to support a compatible application directory.\n\nThe keywords \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in BCP 14, [RFC 2119](https://tools.ietf.org/id/draft-faltstrom-uri-11.html#RFC2119) [RFC2119]."
  },
  {
    "path": "website/versioned_docs/version-1.0/appd-spec.md",
    "content": "---\nsidebar_label: App Directory Specification\ntitle: App Directory Specification 1.0\noriginal_id: appd-spec\n---\n## API\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/1.0/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://raw.githubusercontent.com/finos/FDC3/v1.0/src/app-directory/specification/appd.yaml\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v1/apps`         | POST   | Create a new application definition\n `/v1/apps/{appId}` | GET    | Retrieve an application defintion\n `/v1/apps/search`  | GET    | Retrieve a list of applications\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/appd-use.md",
    "content": "---\nsidebar_label: App Directory Use\ntitle: App Directory Use\nhide_title: true\noriginal_id: appd-use\n---\n\n# App Directory Use\n\nAn application directory (AppD) provides information about an application's\nidentifiers, intents that provide contexts, and location of metadata providing\ninformation specific to the launching and integration of the application.\n\nIn the real world the AppD would support many use cases as defined in the\n[FDC3 Use Cases](use-cases/overview)\n\nThe following provides some common use cases and benefits.\n\n## Embedded Launcher\nA desktop application has the ability to launch (or initialize) an application\nby retrieving all necessary data via a REST call(s) to an AppD service\nand metadata location. As described in the [AppD Discovery](appd-discovery)\nsection, this call requires an application identifier (app1@host.appd.com),\nwhich can be used to both locate the AppD service and key to retrieve the\nspecific application data. The resulting application data will describe the\napplication and the metadata URI or the actual\nmetadata in JSON format. If the metadata is a URI, the launcher would\nretrieve the metadata file from the URI.\n\n![img](/assets/appd_launcher_embedded.png)\n\n\n## Standalone Launcher\n\nIn more advanced cases, there could be a need to execute different types\nof desktop applications, such as web browser or general native application\n(exe, binary). A common approach to support this pattern would be to\ncreate a standalone launcher application that has the ability to query\napplication data from the AppD and executes the desktop application that\ncan run the required application. This is also convenient if you wanted\nto display all possible applications to launch in a single view.\n\n![img](/assets/appd_launcher_standalone.png)\n\n\n## Aggregated View\n\nThere could be many different AppD service instances in the world providing\napplication data zoned to the provider or enterprise deployment. The\nAppD specification allows for unique instances of the service with no\nrequirement to aggregate data or define a structured hierarchy. With this\nsaid, a launcher might want to construct an aggregated view of applications\nfrom one or more AppD instances. In this case, the launcher would be\nrequired to retrieve multiple application definitions from one or more\nAppD instances providing a consolidated view of all applications required.\nToday there is no intention to create a single registry of known AppD\ninstances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location (FQDN).\n\n![img](/assets/appd_launcher_aggregated.png)\n\n\n## Enhancing controls\n\nThe AppD API specification defines the optional use of an access token to\nidentify the requesting user/launcher and implement authorizations around which AppD actions can be performed. Actions are considered standard CRUD operations.\nAgain the specification does not define or make mandatory any authorizations\nor roles that a provider or enterprise can define.\n\nWith this said, it is highly recommended that the implementation take advantage\nand utilize an access token to support these controls. In most cases simple\nuse of roles like \"admin\" and \"user\" would be adequate to create separation\nbetween producer and consumer.\n\nAlternatively a more open approach can be defined, where producers of a new\ndefinition are automatically set to \"owner\" of the the definition.\n\nIn more advanced use cases, actual entitlements can be applied to limit\naccess to specific applications and associated actions based on the source\nuser/launcher identity.\n\nIn all examples, it is up to the implementation to define and engineer the solution\nbased on individual requirements. There are too many variations in approach\nand technology to define a single specification.\n\n\n\n## Reference Implementation\n\n### AppD POC\nPlease view readme on the [AppD POC GitHub](https://github.com/FDC3/appd-poc) .\n\n\n### Launcher\n\nTBD"
  },
  {
    "path": "website/versioned_docs/version-1.0/context-intro.md",
    "content": "---\nsidebar_label: Context Data Overview\ntitle: Context Data Overview\nhide_title: true\noriginal_id: context-intro\n---\n\n# Context Data Overview\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to one another without any prior knowledge.  \n\nFDC3 Context Data defines a standard for passing common identifiers and data between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [Intents](intents-intro) and when broadcasting context to other applications.\n\n## Context Object\n\nContext can be summarised as:\n* Having a unique _type_ identifier, used for routing.\n* Optionally providing a name.\n* Optionally providing a map of equivalent identifiers.\n* Any other properties or metadata.\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n## Example Context Object\n\nAn instrument could for example be derived as (note that the name is required and the type is fixed):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" : \n    {  \n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n    \"country\": \"US\"\n}\n```\n It is important to note that the context data specification allows extra identifiers and properties to be added as needed for each interop use case. In the example above, `country` could represent extra data in addition to the agreed instrument representation.\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/context-spec.md",
    "content": "---\nsidebar_label: Context Data Specification\ntitle: Context Data Specification 1.0\noriginal_id: context-spec\n---\n\n## Introduction\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems.\n\nExchanging context is the most basic entry point to desktop interoperability. The barriers to adoption for this interaction must be kept as low as possible.\n\nThere are two main use case for exchanging context data:\n\n* __Transmitting reference data between applications.__\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n* __Transferring information between applications.__\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there isn't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data needs to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for extra metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standard\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n## The Context Interface\n\n```ts\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n\n### Examples\n\n__Note:__ The below examples show how the base context data interface can be used to define specific context data objects. It is not the purpose of the specification at this stage to define standard representations for objects. It establishes the framework in which such definitions could be created.\n\n#### Instrument\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n#### Contact\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Nick Kolba\",\n    \"id\":{\n        \"email\": \"nick@openfin.co\",\n        \"twitter\": \"nkolba\",\n        \"phone\": \"9171234567\"\n    }\n}\n```\n#### Organization\n```json\n{\n    \"type\": \"fdc3.organization\",\n    \"name\": \"IBM\",\n    \"id\": {\n        \"PERMID\" : \"4295904307\",\n        \"LEI\" : \"VGRQXHF3J8VDLUA7XE92\"\n    }\n}\n```\n#### ContactList\n```json\n{\n    \"type\": \"fdc3.contactList\",\n    \"contacts\": [\n        {\n            \"type\" : \"fdc3.contact\",\n            \"name\":\"Nick Kolba\",\n            \"id\":{\n                \"email\": \"nick@openfin.co\"\n            }\n        },\n        {\n            \"type\" : \"fdc3.contact\",\n            \"name\":\"Espen Overbye\",\n            \"id\":{\n                \"email\": \"espen@openfin.co\"\n            }\n        }\n    ]\n}\n```\n#### Position\n```json\n{\n    \"type\": \"fdc3.position\",\n    \"instrument\": {\n        \"type\" : \"fdc3.instrument\",\n        \"name\" : \"Apple\",\n        \"id\" :\n        {\n            \"ISIN\" : \"US0378331005\"\n        }\n    },\n    \"holding\": 500\n}\n```\n\n### Namespacing\n\nAll well-known types at FDC3 level should be prefixed with `fdc3`. For private type definitions, or type definitions issued by other organisations, different namespaces can be used, e.g. `blackrock.fund`, etc.\n\n### Versioning\n\nThe specification recognises that evolving context data definitions over time, and helping applications to deal with changes to types, are very important.\n\nIt may be as simple as adding an optional `$version` property to types, but it could also be a set of guidelines for adding new properties, without removing or changing existing ones. For example, web technologies like REST or GraphQL do not take a particular opinion about versioning.\n\n### Identifiers\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.factset.symbology.entity\": \"000C7F-E\"\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/fdc3-charter.md",
    "content": "---\nsidebar_label: Charter\ntitle: FDC3 Charter\nhide_title: true\noriginal_id: fdc3-charter\n---\n\n# FDC3 Charter\n\n## Summary\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\n## Scope\nFinancial desktop applications include any app used in common financial workflows:\n\n* Traditional native applications implemented in C++, .NET, Java, Python, etc.\n* Hybrid web/native applications - stand alone native apps embedding Chromium (e.g. Electron, CEF, NW.js) \n* Desktop web applications - platform based apps extending Chromium (e.g. OpenFin, Hosted Web Apps)\n* Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, etc. \n* Web applications running in a commercial browser\n\nThis standards group is focused specifically on the desktop.  Activities of the desktop interoperability group do not include:\n\n* Defining financial objects - where existing standards are well established\n* Interoperability between mobile apps\n* Interoperability via REST or other client to server communication\n\nNote: While these areas are out of scope, compatibility with Mobile and/or REST are still valid points of consideration for the FDC3.\n\n## Success Criteria\n* Commitment from major banks and application vendors to support the standards set out by the FDC3\n* Workflow integrations in the wild leveraging the standards\n\n## Deliverables\n* Define criteria and mechanics for secure communication between apps\n* Define key functions that require specific standards for interoperability \n* Create an agreed taxonomy for common app “intents” within financial desktop workflows\n* Create an agreed taxonomy for common data to be shared across apps within financial desktop workflows\n* Provide reference implementations of all standards\n* Maintain the above standards and reference implementations \n\n### Participation\nTo be successful, the FDC3 is expected to have a critical mass of active participants for its duration. Effective participation in FDC3 means participation in the form of research, authoring, editing, and development activities outside the scope of attending regular meetings.\n\n### Licensing\nThe FDC3 will use Apache 2.0 license or similar for all deliverables. \n"
  },
  {
    "path": "website/versioned_docs/version-1.0/fdc3-compliance.md",
    "content": "---\ntitle: FDC3 Specification Compliance\nsidebar_label: FDC3 Compliance\noriginal_id: fdc3-compliance\n---\n\n\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/id/draft-faltstrom-uri-11.html#RFC2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>   Imperatives of the type defined in this memo must be used with care\n>   and sparingly.  In particular, they MUST only be used where it is\n>   actually required for interoperation or to limit behavior which has\n>   potential for causing harm (e.g., limiting retransmisssions)  For\n>   example, they must not be used to try to impose a particular method\n>  on implementors where the method is not required for\n>   interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers API, App Directory, Context Data, and Intents working groups, it does not apply to the Use Cases working group. \n\n## Personas\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation of the FDC3 API for applications to use. Implicitly, it connects to one or more App Directories.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.  \n\nDepending on persona, implementation compliance with FDC3 will mean different things.  \n\n### Platform Provider\nTo meet the requirements of FDC3, a platform provider would need to support the following:\n\n* Connection to 1 or more App Directories meeting the FDC3 App Directory standards\n* Provide an API to all applications running in the context of the platform that meets the FDC3 API standards, including:\n    * Support for FDC3 Context Data and Intents standards\n    * Support for Intent and Context resolution using a resolver UI\n* At least one workflow of one of the use cases marked as Accepted by the Use Cases working group SHOULD be satisfied by the implementation.\n\n### Application Provider\nFor application providers FDC3 compliance requires:\n* If intents are supported by the application, they SHOULD favor supporting applicable FDC3 defined intents over proprietary ones.  \n* If FDC3 defined intents are supported, they MUST meet the expected context and behavior defined for the intent.  \n* If proprietary intents are handled, those intents SHOULD follow the recommended naming conventions in the specification.\n* If intents are supported, the application SHOULD use the addIntentListener API to set up a handler.\n* If Context Data is supported by the application, they SHOULD favor supporting applicable FDC3 defined Context Data over proprietary ones.  \n* If FDC3 defined Context Data is supported, it MUST meet the interface defined for the type of Context Data.  \n* If proprietary Context Data properties are handled, they SHOULD follow any recommended naming conventions in the specification.\n* If Context Data is supported, the application SHOULD use the addContextListener API to set up a handler.\n\n## References\nThe following specifications and use cases references apply to the above:\n* [API](api/api-spec)\n* [App Directory](appd-spec)\n* [Context Data](context-spec)\n* [Intents](intents-spec)\n* [Use Cases](use-cases/overview)"
  },
  {
    "path": "website/versioned_docs/version-1.0/fdc3-intro.md",
    "content": "---\ntitle: Welcome to FDC3\nsidebar_label: Introduction\noriginal_id: fdc3-intro\n---\n![FDC3](/assets/fdc3-logo.png)\n\nThe mission of FDC3 is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements. [Read the Charter](fdc3-charter.md).\n\nFDC3 was launched in October 2017 by [OpenFin](http://www.openfin.co) in collaboration with major industry participants. It includes representatives from over 40 major banks, buy-side firms, consultancies and financial services platforms. FDC3 uses the Apache 2.0 open source license for all deliverables.\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services."
  },
  {
    "path": "website/versioned_docs/version-1.0/fdc3-standard.md",
    "content": "---\ntitle: FDC3 1.0\nsidebar_label: FDC3 1.0 Abstract\noriginal_id: fdc3-standard\n---\n\n**Status:** Superceded  \n_**released:** 5th mar 2019_  \n_**superseded:** 1st Apr 2020_  \n\n## Abstract\n\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of four complementary parts:\n\n- **[Desktop Agent API](api/api-spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain. \n- **[Intents](intents-spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context-spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](appd-spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n\n## Versioning\n\nThis Standard defines FDC3 Version 1.0.\n\n## Table of Contents\n\n- [Compliance information](fdc3-compliance)\n- [API Part](api/api-spec)\n- [Intents Part](intents-spec)\n- [Context Data Part](context-spec)\n- [App Directory Part](appd-spec)\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/intents-intro.md",
    "content": "---\nsidebar_label: Intents Overview\ntitle: Intents Overview\nhide_title: true\noriginal_id: intents-intro\n---\n\n# Intents Overview\n\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to another without any prior knowledge.\n\n\nFDC3 Intents define a standard set of verbs that can be used to put together common cross-application workflows on the financial desktop.\n* Applications register the Intents & [Context Data](context-intro) combinations they support in the [App Directory](appd-intro)\n* The App Directory supports application discovery by Intents and/or Context Data\n* Intents are not full RPC, apps don’t need to enumerate every function with an intent\n* FDC3 Standard Intents are a limited set, organizations can create their own intents\n\n## Using Intents\nCombined with [Context Data](context-intro) and [App Directory](appd-intro) standards, Intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n type: \"fdc3.contact\",\n name: \"Nick Kolba\",\n id: {\n    email:\"nick@openfin.co\"\n  }\n});\n```"
  },
  {
    "path": "website/versioned_docs/version-1.0/intents-spec.md",
    "content": "---\nsidebar_label: Intents Specification\ntitle: Intents Specification 1.0\noriginal_id: intents-spec\n---\n\n## Introduction\n\nFDC3 [Intents](intents-intro) define a standard set of nouns and verbs that can be used to put together common cross-application workflows on the financial desktop.\n\n### Naming Syntax\n* Intent names should be free of non-alphanumeric characters.\n* ‘.’ will be used to namespace the intent (see below).\n* Intent names should be in UpperCamelCase.\n\n### Characteristics\n\nIntents shoulde be:\n* Recognizable\n    * Generally self-evident what the thing is\n* Repeatable\n    * Many instances across the industry\n* Stateless\n    * Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n* Specific\n    * Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n* Distinct\n    * Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces ###\nAll standard Intent names are reserved. Applications may use their own Intents ad hoc.\nHowever, there is a need for applications to ensure that their Intents avoid collision. The recommended approach here is to use the app name as the noun. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary Intent.\n\n## Initial Set of Standard Intents ##\n\n### StartCall\n  * Expected Context: Contact\n  * Expected behavior: initiate call with contact(s)\n### StartChat\n  * Expected Context: Contact\n  * Expected behavior: initiate chat with contact(s)\n### ViewChart\n  * Expected Context: Instrument\n  * Expected behavior: display a chart for the context\n### ViewContact\n  * Expected Context: Contact\n  * Expected behavior: display details of a contact\n### ViewQuote\n  * Expected Context: Instrument\n  * Expected behavior: display pricing for an instrument\n### ViewNews\n  * Expected Context: Instrument, Contact, Organisation, etc.\n  * Expected behavior: display news for a given context\n### ViewInstrument\n  * Expected Context: Instrument\n  * Expected behavior: display relevant information for a given instrument\n### ViewAnalysis\n  * Expected Context: Instrument, Organization, etc.\n  * Expected behavior: Send context to receiving application for displaying analysis\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\noriginal_id: uc-1\n---\n\n## Preconditions\nOn their desktop, this user has:\n- Their firm's internal research & analytics platform containing liquidity tools and internal research. The product is running and the liquidity tool is open\n- An installed chat application - product is running\n- A third party market data terminal with 3 open applications. These applications are all 'linked' through a channel. \n    - A Watchlist\n    - An Order Book\n    - An Overview of pricing and fundamental data\n- A third party Charting Application access via a browser window. This is not open. \n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\noriginal_id: uc-2\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\noriginal_id: uc-3\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\noriginal_id: uc-4\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\noriginal_id: uc-5\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/009-call-transcription-to-crm.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Call Transcription to CRM\"\nsidebar_label: 9. Call Transcription to CRM\nlayout: use_case\noriginal_id: uc-9\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/010-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Real-Time voice trades -> trade ticket population\"\nsidebar_label: 10. Real-Time voice trades -> trade ticket population\nlayout: use_case\noriginal_id: uc-10\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/013-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-13\ntitle: \"Use Case 13: User launches multiple apps from a single container\"\nsidebar_label: 13. User launches multiple apps from a single container\nlayout: use_case\noriginal_id: uc-13\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/015-sales-floor-base-workflow.md",
    "content": "---\nid: uc-15\ntitle: \"Use Case 15: Sales Floor Base Workflow\"\nsidebar_label: 15. Sales Floor Base Workflow\nlayout: use_case\noriginal_id: uc-15\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/016-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-16\ntitle:  \"Use Case 16: Quantifying FDC3 Interactions\"\nsidebar_label: 16. Quantifying FDC3 Interactions\nlayout: use_case\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/017-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-17\ntitle:  \"Use Case 17: Fine-tuning InterOp with Channels\"\nsidebar_label: 17. Fine-tuning InterOp with Channels\nlayout: use_case\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/meeting-minutes/2020-01-16 uc-wg meeting notes.md",
    "content": "**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n\n\n## Agenda\n### 1. 2020 Move to GitHub - JT (15 min)\n- Goal: manage all new UCWG content in GitHub in 2020\n\n**Proposal:** how to manage the UCWG content \n- Meeting Minutes \n  - legacy [keep them on confluence and link to them] AGREED - link to be added\n  - new [in github, [this folder](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases/meeting-minutes), we also could create a GitHub Issue template] AGREED - link to be updated\n- Governance Docs [to be refreshed and moved to the [use cases intro](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/use-cases-intro.md) page]  - AGREED to move to intro doc, but need to be reviewed and cleaned up. \n  - Ratifying use cases via GitHub PRs - voting done via GitHub (👍 / 👎 on an issue - see [UC 17](https://github.com/finos/FDC3/pull/153)) rather than Google Groups - AGREED \n- Use Cases \n  - 1. In Review [will be managed via submitted pull requests - see [this](https://github.com/finos/FDC3/pulls?q=is%3Aopen+is%3Apr+label%3Ause-cases)]\n  - 2. Accepted [DONE - listed [here](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases)]\n  - 3. Rejected \n  - 4. Deleted \n  - 5. Backlog \n  - Use Case XX: Template [we can create this as a github issue type] - JT to try and prove this works\n- Action Items \n  - to be reviewed and closed out. Relevant ones will be migrated. \n- Process: \n  - One of the participants edits meeting minutes live on a screenshare during the call. All participants on the call review and approve the minutes at the end of the call. Once approved verbally on the call, the meeting minutes PR can be merged. \n\n### 2. UC 17 Vote - Johan (5 min)\n- Voting directly on the PR: https://github.com/finos/FDC3/pull/153\n- APPROVED AND MERGED!\n\n### 3. UCWG Goals and Roadmap - JT (15 min)\n- see proposal [here](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/fdc3-okrs.md#use-case-working-group)\n- UCWG to review offline and comment\n\n### 4. AOB \n- lean UCWG + new recruits\n- clean up open action items in confluence\n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/meeting-minutes/2020-02-20 uc-wg meeting notes.md",
    "content": "\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n| Leslie Spiro | Tick42 |  |\n\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/meeting-minutes/2020-03-19 uc-wg meeting notes.md",
    "content": "**Meeting not held due to low attendance**\n\n**Date**: 19 March 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/overview.md",
    "content": "---\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\noriginal_id: overview\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-1.0/use-cases/readme.md",
    "content": "# Overview \nHere are business use cases that have been documented and ratified by the Use Cases Working Group\n\n# Adoption of Use Cases into the FDC3 Standard\n\n**Use Cases Accepted onto Roadmap of Standards or Implemented**\n\n| Use Cases                                                           | Count         | %       |\n| -------------                                                       |:-------------:| :----:  |\n| 001-equity-sell-side-trader                                         | \t2 / 5       |   40%   | \n| 002-buy-side-portfolio-manager                                      | \t0 / 3\t      |   33%   | \n| 003-inhouse-cross-platform-launcher                                 | \t0 / 8       |    0%   | \n| 004-client-side-fx-trader                                           | \t0 / 1\t      |    0%   | \n| 005-buy-side-treasurer                                              | \t0 / 3\t      |    0%   | \n| 009-call-transcription-to-crm                                       | \t0 / 2\t      |    0%   | \n| 010-realtime-trade-ticket-population                                | \t0 / 1\t      |    0%   | \n| 013-user-launches-multiple-apps-from-a-single-container             | \t0 / 3\t      |    0%   | \n| 015-sales-floor-base-workflow                                       | \t0 / 2\t      |    0%   | \n| 016-quantifying-fdc3-interactions                                   | \t0 / 3\t      |    0%   | \n| total                                                               | \t2 / 31      |  6.5%   | \n\n\n\n**Summary**\n\n| Status                                | Count         | %       |\n| -------------                         |:-------------:| :----:  |\n| New                                   | \t24\t        |   77.5%   | \n| Proposed                              | \t5           | \t16%   | \n| **Accepted onto Roadmap of Standard** | \t0           | \t**0%**  | \n| **Implemented**                       | \t2         \t|  **6.5%** | \n| Rejected                              | \t0           | \t0%    | \n| N/R                                   | \t3           |         | \t\n| Total (excl. N/R)                     | \t31          | \t100%  | \n"
  },
  {
    "path": "website/versioned_docs/version-1.0/why-fdc3.md",
    "content": "---\nsidebar_label: Why FDC3\ntitle: Why FDC3\noriginal_id: why-fdc3\n---\n\n## Why look for FDC3 enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go. The main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3 enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context)\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc. Every application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is an easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3 enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3 enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration, with an [App directory](appd-intro) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering."
  },
  {
    "path": "website/versioned_docs/version-1.1/api/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\n```typescript\ntype Context = object;\n```\n\nThe base object that all contexts should extend.\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\n## Methods\n\n### `open`\n\n```typescript\nopen(name: string, context?: Context): Promise<void>;\n```\n\nLaunches/links to an app by name.\n\nIf a [`Context`](Context) object is passed in, this object will be provided to the opened application via a contextListener.\nThe Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\nIf opening errors, it returns an `Error` with a string from the [`OpenError`](Errors#openerror) enumeration.\n\n#### Example\n ```javascript\n//no context\nawait agent.open('myApp');\n\n//with context\nawait agent.open('myApp', context);\n```\n\n#### See also\n* [`Context`](Context)\n* [`OpenError`](Errors#openerror)\n\n### `findIntent`\n\n```typescript\nfindIntent(intent: string, context?: Context): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context.\n\n_findIntent_ is effectively granting programmatic access to the Desktop Agent's resolver. \nIt returns a promise resolving to the intent, its metadata and metadata about the apps that are registered to handle it.\nThis can be used to raise the intent against a specific app.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n\n#### Examples\n```javascript\n// I know 'StartChat' exists as a concept, and want to know more about it ...\nconst appIntent = await agent.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }\n\n// raise the intent against a particular app\nawait agent.raiseIntent(appIntent.intent.name, context, appIntent.apps[0].name);\n```\n\n#### See also\n* [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```typescript\nfindIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context.\n_findIntentsByContext_ is effectively granting programmatic access to the Desktop Agent's resolver. \nA promise resolving to all the intents, their metadata and metadata about the apps that registered as handlers is returned, based on the context types the intents have registered.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n \n #### Examples\n ```javascript\n // I have a context object, and I want to know what I can do with it, hence, I look for intents...\n const appIntents = await agent.findIntentsByContext(context);\n \n // returns, for example:\n // [{\n //     intent: { name: \"StartCall\", displayName: \"Call\" },\n //     apps: [{ name: \"Skype\" }]\n // },\n // {\n //     intent: { name: \"StartChat\", displayName: \"Chat\" },\n //     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n // }];\n \n // select a particular intent to raise\n const startChat = appIntents[1];\n \n // target a particular app\n const selectedApp = startChat.apps[0];\n \n // raise the intent, passing the given context, targeting the app\n await agent.raiseIntent(startChat.intent.name, context, selectedApp.name);\n ```\n\n#### See also\n   * [`ResolveError`](Errors#resolveerror)\n\n### `broadcast`\n```typescript\nbroadcast(context: Context): void;\n```\n\nPublishes context to other apps on the desktop.\n\n#### Examples\n```javascript\nagent.broadcast(context);\n```\n#### See also\n* [addContextListener](#addcontextlistener)\n\n### `raiseIntent`\n\n```typescript\nraiseIntent(intent: string, context: Context, target?: string): Promise<IntentResolution>;\n```\nRaises an intent to the desktop agent to resolve.\n#### Examples\n```javascript\n//raise an intent to start a chat with a given contact\nconst intentR = await agent.findIntents(\"StartChat\", context);\n//use the IntentResolution object to target the same chat app with a new context\nagent.raiseIntent(\"StartChat\", newContext, intentR.source);\n```\n#### See also\n* [`IntentResolution`](#intentresolution)\n\n### `addIntentListener`\n```typescript\naddIntentListener(intent: string, handler: (context: Context) => void): Listener;\n```\n Adds a listener for incoming Intents from the Agent.\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n### `addContextListener`\n```typescript\naddContextListener(handler: (context: Context) => void): Listener;\n```\nAdds a listener for incoming context broadcast from the Desktop Agent.\n\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n## Return Types\n\n### `AppIntent`\n\n```typescript\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\nAn interface that represents the binding of an intent to apps\n\n#### See also\n* [`IntentMetadata`](#intentmetadata)\n* [`AppMetadata`](#appmetadata)\n\n### `IntentMetadata`\n\n```typescript\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n### `AppMetadata`\n\n```typescript\ninterface AppMetadata {\n  name: string;\n}\n```\n\nApp metadata is Desktop Agent specific - but should always support a name property.\n\n### `IntentResolution`\n\n```typescript\ninterface IntentResolution {\n  source: string;\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n \n#### Example\n```javascript\n//resolve a \"Chain\" type intent\nvar intentR = await agent.raiseIntent(\"intentName\", context);\n//resolve a \"Client-Service\" type intent with data response\nvar intentR = await agent.raiseIntent(\"intentName\", context);\nvar dataR = intentR.data;\n```\n\n#### See also\n* [`DesktopAgent.raiseIntent`](#raiseintent)\n\n\n### `Listener`\n\n```typescript\ninterface Listener {\n  unsubscribe();\n}\n```\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](#addintentlistener) or [`addContextListener`](#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\nThe `unsubscribe` method on the listener object allows the application to cancel the subscription.\n\n#### See also\n* [`DesktopAgent.addIntentListener`](#addintentlistener)\n* [`DesktopAgent.addContextListener`](#addcontextlistener)\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/Errors.md",
    "content": "---\nsidebar_label: Errors\ntitle: Errors\nhide_title: true\noriginal_id: Errors\n---\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n* [`DesktopAgent.open`](DesktopAgent#open)\n\n\n## `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/overview.md",
    "content": "---\nsidebar_label: API Overview\ntitle: API Overview\nhide_title: true\noriginal_id: overview\n---\n# API Overview\n\nFDC3 API standards support the following goals:\n- Create a consistent developer interface for working with FDC3 \n- Standardize interfaces for reference implementations\n- Standardize interfaces between Desktop Agents\n\nThe role of FDC3 API standards is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications - standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary its importance.\n\nThe focus on the API working group has been to create a small but consistent API, the following docs go through the components and API's in detail.\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/AppIntent.md",
    "content": "---\nsidebar_label: AppIntent\ntitle: AppIntent\nhide_title: true\noriginal_id: AppIntent\n---\n# `AppIntent`\n\n```ts\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\nAn interface that represents the binding of an intent to apps, returned as part of intent disocvery. \nFor each intent, it reference the applications that support that intent.\n\n#### See also\n* [`AppMetadata`](AppMetadata)\n* [`IntentMetadata`](IntentMetadata)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/AppMetadata.md",
    "content": "---\nsidebar_label: AppMetadata\ntitle: AppMetadata\nhide_title: true\noriginal_id: AppMetadata\n---\n\n# `AppMetadata`\n\n```ts\ninterface AppMetadata {\n  name: string;\n  title?: string;\n  tooltip?: string;\n  description?: string;\n  icons?: Array<string>;\n  images?: Array<string>;\n}\n```\n\nApp metadata is provided by the FDC3 App Directory that the desktop agent connects to.\n\nIt always includes at least a `name` property, which can be used with [`open`](DesktopAgent#open) and [`raiseIntent`](DesktopAgent#raiseintent).\n\nOptionally, extra information from the app directory can be returned, to aid in rendering UI elements, e.g. a context menu.\nThis includes a title, description, tooltip and icon and image URLs.\n\n#### See also\n* [`AppIntent.apps`](AppIntent)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/Channel.md",
    "content": "---\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\noriginal_id: Channel\n---\n# `Channel`\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: string;\n  displayMetadata?: DisplayMetadata;\n\n  // methods\n  broadcast(context: Context): void;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(handler: ContextHandler): Listener;\n  addContextListener(contextType: string, handler: ContextHandler): Listener;\n}\n```\n\nRepresents a context channel that applications can join to share context data. \n\nA channel can be either a well-known \"system\" channel (retrieved with [`getSystemChannels`](DesktopAgent#getsystemchannels)) or a custom \"app\" channel (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)).\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n#### See also\n\n* [`Context`](Context)\n* [`DesktopAgent.getSystemChannels`](DesktopAgent#getsystemchannels)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`DesktopAgent.joinChannel`](DesktopAgent#joinchannel)\n\n## Properties\n\n### `id`\n\n```ts\npublic readonly id: string;\n```\n\nUniquely identifies the channel. It is either assigned by the desktop agent (system channel) or defined by an application (app channel).\n\n### `type`\n\n```ts\npublic readonly type: string;\n```\n\nCan be _system_ or _app_.\n\n### `displayMetadata`\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\nDisplayMetadata can be used to provide display hints for channels intended to be visualized and selectable by end users.\n\n#### See also\n* [`DisplayMetadata`](DisplayMetadata)\n\n## Methods\n\n\n### `addContextListener`\n\n```ts\npublic addContextListener(handler: ContextHandler): Listener;\n```\n\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n```ts\npublic addContextListener(contextType: string, handler: ContextHandler): Listener;\n```\n\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\n#### Examples\n\nAdd a listener for any context that is broadcast on the channel:\n\n```ts\nconst listener = channel.addContextListener(context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n```ts\nconst contactListener = channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n#### See also\n* [`Listener`](Listener)\n* [`ContextHandler`](ContextHandler)\n* [`broadcast`](#broadcast)\n* [`getCurrentContext`](#addcontextlistener)\n\n### `broadcast`\n\n```typescript\npublic broadcast(context: Context): void;\n```\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the method will return an `Error` with a string from the [`ChannelError`](ChannelError) enumeration.\n\n#### Example\n\n```javascript\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n* [`ChannelError`](ChannelError)\n* [`getCurrentContext`](#getcurrentcontext)\n* [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\n\nIf getting the current context fails, the promise will return an `Error` with a string from the [`ChannelError`](ChannelError) enumeration.\n\n#### Examples\n\nWithout specifying a context type:\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\nSpecifying a context type:\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n* [`ChannelError`](ChannelError)\n* [`broadcast`](#broadcast)\n* [`addContextListener`](#addcontextlistener)\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/ChannelError.md",
    "content": "---\nsidebar_label: ChannelError\ntitle: ChannelError\nhide_title: true\noriginal_id: ChannelError\n---\n# `ChannelError`\n\n```typescript\nenum ChannelError {\n  NoChannelFound = \"NoChannelFound\",\n  AccessDenied = \"AccessDenied\",\n  CreationFailed = \"CreationFailed\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinChannel`](DesktopAgent#joinchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n#### See also\n\n* [`DesktopAgent.joinChannel`](DesktopAgent#joinchannel)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\n```typescript\ntype Context = object;\n```\n\nThe base object that all contexts should extend.\n\nThe API specification allows this to be any object, but typically this is supposed to be a context data object adhering to the [Context Data Specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`.\n\nThe `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n#### See also\n\n* [`ContextHandler`](ContextHandler)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/ContextHandler.md",
    "content": "---\nsidebar_label: ContextHandler\ntitle: ContextHandler\nhide_title: true\noriginal_id: ContextHandler\n---\n# `ContextHandler`\n\n```typescript\ntype ContextHandler = (context: Context) => void;\n```\n\nDescribes a callback that handles a context event.\n\nUsed when attaching listeners for context broadcasts and raised intents.\n\n#### See also\n* [`Context`](Context)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(name: string, context?: Context): Promise<void>;\n  \n  // context\n  broadcast(context: Context): void;\n  addContextListener(handler: ContextHandler): Listener;\n  addContextListener(contextType: string, handler: ContextHandler): Listener;\n\n  // intents\n  findIntent(intent: string, context?: Context): Promise<AppIntent>;\n  findIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, target?: string): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: ContextHandler): Listener;\n  \n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel>;\n  leaveCurrentChannel() : Promise<void>;\n}\n```\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\n## Methods\n\n### `addContextListener`\n\n```ts\naddContextListener(handler: ContextHandler): Listener;\naddContextListener(contextType: string, handler: ContextHandler): Listener;\n```\n\nAdds a listener for incoming context broadcast from the Desktop Agent. If the consumer is only interested in\na context of a particular type, they can use the relevant overload that allows the type to be specified.\n\n#### Examples\n\n```js\n// any context\nconst listener = fdc3.addContextListener(context => { ... });\n\n// listener for a specific type\nconst contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });\n```\n\n#### See also\n* [`Listener`](Listener)\n* [`Context`](Context)\n\n### `addIntentListener`\n\n```ts\naddIntentListener(intent: string, handler: ContextHandler): Listener;\n```\n\n Adds a listener for incoming Intents from the Agent.\n\n#### Examples\n\n```js\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n});\n```\n\n#### See also\n\n* [`Listener`](Listener)\n* [`Context`](Context)\n\n### `broadcast`\n\n```ts\nbroadcast(context: Context): void;\n```\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever `Channel` the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\n#### Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n#### See also\n\n* [addContextListener](#addcontextlistener)\n\n### `findIntent`\n\n```ts\nfindIntent(intent: string, context?: Context): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context.\n\n_findIntent_ is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to the intent, its metadata and metadata about the apps that are registered to handle it.\nThis can be used to raise the intent against a specific app.\n\n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](ResolveError) enumeration.\n\n#### Examples\n\n```js\n// I know 'StartChat' exists as a concept, and want to know more about it ...\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0].name);\n```\n\n#### See also\n\n* [`ResolveError`](ResolveError)\n\n### `findIntentsByContext`\n\n```ts\nfindIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context.\n_findIntentsByContext_ is effectively granting programmatic access to the Desktop Agent's resolver. \nA promise resolving to all the intents, their metadata and metadata about the apps that registered as handlers is returned, based on the context types the intents have registered.\n\nIf the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](ResolveError) enumeration.\n\n#### Example\n\n```js\n// I have a context object, and I want to know what I can do with it, hence, I look for intents...\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [{\n//     intent: { name: \"StartCall\", displayName: \"Call\" },\n//     apps: [{ name: \"Skype\" }]\n// },\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app\nconst selectedApp = startChat.apps[0];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp.name);\n```\n\n#### See also\n\n* [`ResolveError`](ResolveError)\n\n### `getCurrentChannel`\n\n```ts\ngetCurrentChannel() : Promise<Channel>;\n```\n\nReturns the `Channel` object for the current channel membership.  Returns `null` if the app is not joined to a channel. \n\n#### Examples\n\n```js\n//get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `getOrCreateChannel`\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\nReturns a Channel object for the specified channel, creating it (as an _App_ channel) - if it does not exist.\n`Error` with a string from the [`ChannelError`](ChannelError) enumeration if channel could not be created or access was denied.\n\n#### Example\n\n```js\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  const myChannel.addContextListener(context => {});\n}\ncatch (err){\n  //app could not register the channel\n}\n\n```\n\n#### See also\n\n*  [`Channel`](Channel)\n\n### `getSystemChannels`\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\nRetrieves a list of the System channels available for the app to join.  This should include the 'global' channel.\n\n#### Example\n\n```js\nconst systemChannels = await fdc3.getSystemChannels(); \nconst redChannel = systemChannels.find(c => c.id === 'red');\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `joinChannel`\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\nJoins the app to the specified channel.\nIf an app is joined to a channel, all _fdc3.broadcast_ calls will go to the channel, and all listeners assigned via _fdc3.addContextListener_ will listen on the channel.\nAn app can only be joined to one channel at a time.\nRejects with error if the channel is unavailable or the join request is denied.\n `Error` with a string from the [`ChannelError`](ChannelError) enumeration.\n\n#### Examples\n\n```js\n// get all system channels\nconst channels = await fdc3.getSystemChannels();\n\n// create UI to pick from the system channels\n\n// join the channel on selection\nfdc3.joinChannel(selectedChannel.id);\n\n```\n\n#### See also\n\n* [`getSystemChannels`](#getsystemchannels)\n\n### `leaveCurrentChannel`\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\nRemoves the app from any channel membership.  Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be in a no-op when the app is not on a channel.\n\n#### Examples\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(channelListener);\n\n```\n\n### `open`\n\n```ts\nopen(name: string, context?: Context): Promise<void>;\n```\n\nLaunches/links to an app by name.\n\nIf a [`Context`](Context) object is passed in, this object will be provided to the opened application via a contextListener.\nThe Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\nIf opening errors, it returns an `Error` with a string from the [`OpenError`](OpenError) enumeration.\n\n#### Example\n\n```js\n// no context\nawait fdc3.open('myApp');\n\n// with context\nawait fdc3.open('myApp', context);\n```\n\n#### See also\n\n* [`Context`](Context)\n* [`OpenError`](OpenError)\n\n### `raiseIntent`\n\n```ts\nraiseIntent(intent: string, context: Context, target?: string): Promise<IntentResolution>;\n```\n\nRaises an intent to the desktop agent to resolve.\n\n#### Example\n\n```js\n//raise an intent to start a chat with a given contact\nconst intentResolution = await fdc3.findIntents(\"StartChat\", context);\n//use the IntentResolution object to target the same chat app with a new context\nawait fdc3.raiseIntent(\"StartChat\", newContext, intentResolution.source);\n```\n\n#### See also\n\n* [`IntentResolution`](IntentResolution)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/DisplayMetadata.md",
    "content": "---\nsidebar_label: DisplayMetadata\ntitle: DisplayMetadata\nhide_title: true\noriginal_id: DisplayMetadata\n---\n# `DisplayMetadata`\n\n```ts\n public interface DisplayMetadata {\n  name?: string;\n  color?: string;\n  glyph?: string;\n}\n```\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n#### See also\n\n* [`Channel`](Channel)\n* [`DesktopAgent.getSystemChannels`](DesktopAgent#getsystemchannels)\n\n## Properties\n\n### `name`\n\n```ts\nname?: string;\n```\n\nThe display name for the channel.\n\n### `color`\n\n```ts\ncolor?: string;\n```\n\nA name, hex, rgba, etc. that should be associated within the channel when displaying it in a UI.\n\n### `glyph`\n\n```ts\nglyph: string;\n```\n\nA URL of an image that can be used to display this channel."
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/IntentMetadata.md",
    "content": "---\nsidebar_label: IntentMetadata\ntitle: IntentMetadata\nhide_title: true\noriginal_id: IntentMetadata\n---\n# `IntentMetadata`\n\n```ts\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n\n#### See also\n* [`AppIntent.intent`](AppIntent)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/IntentResolution.md",
    "content": "---\nsidebar_label: IntentResolution\ntitle: IntentResolution\nhide_title: true\noriginal_id: IntentResolution\n---\n# `IntentResolution`\n\n```ts\ninterface IntentResolution {\n  source: string;\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n \n#### Example\n```js\n//resolve a \"Chain\" type intent\nconst intentResolution = await fdc3.raiseIntent(\"intentName\", context);\n```\n\n#### See also\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/Listener.md",
    "content": "---\nsidebar_label: Listener\ntitle: Listener\nhide_title: true\noriginal_id: Listener\n---\n# `Listener`\n\n```typescript\ninterface Listener {\n  unsubscribe(): void;\n}\n```\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\n\n## Methods\n\n### `unsubscribe`\n\n```ts\nunsubscribe(): void;\n```\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n#### See also\n\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`ContextHandler`](ContextHandler)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/OpenError.md",
    "content": "---\nsidebar_label: OpenError\ntitle: OpenError\nhide_title: true\noriginal_id: OpenError\n---\n# `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n* [`DesktopAgent.open`](DesktopAgent#open)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/ref/ResolveError.md",
    "content": "---\nsidebar_label: ResolveError\ntitle: ResolveError\nhide_title: true\noriginal_id: ResolveError\n---\n# `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.1/api/spec.md",
    "content": "---\nsidebar_label: API Specification\ntitle: API Specification 1.1\noriginal_id: spec\n---\n## Components\n### Desktop Agent\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- Finsemble\n- OpenFin\n- Refinitiv Eikon\n\nDesktop Agents expose an FDC3 standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n#### Desktop Agent Implementation\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A typical implemention would provide instantiable classes for the following interfaces:\n\n- `DesktopAgent`\n- `Channel`\n- `Listener`\n\nOther interfaces defined in the spec are not critical to define as concrete types.  Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.  These interfaces include:\n\n- `Context`\n- `AppIntent`\n- `IntentResolution`\n- `AppMetadata`\n- `IntentMetadata`\n- `DisplayMetadata`\n\n\n\n#### API Access\nThe FDC3 API can be made available to an application through a number of different methods.  In the case of web applications, a Desktop Agent SHOULD provide the FDC3 API via a global accessible as _window.fdc3_. Implementors MAY additionally make the API available through modules, imports, or other means.\n\n#### Standards vs. Implementation\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n#### Inter-Agent Communication\nA goal of FDC3 standards is that applications running in different Desktop Agent contexts on the same desktop would be able to interoperate.  And that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\nDesktop Agent interop is supported by common standards for APIs for App discovery and launching.  So, an App in one Desktop Agent context would not need to know a different syntax to call an App in another Desktop Agent context.\n\nThe actual connection protocol between Desktop Agents is not currently in scope for FDC3 standards.  Given that there are a relatively small number of Desktop Agents, and that any given desktop will have a finite and relatively static number of Desktop Agents installed at any given time, the connectivity between different Agents can be adequetly handled for the time being on a case-by-case basis.\n\n### Application\nAn application is any endpoint on the desktop that is:\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of End Points include:\n- Native Applications\n- PWA/Web Applications\n- Headless “services” running on the desktop\n\n## Functional Use Cases\n### Open an Application by Name\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Raising Intents\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that Intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).   Currently, this is the primary focus in FDC3\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client.  Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n#### Intent Resolution\nRaising an Intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n##### Resolve\n- Intent was resolved unambigiously and the recieving app was launched successfully.\n- Intent was ambigious, a resolution was chosen by the end user and the chosen application was launched succesfully.\n\n##### Reject\n- An app matching the intent was not found.\n- A match was found, but the recieving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n##### Resolution Object\nIf the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format:\n\n```js\n{\n    source: String;\n    data?: Object;\n    version: String;\n}\n```\n- *source* = identifier for the Application resolving the intent (null if the intent could not be resolved)\n- *data* = return data structure - if one is provided for the given intent\n- *version* = the version number of the Intents schema being used\n\nFor example\n\n```js\ntry {\n    const result = await fdc3.raiseIntent('StageOrder');\n    if (result.data) {\n        const orderId = result.data.id;\n    }\n}\ncatch (er){\n    console.log(er.message);\n}\n\n```\n\n##### Upgrading to a Remote API Connection\nThere are a wide range of workflows where decoupled intents and/or context passing do not provide rich enough interactivity and applications are better off exposing proprietary APIs.  In these cases, an App can use the *source* property on the resolution of an intent to connect directly to another App and from there, call remote APIs using the methods available in the Desktop Agent context for the App.  For example:\n\n```js\nconst chart = await fdc3.raiseIntent('ViewChart');\n// construct a vendor wrapper for the App\nconst chartApp = fin.Application.wrap(chart.source);\n// do some vendor-specific stuff\n```\n![Upgrading Connection to Remote API](/assets/api-3.png)\n\n### Register an Intent\nApplications 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.\n\n#### Compliance with Intent Standards\nIntents 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.\n\nIt is expected that App Directories will also curate listed apps and ensure that they are complying with declared intents.\n\nLike FDC3 Context Data, the Intent schemas need to be versioned.  Desktop Agents will be responsible to declare which version of the Intent schema they are using.   Applications may also assert a specific version requirement when raising an Intent.  Version negotation may be supported by a given Desktop Agent.\n\n### Send/broadcast context\nOn the financial desktop, applications often want to broadcast context to any number of applications.  Context sharing needs to support concepts of different groupings of applications as well as data privacy concerns.  Each Desktop Agent will have its own rules for supporting these features.\n\n## Resolvers\nIntents functionality is dependent on resolver functionality to map the intent to a specific App.  This will often require end-user input.  Resolution can either be performed by the Desktop Agent (raising UI to pick the desired App for the intent) or by the app launching the intent - in which case the calling App will handle the resolution itself (using the findIntents API below) and then invoke an explicit Intent object.\n\n## Context channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\nThere are two types of channels, which are functionally identical, but have different visibility and discoverability semantics.\n\n1. The 'system' ones, which have a well understood identity. One is called 'global'.\n2. The 'app' ones, which have a transient identity and need to be revealed\n\n\n### Joining Channels\nApps can join channels.  An app can only be joined to one channel at a time.  When an app joins a channel it will automatically recieve the current context for that channel.\n\nWhen an app is joined to a channel, calls to fdc3.broadcast and listeners added through fdc3.addContextListener will be routed to that channel.  If an app is not joined to a channel these methods will be no-ops, but apps can still choose to listen and broadcast to specific channels via the methods on the `Channel` class.\n\nIt is possible that a call to join a channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app.  Always, there SHOULD be a clear UX indicator of what channel an app is joined to.\n\n### The 'global' Channel\nThe 'system' channels include a 'global' channel which serves as the backwards compatible layer with the 'send/broadcast context' behavior in FDC3 1.0.  A desktop agent MAY choose to make membership in the 'global' channel the default state for apps on start up.\n\nThe 'global' channel should be returned as part of the response from the `fdc3.getSystemChannels` call.  Desktop Agents may want to filter out the 'global' option in their UI for system channel pickers.\n\n\n#### Examples\n\nAn app queries the current context of the `global` channel.\n\n```js\nconst globalChannel = await fdc3.getOrCreateChannel(\"global\");\nconst context = await globalChannel.getCurrentContext(\"fdc3.instrument\");\n```\n\nAn app can explicitly receive context events on the `global` (or any other) channel, regardless of what it is currently joined to.\n\n```js\n// retrieve current fdc3 context\nconst context = await fdc3.getCurrentContext(\"fdc3.instrument\")\n// context is null, as not currently joined to a channel\n\nconst globalChannel = await fdc3.getSystemChannels.filter(c => c.id === \"global\")\nconst globalContext = await fdc3.getCurrentContext(\"fdc3.instrument\")\n// context is instrument AAPL on the global channel\n\nfdc3.joinChannel('global')\nconst context = await fdc3.getCurrentContext('fdc3.instrument')\n// top-level context is now instrument AAPL as well because we have joined the global channel\n```\n\n### Direct Listening and Broadcast on Channels\nWhile joining channels automates a lot of the channel behavior for an app, it has the limitation in that an app can belong to only one channel at a time.  Listening and Broadcasting to channels using the _Channel.addBroadcastListener_ and the _Channel.broadcast_ APIs provides an app with fine-grained controls for specific channels.  This is especially useful for working with dynamic _App Channels_.\n\n### Examples\nTo find a system channel, one calls\n\n```js\n// returns an array of channels\nconst allChannels = await fdc3.getSystemChannels();\nconst redChannel = allChannels.find(c => c.id === 'red');\n```\n#### Joining channels\n\nTo join a channel. one calls\n\n```js\nfdc3.joinChannel(redChannel.id);\n```\n\nCalling _fdc3.broadcast_ will now route context to the joined channel.\n\n#### App Channels\n\nApp channels are topics dynamically created by applications connected via FDC3. For example, an app may create a channel to broadcast to others data or status specific to that app.\n\nTo get (or create) a channel reference, then interact with it\n\n```js\nconst appChannel = await fdc3.getOrCreateChannel('my_custom_channel');\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nappChannel.addContextListener(context => {...});\n// broadcast to the channel\nappChannel.broadcast(context);\n\n```\n\n## APIs\nThe APIs are defined in TypeScript in [src], with documentation generated in the [docs] folder.\n\n[src]: https://github.com/finos/FDC3/tree/main/src/api\n[docs]: https://github.com/finos/FDC3/tree/main/docs/api\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/app-directory/discovery.md",
    "content": "---\nsidebar_label: App Directory Discovery\ntitle: App Directory Discovery\nhide_title: true\noriginal_id: discovery\n---\n\n# App Directory Discovery\n\n## Simple Definition\n\nThe App Directory (AppD) is a service that provides a financial application definition that includes a trusted identifier(s) and associated metadata. The information registered as part of an application definition supports discovery, launch configuration, intents and context data supporting the use and interoperability of financial applications.\n\n## Topology\n\nAppD services shall support a distributed or detached model to managing application data servicing, where there are (N) AppD services on a network providing information related to a subset of namespace \"zones\" that align with the financial application identifiers. This approach encourages independence, scale and responsive provisioning of application definitions. This is modeled from a subset of the public name service \"Domain Name System\", which has proven reliable and conceptually fit for discovery.\n\n## Service Discovery Approach\n\nIn order to support the discovery of application data stored in a given directory, name space concepts are introduced to both identify the realm of application definitions and AppD service locations that host data. In simple terms, there has to be a way of discovering the location of the AppD service itself and the associated application definitions that are available from that service.\n\n### Application Identifier\n\n- Application data discovery through nested namespace approach and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n### Resolving host system\n\n- AppD service host discovery implementations should support the following requirements;\n  1. Discovery of the AppD location using the fully qualified application ID domain name. This would be the fqdn part of the email structure.\n  2. Discovery of the AppD location using the fully qualified application ID domain name to lookup DNS SRV records identifying the host server location and access TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782) )\n  3. Statically defined URI records for use within client applications directly. This is similar to #1 above, but provides explicit protocol, port and url definitions as part of the defintion.\n\n**Examples:**\n\n*AppD service through DNS / SRV records:*\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/appd_srv.png?version=1&modificationDate=1530189735237&cacheVersion=1&api=v2&width=958&height=250)\n\nAppD Service distribution visual:\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/AppDServiceDistribution.png?version=1&modificationDate=1526307911273&cacheVersion=1&api=v2&width=498&height=250)\n\n## Application data discovery\n\nApplication data discovery shall be accessible through a unique application identifier (AppId) representing a single application represented by a nested namespace syntax using dot notation and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n**Example:**\n\n```\ngetAppData(\"app@sub.root\")\n\n    Application {\n      \"appId\": \"app@sub.root\",\n      \"name\": \"App Name\",\n      \"manifest\": \"https://sub.root/app_manifest.json\",\n      \"manifestType\": \"vendor_type\",\n      \"version\": \"1\",\n      \"title\": \"A very cool App\",\n      \"tooltip\": \"A very cool app really\",\n      \"description\": \"Yes..this is the coolest app ever..\",\n      \"images\": [\n        {\n          \"url\": \"string\"\n        }\n      ],\n      \"contactEmail\": \"string\",\n      \"supportEmail\": \"string\",\n      \"publisher\": \"string\",\n      \"icons\": [\n        {\n          \"icon\": \"string\"\n        }\n      ],\n      \"customConfig\": [\n        {\n          \"name\": \"string\",\n          \"value\": \"string\"\n        }\n      ],\n      \"intents\": [\n        {\n          \"name\": \"string\",\n          \"displayName\": \"string\",\n          \"contexts\": [\n            \"string\"\n          ],\n          \"customConfig\": {}\n        }\n      ]\n    }\n```\n\n## Service Discovery (Expanded)\n\nThe following represents the three ways AppD service instances should be discovered over a given network. Again, the view is that AppD services are distributed/decoupled based on associated application namespace on a given network. This takes into account the use of the application identifiers described in previous section. A launcher is required to use a URI (e.g. \"https://appd.foo.com/api/appd/apps/app1@appd.foo.com\") to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required. This proposal focuses on the following approaches to achieve this resolution.\n\n### Application ID namespace syntax host resolution\n\nAn application directory URI can be constructed using a fully qualified application ID (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application name \"app1\" with a fully qualified identifier of \"app1@appd.foo.com\" an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" may resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by;\n\n1. URI protocol is defaulted to https, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default https/443, but can be overridden by the launcher\n4. URI url is by default \"/api/**(service)/(version)/apps\" .**  It is recommended that we identify service label as \"**appd**\" with version being optional. Calls that are made without version automatically default to latest \"/api/appd/apps/app1\" vs \"/api/appd/v1/apps/app1\"\n\nThe resulting URI to retrieve application data for \"app1\" would be \"[https://appd.foo.com/api/appd/v1/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v1/apps/app1.appd.foo.com)\"\n\n### Application identifiers, Shrinking the URI and AppdD defaults\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID \"app1@appd.foo.com\" is represented as \"app1\" within the application directory.  As a result a launcher can use a shortened URI construct \"[https://appd.foo.com/api/appd/v1/apps/app1](https://appd.foo.com/api/appd/v1/apps/app1)\" to resolve the application data vs \"https://appd.foo.com/api/appd/v1/apps/app1@appd.foo.com\".\n\n### DNS/SRV Records\n\nAnother approach to support AppD service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an AppD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *service*: the symbolic name of the desired service.  For AppD service, this must be identified as \"**_appd**\"\n- *proto*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *name*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *TTL*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *class*: standard DNS class field (this is always *IN*).\n- *priority*: the priority of the target host, lower value means more preferred.\n- *weight*: A relative weight for records with the same priority, higher value means more preferred.\n- *port*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *target*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record **must use** the following definitions:\n\n- service = **_appd**\n- proto = **_tcp**\n- name = must map to the domain of the application identifier . Example:  the **name** for application identifier **\"app1.appd.foo.com\"** would be **\"appd.foo.com\"**\n\n**Known domains:**\n\nAlthough SRV records provide the means of resolving the location of an AppD service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that  the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n\n### Static configuration\n\nAs the name implies, a static configuration for the AppD service location is predefined within the launcher following the same domain:URI model mentioned in previous sections.\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/StaticConfig.png?version=1&modificationDate=1526330937517&cacheVersion=1&api=v2&width=800&height=376)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/app-directory/overview.md",
    "content": "---\nsidebar_label: App Directory Overview\ntitle: App Directory Overview\nhide_title: true\noriginal_id: overview\n---\n\n# App Directory Overview\n\nThe FDC3 App Directory provides trusted identity for financial desktop apps. This identity can be used to prevent spoofing and man-in-the-middle attacks when apps communicate with one another and exchange data. The App Directory also enables service discovery. Apps are registered with a declaration of the intents and context data that can be used when interoperating.\n\n## Core features\n\n- Provide verification of identity for an application running on a desktop - whether it is Native, Web, or Hybrid.\n- Resolve human readable names for applications to the location of and instructions for launching\n- Serve as a repository for application metadata supporting discoverability by intent, context, and other workflow driven facets.\n\n## Sections to review\n\n- [Application Directory Discovery](discovery.md) describes how to resolve the location of the Application Directory using an application identifier.\n- [Application Directory Usage](usage.md) provides a simple view on how application directories can be used.  This also includes links to a reference implementation.\n- [Application Directory specification](spec.md) is the interface definition required to support a compatible application directory.\n\nThe keywords \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in BCP 14, [RFC 2119](https://tools.ietf.org/id/draft-faltstrom-uri-11.html#RFC2119) [RFC2119]."
  },
  {
    "path": "website/versioned_docs/version-1.1/app-directory/spec.md",
    "content": "---\nsidebar_label: App Directory Specification\ntitle: App Directory Specification 1.1\noriginal_id: spec\n---\n## API\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/1.1/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/1.1/app-directory.yaml\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v1/apps`         | POST   | Create a new application definition\n `/v1/apps/{appId}` | GET    | Retrieve an application defintion\n `/v1/apps/search`  | GET    | Retrieve a list of applications\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/app-directory/usage.md",
    "content": "---\nsidebar_label: App Directory Usage\ntitle: App Directory Usage\nhide_title: true\noriginal_id: usage\n---\n\n# App Directory Usage\n\nAn application directory (AppD) provides information about an application's\nidentifiers, intents that provide contexts, and location of metadata providing\ninformation specific to the launching and integration of the application.\n\nIn the real world the AppD would support many use cases as defined in the\n[FDC3 Use Cases](../use-cases/overview)\n\nThe following provides some common use cases and benefits.\n\n## Embedded Launcher\n\nA desktop application has the ability to launch (or initialize) an application\nby retrieving all necessary data via a REST call(s) to an AppD service\nand metadata location. As described in the [AppD Discovery](discovery)\nsection, this call requires an application identifier (app1@host.appd.com),\nwhich can be used to both locate the AppD service and key to retrieve the\nspecific application data. The resulting application data will describe the\napplication and the metadata URI or the actual\nmetadata in JSON format. If the metadata is a URI, the launcher would\nretrieve the metadata file from the URI.\n\n![img](/assets/appd_launcher_embedded.png)\n\n\n## Standalone Launcher\n\nIn more advanced cases, there could be a need to execute different types\nof desktop applications, such as web browser or general native application\n(exe, binary). A common approach to support this pattern would be to\ncreate a standalone launcher application that has the ability to query\napplication data from the AppD and executes the desktop application that\ncan run the required application. This is also convenient if you wanted\nto display all possible applications to launch in a single view.\n\n![img](/assets/appd_launcher_standalone.png)\n\n\n## Aggregated View\n\nThere could be many different AppD service instances in the world providing\napplication data zoned to the provider or enterprise deployment. The\nAppD specification allows for unique instances of the service with no\nrequirement to aggregate data or define a structured hierarchy. With this\nsaid, a launcher might want to construct an aggregated view of applications\nfrom one or more AppD instances. In this case, the launcher would be\nrequired to retrieve multiple application definitions from one or more\nAppD instances providing a consolidated view of all applications required.\nToday there is no intention to create a single registry of known AppD\ninstances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location (FQDN).\n\n![img](/assets/appd_launcher_aggregated.png)\n\n\n## Enhancing controls\n\nThe AppD API specification defines the optional use of an access token to\nidentify the requesting user/launcher and implement authorizations around which AppD actions can be performed.  Actions are considered standard CRUD operations.\nAgain the specification does not define or make mandatory any authorizations\nor roles that a provider or enterprise can define.\n\nWith this said, it is highly recommended that the implementation take advantage\nand utilize an access token to support these controls. In most cases simple\nuse of roles like \"admin\" and \"user\" would be adequate to create separation\nbetween producer and consumer.\n\nAlternatively a more open approach can be defined, where producers of a new\ndefinition are automatically set to \"owner\" of the the definition.\n\nIn more advanced use cases, actual entitlements can be applied to limit\naccess to specific applications and associated actions based on the source\nuser/launcher identity.\n\nIn all examples, it is up to the implementation to define and engineer the solution\nbased on individual requirements. There are too many variations in approach\nand technology to define a single specification.\n\n\n\n## Reference Implementation\n\n### AppD POC\nPlease view readme on the [AppD POC GitHub](https://github.com/FDC3/appd-poc) .\n\n\n### Launcher\n\nTBD"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/overview.md",
    "content": "---\nsidebar_label: Context Data Overview\ntitle: Context Data Overview\nhide_title: true\noriginal_id: overview\n---\n\n# Context Data Overview\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to one another without any prior knowledge.  \n\nFDC3 Context Data defines a standard for passing common identifiers and data between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [Intents](../intents/overview) and when broadcasting context to other applications.\n\n## Context Object\n\nContext can be summarised as:\n* Having a unique _type_ identifier, used for routing.\n* Optionally providing a name.\n* Optionally providing a map of equivalent identifiers.\n* Any other properties or metadata.\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n## Example Context Object\n\nAn instrument could for example be derived as (note that the name is required and the type is fixed):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" : \n    {  \n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n    \"country\": \"US\"\n}\n```\n It is important to note that the context data specification allows extra identifiers and properties to be added as needed for each interop use case. In the example above, `country` could represent extra data in addition to the agreed instrument representation.\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Contact.md",
    "content": "---\nsidebar_label: Contact\ntitle: Contact\nhide_title: true\noriginal_id: Contact\n---\n# `Contact`\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Type\n\n`fdc3.contact`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/contact.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.contact'`  |\n| `name`      | string  | No       | `'Jane Doe'`      |\n| `id.email`  | string  | No       | `'jane@mail.com'` |\n| `id.FDS_ID` | string  | No       | `'ABC123-E'`      |\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact'\n    name: 'Jane Doe',\n    id: {\n        email: 'jane.doe@mail.com'\n    }\n}\n\n\nfdc3.broadcast(contact)\n```\n\n## See Also\n\nOther Types\n- [ContactList](ContactList)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [ViewContact](../../intents/ref/ViewContact)\n\nFINOS Financial Objects\n- [Contact](https://fo.finos.org/docs/objects/contact)"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/ContactList.md",
    "content": "---\nsidebar_label: ContactList\ntitle: ContactList\nhide_title: true\noriginal_id: ContactList\n---\n# `ContactList`\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nNotes:\n\n- The contact list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.contactList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/contactList.schema.json\n\n## Details\n\n| Property    | Type      | Required | Example Value          |\n|-------------|-----------|----------|------------------------|\n| `type`      | string    | Yes      | `'fdc3.contactList'`   |\n| `id`        | object    | No       | `{ customId: '5576' }` |\n| `name`      | string    | No       | `'My address book'`    |\n| `contacts`  | Contact[] | Yes      | `[contact1, contact2]` |\n\n## Example\n\n```js\nconst contacts = {\n    type: 'fdc3.contactList',\n    contacts: [\n        {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john.doe@mail.com'\n            }\n        },\n    ]\n}\n\n\nfdc3.raiseIntent('StartChat', contacts)\n```\n\n## See Also\n\nOther Types\n- [Contact](Contact)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n\nFINOS Financial Objects\n- [ContactList](https://fo.finos.org/docs/objects/contactlist)"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not \nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/context.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema. \nThe FDC3 [API](../../api/overview) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/overview) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardised FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. \nFor non-standard types, e.g. those defined and used by a particular organisation, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications\nidentify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\n## See Also\n\nFDC3 Specifications\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Country.md",
    "content": "---\nsidebar_label: Country\ntitle: Country\nhide_title: true\noriginal_id: Country\n---\n# `Country`\n\nAn entity that can be used when referencing countries that can be used on it's own as well as in other contexts when adding additional attributes e.g. when adding address details to a [Contact](../../context/ref/Contact)\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement\nis for at least one standardised identifier to be provided.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardised and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n\n## Type\n\n`fdc3.country`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/country.schema.json\n\n## Details\n\n| Property         | Type    | Required | Example Value        |\n|------------------|---------|----------|----------------------|\n| `type`           | string  | Yes      | `'fdc3.country'`     |\n| `name`           | string  | No       | `'Sweden'`           |\n| `id.ISOALPHA2`   | string  | No       | `'SE'`               |\n| `id.ISOALPHA3`   | string  | No       | `'SWE'`              |\n\n## Example\n\n```js\nconst country = {\n    type: 'fdc3.country'\n    name: 'Sweden',\n    id: {\n        ISOALPHA3: 'SWE'\n    }\n}\n\n\nfdc3.broadcast(country)\n```\n\n## See Also\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n- [Country](https://fo.finos.org/docs/objects/country)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Instrument.md",
    "content": "---\nsidebar_label: Instrument\ntitle: Instrument\nhide_title: true\noriginal_id: Instrument\n---\n# `Instrument`\n\nA financial instrument from any asset class.\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match.\n\nNotes:\n\n- Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified.\nIn general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\n- It is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement\nis for at least one instrument identifier to be provided.\n\n- Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant for stock tickers specifically,\nif the identifier you want to share is not a stock ticker, or one of the other standardised ones, rather define \na property that makes it clear what value it is. This makes it easier for target applications.\n\n## Type\n\n`fdc3.instrument`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/instrument.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value       |\n|-------------|---------|----------|---------------------|\n| `type`      | string  | Yes      | `'fdc3.instrument'` |\n| `name`      | string  | No       | `'Microsoft'`       |\n| `id.ticker` | string  | No       | `'MSFT'`            |\n| `id.BBG`    | string  | No       | `'MSFT:US'`         |\n| `id.CUSIP`  | string  | No       | `'594918104'`       |\n| `id.FDS_ID` | string  | No       | `'P8R3C2-R'`        |\n| `id.FIGI`   | string  | No       | `'BBG000BPH459'`    |\n| `id.ISIN`   | string  | No       | `'US5949181045'`    |\n| `id.PERMID` | string  | No       | `'4295907168'`      |\n| `id.RIC`    | string  | No       | `'MSFT.OQ'`         |\n| `id.SEDOL`  | string  | No       | `'2588173'`         |\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument'\n    name: 'Microsoft',\n    id: {\n        ticker: 'MSFT',\n        RIC: 'MSFT.OQ',\n        ISIN: 'US5949181045'\n    }\n}\n\nfdc3.joinChannel('global')\nfdc3.broadcast(instrument)\n```\n\n## See Also\n\nOther Types\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n- [Instrument](https://fo.finos.org/docs/objects/instrument)"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/InstrumentList.md",
    "content": "---\nsidebar_label: InstrumentList\ntitle: InstrumentList\nhide_title: true\noriginal_id: InstrumentList\n---\n# `InstrumentList`\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist).\n\nWhen holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type, though.\n\nNotes:\n\n- The instrument list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.instrumentList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/instrumentList.schema.json\n\n## Details\n\n| Property      | Type         | Required | Example Value                  |\n|---------------|--------------|----------|--------------------------------|\n| `type`        | string       | Yes      | `'fdc3.instrumentList'`        |\n| `name`        | string       | No       | `'Interesting instruments...'` |\n| `id`          | object       | No       | `{ customId: '5464' }`         |\n| `instruments` | Instrument[] | Yes      | `[instrument1, instrument2]`   |\n\n## Example\n\n```js\nconst instruments = {\n    type: 'fdc3.instrumentList',\n    instruments: [\n        {\n            type: 'fdc3.instrument',\n            id: {\n                ticker: 'AAPL'\n            }\n        },\n        {\n            type: 'fdc3.instrument',\n            id: {\n                ticker: 'MSFT'\n            }\n        },\n    ]\n}\n\nfdc3.joinChannel('global')\nfdc3.broadcast(instruments)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n- [InstrumentList](https://fo.finos.org/docs/objects/instrumentlist)"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Organization.md",
    "content": "---\nsidebar_label: Organization\ntitle: Organization\nhide_title: true\noriginal_id: Organization\n---\n# `Organization`\n\nAn entity that can be used when referencing private companies and other organizations where a specific intrument is not availabe or desired e.g. CRM and News workflows.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement\nis for at least one specified identifier to be provided.\n\n## Type\n\n`fdc3.organization`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/organization.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value             |\n|-------------|---------|----------|---------------------------|\n| `type`      | string  | Yes      | `'fdc3.organization'`     |\n| `name`      | string  | No       | `'Cargill, Incorporated'` |\n| `id.LEI`    | string  | No       | `'QXZYQNMR4JZ5RIRN4T31'`  |\n| `id.PERMID` | string  | No       | `'4296555324'`            |\n| `id.FDS_ID` | string  | No       | `'00161G-E'`              |\n\n## Example\n\n```js\nconst organization = {\n    type: 'fdc3.organization'\n    name: 'Cargill, Incorporated',\n    id: {\n        LEI: 'QXZYQNMR4JZ5RIRN4T31',\n        FDS_ID: '00161G-E'\n    }\n}\n\n\nfdc3.broadcast(organization)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n- [Organization](https://fo.finos.org/docs/objects/organization)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Portfolio.md",
    "content": "---\nsidebar_label: Portfolio\ntitle: Portfolio\nhide_title: true\noriginal_id: Portfolio\n---\n# `Portfolio`\n\nA financial portfolio made up of muliple positions (holdings) in several instruments. Contrast this\nwith e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe [Portfolio](Portfolio) type consists of an array of [Position](Position) types, each of which\nrefers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the portfolio can be added, the schema just \nspecifies the minimum contract.\n\n- The portfolio schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.portfolio`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/portfolio.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.portfolio'`        |\n| `id`         | object     | No       | `{ portfolioId: '7381' }` |\n| `name`       | string     | No       | `'My share portfolio'`    |\n| `positions`  | Position[] | Yes      | `[position1, position2]`  |\n\n## Example\n\n```js\nconst position = {\n    type: 'fdc3.portfolio',\n    positions: [\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument'\n                id: {\n                    ticker: 'AAPL'\n                }\n            },\n            holding: 2000000\n        },\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument'\n                id: {\n                    ticker: 'MSFT'\n                }\n            },\n            holding: 1500000\n        },\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument'\n                id: {\n                    ticker: 'IBM'\n                }\n            },\n            holding: 3000000\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewAnalysis', portfolio)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/ref/Position.md",
    "content": "---\nsidebar_label: Position\ntitle: Position\nhide_title: true\noriginal_id: Position\n---\n# `Position`\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good\nexample of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents\nmultiple holdings in a combination of instruments.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the position can be added, the schema just \nspecifies the minimum contract.\n\n- The position schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.position`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.1/position.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value                      |\n|--------------|------------|----------|------------------------------------|\n| `type`       | string     | Yes      | `'fdc3.position'`                  |\n| `id`         | object     | No       | `{ positionId: '6475' }`           |\n| `name`       | string     | No       | `'My Apple shares'`                |\n| `holding`    | number     | Yes      | `2000000`                          |\n| `instrument` | Instrument | Yes      | `{ type: 'fdc3.instrument', ... }` |\n\n## Example\n\n```js\nconst position = {\n    type: 'fdc3.position',\n    instrument: {\n        type: 'fdc3.instrument'\n        id: {\n            ticker: 'AAPL'\n        }\n    },\n    holding: 2000000\n}\n\nfdc3.raiseIntent('ViewChart', position)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/position)"
  },
  {
    "path": "website/versioned_docs/version-1.1/context/spec.md",
    "content": "---\nsidebar_label: Context Data Specification\ntitle: Context Data Specification 1.1\noriginal_id: spec\n---\n\n## Introduction\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems.\n\nExchanging context is the most basic entry point to desktop interoperability. The barriers to adoption for this interaction must be kept as low as possible.\n\nThere are two main use cases for exchanging context data:\n\n* __Transmitting reference data between applications.__\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n* __Transferring information between applications.__\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there isn't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n## The Context Interface\n\n```ts\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n### Namespacing\n\nAll well-known types at FDC3 level should be prefixed with `fdc3`. For private type definitions, or type definitions issued by other organisations, different namespaces can be used, e.g. `blackrock.fund`, etc.\n\n### Versioning\n\nThe specification recognises that evolving context data definitions over time, and helping applications to deal with changes to types, are very important.\n\nIt may be as simple as adding an optional `$version` property to types, but it could also be a set of guidelines for adding new properties, without removing or changing existing ones. For example, web technologies like REST or GraphQL do not take a particular opinion about versioning.\n\n### Identifiers\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n## Standard Context Types\n\nThe following are standard FDC3 context types.\n __Note:__ The specification for these types are shared with the [FINOS Financial Objects](https://fo.finos.org) definitions, JSON schemas are hosted with FDC3.\n\n- __fdc3.contact__\n    - A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/contact)\n    - [schema](pathname:///schemas/1.1/contact.schema.json)\n- __fd3.contactList__\n    - A collection of contacts.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/contactlist)\n    - [schema](pathname:///schemas/1.1/contactList.schema.json)\n- __fdc3.country__\n    - A standard country entity.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/country)\n    - [schema](pathname:///schemas/1.1/country.schema.json)\n- __fdc3.instrument__\n    - A financial instrument from any asset class.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/instrument)\n    - [schema](pathname:///schemas/1.1/instrument.schema.json)\n- __fdc3.instrumentList__\n    - A collection of instruments.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/instrumentList)\n    - [schema](pathname:///schemas/1.1/instrumentList.schema.json)\n- __fdd3.organization__\n    - A standard organization entity.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/organization)\n    - [schema](pathname:///schemas/1.1/organization.schema.json)\n- __fdc3.portfolio__\n    - A collection of positions.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/portfolio)\n    - [schema](pathname:///schemas/1.1/portfolio.schema.json)\n- __fdc3.position__\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/position)\n    - [schema](pathname:///schemas/1.1/position.schema.json)\n\n__Note:__ The below examples show how the base context data interface can be used to define specific context data objects. It is not the purpose of the specification at this stage to define standard representations for objects. It establishes the framework in which such definitions could be created.\n\n### Examples\n\n#### Contact\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### ContactList\n```json\n{\n    \"type\": \"fdc3.contactList\",\n    \"name\": \"client list\",\n    \"contacts\":[\n        {\n            \"type\":\"fdc3.contact\",\n            \"name\":\"joe\",\n            \"id\":{\n                \"email\": \"joe@company1.com\",\n            }\n        },\n        {\n            \"type\":\"fdc3.contact\",\n            \"name\":\"jane\",\n            \"id\":{\n                \"email\": \"jane@company2.com\",\n            }\n        }\n    ]\n}\n```\n\n#### Country\n```json\n{\n    \"type\":\"fdc3.country\",\n    \"name\":\"the USA\",\n    \"id\":{\n        \"ISOALPHA2\":\"US\",\n        \"ISOALPHA3\":\"USA\"\n    }\n}\n```\n\n#### Instrument\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### InstrumentList\n```json\n{\n    \"type\" : \"fdc3.instrumentList\",\n    \"name\" : \"my portfolio\",\n    \"instruments\" : [\n        {\n            \"type\" : \"fdc3.instrument\",\n            \"name\" : \"Apple\",\n            \"id\": {\n               \"ticker\" : \"aapl\"\n            }\n        },\n        {\n            \"type\" : \"fdc3.instrument\",\n            \"name\" : \"International Business Machines\",\n            \"id\": {\n               \"ticker\" : \"ibm\"\n            }\n        }\n    ]\n}\n```\n\n#### Organization\n```json\n{\n    \"type\": \"fdc3.organization\",\n    \"name\": \"IBM\",\n    \"id\": {\n        \"PERMID\" : \"4295904307\",\n        \"LEI\" : \"VGRQXHF3J8VDLUA7XE92\"\n    }\n}\n```\n\n#### Portfolio\n```json\n{\n    \"type\":\"fdc3.portfolio\"\n    \"name\":\"my portfolio\",\n    \"positions\":[\n        {\n            \"type\": \"fdc3.position\",\n            \"instrument\": {\n                \"type\" : \"fdc3.instrument\",\n                \"name\" : \"Apple\",\n                \"id\" :\n                {\n                    \"ISIN\" : \"US0378331005\"\n                }\n            },\n            \"holding\": 500\n        },\n         {\n            \"type\": \"fdc3.position\",\n            \"instrument\": {\n                \"type\" : \"fdc3.instrument\",\n                \"name\" : \"IBM\",\n                \"id\" :\n                {\n                    \"ISIN\" : \"US4592001014\"\n                }\n            },\n            \"holding\": 1000\n        }\n    ]\n}\n```\n\n\n#### Position\n```json\n{\n    \"type\": \"fdc3.position\",\n    \"instrument\": {\n        \"type\" : \"fdc3.instrument\",\n        \"name\" : \"Apple\",\n        \"id\" :\n        {\n            \"ISIN\" : \"US0378331005\"\n        }\n    },\n    \"holding\": 500\n}\n```\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/fdc3-charter.md",
    "content": "---\nsidebar_label: Charter\ntitle: FDC3 Charter\nhide_title: true\noriginal_id: fdc3-charter\n---\n\n# FDC3 Charter\n\n## Summary\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\n## Scope\nFinancial desktop applications include any app used in common financial workflows:\n\n* Traditional native applications implemented in C++, .NET, Java, Python, etc.\n* Hybrid web/native applications - stand alone native apps embedding Chromium (e.g. Electron, CEF, NW.js) \n* Desktop web applications - platform based apps extending Chromium (e.g. OpenFin, Finsemble, Glue42)\n* Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, etc. \n* PWAs & Web applications running in a commercial browser\n\nThis standards group is focused specifically on the desktop.  Activities of the desktop interoperability group do not include:\n\n* Defining financial objects - where existing standards are well established\n* Interoperability between mobile apps\n* Interoperability via REST or other client to server communication\n\nNote: While these areas are out of scope, compatibility with Mobile and/or REST are still valid points of consideration for the FDC3.\n\n## Success Criteria\n* Commitment from major banks and application vendors to support the standards set out by the FDC3\n* Workflow integrations in the wild leveraging the standards\n\n## Deliverables\n* Define criteria and mechanics for secure communication between apps\n* Define key functions that require specific standards for interoperability \n* Create an agreed taxonomy for common app “intents” within financial desktop workflows\n* Create an agreed taxonomy for common data to be shared across apps within financial desktop workflows\n* Provide reference implementations of all standards\n* Maintain the above standards and reference implementations \n\n### Participation\nTo be successful, the FDC3 is expected to have a critical mass of active participants for its duration. Effective participation in FDC3 means participation in the form of research, authoring, editing, and development activities outside the scope of attending regular meetings.\n\n### Licensing\nThe FDC3 will use Apache 2.0 license or similar for all deliverables. \n"
  },
  {
    "path": "website/versioned_docs/version-1.1/fdc3-compliance.md",
    "content": "---\ntitle: FDC3 Specification Compliance\nsidebar_label: FDC3 Compliance\noriginal_id: fdc3-compliance\n---\n\n\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>   Imperatives of the type defined in this memo must be used with care\n>   and sparingly.  In particular, they MUST only be used where it is\n>   actually required for interoperation or to limit behavior which has\n>   potential for causing harm (e.g., limiting retransmisssions)  For\n>   example, they must not be used to try to impose a particular method\n>  on implementors where the method is not required for\n>   interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers API, App Directory, Context Data, and Intents working groups, it does not apply to the Use Cases working group. \n\n## Personas\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation of the FDC3 API for applications to use. Implicitly, it connects to one or more App Directories.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.  \n\nDepending on persona, implementation compliance with FDC3 will mean different things.  \n\n### Platform Provider\nTo meet the requirements of FDC3, a platform provider would need to support the following:\n\n* Connection to 1 or more App Directories meeting the FDC3 App Directory standards\n* Provide an API to all applications running in the context of the platform that meets the FDC3 API standards, including:\n    * Support for FDC3 Context Data and Intents standards\n    * Support for Intent and Context resolution using a resolver UI\n* At least one workflow of one of the use cases marked as Accepted by the Use Cases working group SHOULD be satisfied by the implementation.\n\n### Application Provider\nFor application providers FDC3 compliance requires:\n* If intents are supported by the application, they SHOULD favor supporting applicable FDC3 defined intents over proprietary ones.  \n* If FDC3 defined intents are supported, they MUST meet the expected context and behavior defined for the intent.  \n* If proprietary intents are handled, those intents SHOULD follow the recommended naming conventions in the specification.\n* If intents are supported, the application SHOULD use the addIntentListener API to set up a handler.\n* If Context Data is supported by the application, they SHOULD favor supporting applicable FDC3 defined Context Data over proprietary ones.  \n* If FDC3 defined Context Data is supported, it MUST meet the interface defined for the type of Context Data.  \n* If proprietary Context Data properties are handled, they SHOULD follow any recommended naming conventions in the specification.\n* If Context Data is supported, the application SHOULD use the addContextListener API to set up a handler.\n\n## References\nThe following specifications and use case references apply to the above:\n* [API](api/spec)\n* [App Directory](app-directory/spec)\n* [Context Data](context/spec)\n* [Intents](intents/spec)\n* [Use Cases](use-cases/overview)\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/fdc3-intro.md",
    "content": "---\ntitle: Welcome to FDC3\nsidebar_label: Introduction\noriginal_id: fdc3-intro\n---\n![FDC3](/assets/fdc3-logo.png)\n\nThe mission of FDC3 is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements. [Read the Charter](fdc3-charter.md).\n\nFDC3 was launched in October 2017 by [OpenFin](http://www.openfin.co) in collaboration with major industry participants. It includes representatives from over 40 major banks, buy-side firms, consultancies and financial services platforms. FDC3 uses the Apache 2.0 open source license for all deliverables.\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services."
  },
  {
    "path": "website/versioned_docs/version-1.1/fdc3-standard.md",
    "content": "---\ntitle: FDC3 1.1\nsidebar_label: FDC3 1.1 Abstract\noriginal_id: fdc3-standard\n---\n\n**Status:** Superceded  \n_**adopted:** 1st Apr 2020_  \n_**released:** 14th Apr 2020_  \n_**superseded:** 1st Apr 2021_  \n\n## Abstract\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of four complementary parts:\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain. \n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n\n## Versioning\nThis Standard defines FDC3 Version 1.1. The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md). \n\n## Table of Contents\n- [Compliance information](fdc3-compliance)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part ](app-directory/spec)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/overview.md",
    "content": "---\nsidebar_label: Intents Overview\ntitle: Intents Overview\nhide_title: true\noriginal_id: overview\n---\n\n# Intents Overview\n\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to another without any prior knowledge.\n\n\nFDC3 Intents define a standard set of verbs that can be used to put together common cross-application workflows on the financial desktop.\n* Applications register the Intents & [Context Data](../context/overview) combinations they support in the [App Directory](../app-directory/overview)\n* The App Directory supports application discovery by Intents and/or Context Data\n* Intents are not full RPC, apps don’t need to enumerate every function with an intent\n* FDC3 Standard Intents are a limited set, organizations can create their own intents\n\n## Using Intents\nCombined with [Context Data](../context/overview) and [App Directory](../app-directory/overview) standards, Intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n type: \"fdc3.contact\",\n name: \"Jane Doe\",\n id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/StartCall.md",
    "content": "---\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\noriginal_id: StartCall\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n- [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/StartChat.md",
    "content": "---\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\noriginal_id: StartChat\n---\n# `StartChat`\n\nInitiate a chat with a contact or list of contacts.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n- [StartCall](StartCall)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewAnalysis.md",
    "content": "---\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\noriginal_id: ViewAnalysis\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewChart.md",
    "content": "---\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\noriginal_id: ViewChart\n---\n# `ViewChart`\n\nDisplay a chart for the provided instrument(s).\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Portfolio](../../context/ref/Portfolio)\n* [Position](../../context/ref/Position)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n- [ViewQuote](ViewQuote)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewContact.md",
    "content": "---\nsidebar_label: ViewContact\ntitle: ViewContact\nhide_title: true\noriginal_id: ViewContact\n---\n# `ViewContact`\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n\nIntents\n- [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewInstrument.md",
    "content": "---\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\noriginal_id: ViewInstrument\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewNews.md",
    "content": "---\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\noriginal_id: ViewNews\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n* [Country](../../context/ref/Country)\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n\nIntents\n- [ViewAnalysis](ViewAnalysis)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/ref/ViewQuote.md",
    "content": "---\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\noriginal_id: ViewQuote\n---\n# `ViewQuote`\n\nDisplay pricing for an instrumen.\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.1/intents/spec.md",
    "content": "---\nsidebar_label: Intents Specification\ntitle: Intents Specification 1.1\noriginal_id: spec\n---\n\n## Introduction\n\nFDC3 [Intents](../intents/overview) define a standard set of nouns and verbs that can be used to put together common cross-application workflows on the financial desktop.\n\n### Naming Syntax\n* Intent names should be free of non-alphanumeric characters.\n* ‘.’ will be used to namespace the intent (see below).\n* Intent names should be in UpperCamelCase.\n\n### Characteristics\n\nIntents shoulde be:\n* Recognizable\n    * Generally self-evident what the thing is\n* Repeatable\n    * Many instances across the industry\n* Stateless\n    * Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n* Specific\n    * Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n* Distinct\n    * Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces ###\nAll standard Intent names are reserved. Applications may use their own Intents ad hoc.\nHowever, there is a need for applications to ensure that their Intents avoid collision. The recommended approach here is to use the app name as the noun. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary Intent.\n\n## Initial Set of Standard Intents ##\n\n### StartCall\n  * Expected Context: Contact\n  * Expected behavior: initiate call with contact(s)\n### StartChat\n  * Expected Context: Contact\n  * Expected behavior: initiate chat with contact(s)\n### ViewChart\n  * Expected Context: Instrument\n  * Expected behavior: display a chart for the context\n### ViewContact\n  * Expected Context: Contact\n  * Expected behavior: display details of a contact\n### ViewQuote\n  * Expected Context: Instrument\n  * Expected behavior: display pricing for an instrument\n### ViewNews\n  * Expected Context: Instrument, Contact, Organisation, etc.\n  * Expected behavior: display news for a given context\n### ViewInstrument\n  * Expected Context: Instrument\n  * Expected behavior: display relevant information for a given instrument\n### ViewAnalysis\n  * Expected Context: Instrument, Organization, etc.\n  * Expected behavior: Send context to receiving application for displaying analysis\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\noriginal_id: uc-1\n---\n\n## Preconditions\nOn their desktop, this user has:\n- Their firm's internal research & analytics platform containing liquidity tools and internal research. The product is running and the liquidity tool is open\n- An installed chat application - product is running\n- A third party market data terminal with 3 open applications. These applications are all 'linked' through a channel. \n    - A Watchlist\n    - An Order Book\n    - An Overview of pricing and fundamental data\n- A third party Charting Application access via a browser window. This is not open. \n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\noriginal_id: uc-2\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\noriginal_id: uc-3\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\noriginal_id: uc-4\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\noriginal_id: uc-5\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/009-call-transcription-to-crm.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Call Transcription to CRM\"\nsidebar_label: 9. Call Transcription to CRM\nlayout: use_case\noriginal_id: uc-9\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/010-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Real-Time voice trades -> trade ticket population\"\nsidebar_label: 10. Real-Time voice trades -> trade ticket population\nlayout: use_case\noriginal_id: uc-10\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/013-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-13\ntitle: \"Use Case 13: User launches multiple apps from a single container\"\nsidebar_label: 13. User launches multiple apps from a single container\nlayout: use_case\noriginal_id: uc-13\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/015-sales-floor-base-workflow.md",
    "content": "---\nid: uc-15\ntitle: \"Use Case 15: Sales Floor Base Workflow\"\nsidebar_label: 15. Sales Floor Base Workflow\nlayout: use_case\noriginal_id: uc-15\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/016-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-16\ntitle: \"Use Case 16: Quantifying FDC3 Interactions\"\nsidebar_label: 16. Quantifying FDC3 Interactions\nlayout: use_case\noriginal_id: uc-16\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/017-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-17\ntitle: \"Use Case 17: Fine-tuning InterOp with Channels\"\nsidebar_label: 17. Fine-tuning InterOp with Channels\nlayout: use_case\noriginal_id: uc-17\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.1/use-cases/overview.md",
    "content": "---\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\noriginal_id: overview\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-1.1/why-fdc3.md",
    "content": "---\nsidebar_label: Why FDC3\ntitle: Why FDC3\noriginal_id: why-fdc3\n---\n\n## Why look for FDC3 enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go. The main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3 enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context)\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc. Every application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3 enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3 enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration, with an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\n```typescript\ntype Context = object;\n```\n\nThe base object that all contexts should extend.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\n## Methods\n\n### `open`\n\n```typescript\nopen(name: string, context?: Context): Promise<void>;\n```\n\nLaunches/links to an app by name.\n\nIf a [`Context`](Context) object is passed in, this object will be provided to the opened application via a contextListener.\nThe Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\nIf opening errors, it returns an `Error` with a string from the [`OpenError`](Errors#openerror) enumeration.\n\n#### Example\n ```javascript\n//no context\nawait agent.open('myApp');\n\n//with context\nawait agent.open('myApp', context);\n```\n\n#### See also\n* [`Context`](Context)\n* [`OpenError`](Errors#openerror)\n\n### `findIntent`\n\n```typescript\nfindIntent(intent: string, context?: Context): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context.\n\n_findIntent_ is effectively granting programmatic access to the Desktop Agent's resolver. \nIt returns a promise resolving to the intent, its metadata and metadata about the apps that are registered to handle it.\nThis can be used to raise the intent against a specific app.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n\n#### Examples\n```javascript\n// I know 'StartChat' exists as a concept, and want to know more about it ...\nconst appIntent = await agent.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }\n\n// raise the intent against a particular app\nawait agent.raiseIntent(appIntent.intent.name, context, appIntent.apps[0].name);\n```\n\n#### See also\n* [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```typescript\nfindIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context.\n_findIntentsByContext_ is effectively granting programmatic access to the Desktop Agent's resolver. \nA promise resolving to all the intents, their metadata and metadata about the apps that registered as handlers is returned, based on the context types the intents have registered.\n \n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n \n #### Examples\n ```javascript\n // I have a context object, and I want to know what I can do with it, hence, I look for intents...\n const appIntents = await agent.findIntentsByContext(context);\n \n // returns, for example:\n // [{\n //     intent: { name: \"StartCall\", displayName: \"Call\" },\n //     apps: [{ name: \"Skype\" }]\n // },\n // {\n //     intent: { name: \"StartChat\", displayName: \"Chat\" },\n //     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n // }];\n \n // select a particular intent to raise\n const startChat = appIntents[1];\n \n // target a particular app\n const selectedApp = startChat.apps[0];\n \n // raise the intent, passing the given context, targeting the app\n await agent.raiseIntent(startChat.intent.name, context, selectedApp.name);\n ```\n\n#### See also\n   * [`ResolveError`](Errors#resolveerror)\n\n### `broadcast`\n```typescript\nbroadcast(context: Context): void;\n```\n\nPublishes context to other apps on the desktop.\n\n#### Examples\n```javascript\nagent.broadcast(context);\n```\n#### See also\n* [addContextListener](#addcontextlistener)\n\n### `raiseIntent`\n\n```typescript\nraiseIntent(intent: string, context: Context, target?: string): Promise<IntentResolution>;\n```\nRaises an intent to the desktop agent to resolve.\n#### Examples\n```javascript\n//raise an intent to start a chat with a given contact\nconst intentR = await agent.findIntents(\"StartChat\", context);\n//use the IntentResolution object to target the same chat app with a new context\nagent.raiseIntent(\"StartChat\", newContext, intentR.source);\n```\n#### See also\n* [`IntentResolution`](#intentresolution)\n\n### `addIntentListener`\n```typescript\naddIntentListener(intent: string, handler: (context: Context) => void): Listener;\n```\n Adds a listener for incoming Intents from the Agent.\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n### `addContextListener`\n```typescript\naddContextListener(handler: (context: Context) => void): Listener;\n```\nAdds a listener for incoming context broadcast from the Desktop Agent.\n\n#### See also\n* [`Listener`](#listener)\n* [`Context`](Context)\n\n## Return Types\n\n### `AppIntent`\n\n```typescript\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\nAn interface that represents the binding of an intent to apps\n\n#### See also\n* [`IntentMetadata`](#intentmetadata)\n* [`AppMetadata`](#appmetadata)\n\n### `IntentMetadata`\n\n```typescript\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n### `AppMetadata`\n\n```typescript\ninterface AppMetadata {\n  name: string;\n}\n```\n\nApp metadata is Desktop Agent specific - but should always support a name property.\n\n### `IntentResolution`\n\n```typescript\ninterface IntentResolution {\n  source: string;\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n \n#### Example\n```javascript\n//resolve a \"Chain\" type intent\nvar intentR = await agent.raiseIntent(\"intentName\", context);\n//resolve a \"Client-Service\" type intent with data response\nvar intentR = await agent.raiseIntent(\"intentName\", context);\nvar dataR = intentR.data;\n```\n\n#### See also\n* [`DesktopAgent.raiseIntent`](#raiseintent)\n\n\n### `Listener`\n\n```typescript\ninterface Listener {\n  unsubscribe();\n}\n```\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](#addintentlistener) or [`addContextListener`](#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\nThe `unsubscribe` method on the listener object allows the application to cancel the subscription.\n\n#### See also\n* [`DesktopAgent.addIntentListener`](#addintentlistener)\n* [`DesktopAgent.addContextListener`](#addcontextlistener)\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/Errors.md",
    "content": "---\nsidebar_label: Errors\ntitle: Errors\nhide_title: true\noriginal_id: Errors\n---\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n* [`DesktopAgent.open`](DesktopAgent#open)\n\n\n## `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/api-intro.md",
    "content": "---\nsidebar_label: API Overview\ntitle: API Overview\nhide_title: true\noriginal_id: api-intro\n---\n# API Overview\n\nFDC3 API standards support the following goals:\n- Create a consistent developer interface for working with FDC3 \n- Standardize interfaces for reference implementations\n- Standardize interfaces between Desktop Agents\n\nThe role of FDC3 API standards is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications - standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary its importance.\n\nThe focus on the API working group has been to create a small but consistent API, the following docs go through the components and API's in detail.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/api-spec.md",
    "content": "---\nsidebar_label: API Specification\ntitle: API Specification 1.0\noriginal_id: api-spec\n---\n\n## Components\n### Desktop Agent\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- OpenFin\n- Autobahn\n- ThomsonReuters Eikon\n\nDesktop Agents expose an FDC3 standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n#### Inter-Agent Communication\nA goal of FDC3 standards is that applications running in different Desktop Agent contexts on the same desktop would be able to interoperate.  And that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\nDesktop Agent interop is supported by common standards for APIs for App discovery and launching.  So, an App in one Desktop Agent context would not need to know a different syntax to call an App in another Desktop Agent context.\n\nThe actual connection protocol between Desktop Agents is not currently in scope for FDC3 standards.  Given that there are a relatively small number of Desktop Agents, and that any given desktop will have a finite and relatively static number of Desktop Agents installed at any given time, the connectivity between different Agents can be adequately handled for the time being on a case-by-case basis.\n\n### Application\nAn application is any endpoint on the desktop that is:\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of End Points include:\n- Native Applications\n- PWA/Web Applications\n- Headless “services” running on the desktop\n\n## Functional Use Cases\n### Open an Application by Name\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Raising Intents\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that Intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).   Currently, this is the primary focus in FDC3\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client.  Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n#### Intent Resolution\nRaising an Intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n##### Resolve\n- Intent was resolved unambiguously and the receiving app was launched successfully.\n- Intent was ambiguous, a resolution was chosen by the end user and the chosen application was launched successfully.\n\n##### Reject\n- An app matching the intent was not found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n##### Resolution Object\nIf the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format:\n\n```javascript\n{\n    source: String;\n    data?: Object;\n    version: String;\n}\n```\n- *source* = identifier for the Application resolving the intent (null if the intent could not be resolved)\n- *data* = return data structure - if one is provided for the given intent\n- *version* = the version number of the Intents schema being used\n\nFor example\n\n```javascript\ntry {\n    let result = await agent.raiseIntent('StageOrder');\n    if (result.data){\n        let orderId = result.data.id;\n    }\n}\ncatch (er){\n    console.log(er.message);\n}\n\n```\n\n##### Upgrading to a Remote API Connection\nThere are a wide range of workflows where decoupled intents and/or context passing do not provide rich enough interactivity and applications are better off exposing proprietary APIs.  In these cases, an App can use the *source* property on the resolution of an intent to connect directly to another App and from there, call remote APIs using the methods available in the Desktop Agent context for the App.  For example:\n\n```javascript\n    let chart = await agent.raiseIntent('ViewChart');\n     //construct an OpenFin wrapper for the App\n    let chartApp = fin.Application.wrap(chart.source);\n    //do some OpenFin specific stuff\n```\n![Upgrading Connection to Remote API](/assets/api-3.png)\n\n### Register an Intent\nApplications 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.\n\n#### Compliance with Intent Standards\nIntents 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.\n\nIt is expected that App Directories will also curate listed apps and ensure that they are complying with declared intents.\n\nLike FDC3 Context Data, the Intent schemas need to be versioned.  Desktop Agents will be responsible to declare which version of the Intent schema they are using.   Applications may also assert a specific version requirement when raising an Intent.  Version negotiation may be supported by a given Desktop Agent.\n\n### Send/broadcast context\nOn the financial desktop, applications often want to broadcast context to any number of applications.  Context sharing needs to support concepts of different groupings of applications as well as data privacy concerns.  Each Desktop Agent will have its own rules for supporting these features.\n\n## Resolvers\nIntents functionality is dependent on resolver functionality to map the intent to a specific App.  This will often require end-user input.  Resolution can either be performed by the Desktop Agent (raising UI to pick the desired App for the intent) or by the app launching the intent - in which case the calling App will handle the resolution itself (using the findIntents API below) and then invoke an explicit Intent object.\n\n## APIs\nThe APIs are defined in TypeScript in [src], with the documentation generated in the [docs] folder.\n\n[src]: https://github.com/finos/FDC3/tree/main/src/api\n[docs]: https://github.com/finos/FDC3/tree/main/docs/api\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/overview.md",
    "content": "---\nsidebar_label: API Overview\ntitle: API Overview\nhide_title: true\noriginal_id: overview\n---\n# API Overview\n\nThe API specification of the FDC3 standard support the following goals:\n- Create a consistent developer interface for working with FDC3\n- Standardize interfaces for reference implementations\n- Standardize interfaces between desktop agents\n\nThe role of FDC3 API specification is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications - standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe focus of the FDC3 Standard Working Group has been to create a small but consistent API, the following docs go through the components and API's in detail.\n\n## Key Elements\n\n- [`window.fdc3`](ref/Globals#windowfdc3-object) global object and [`fdc3Ready`](ref/Globals#fdc3ready-event) event, for accessing FDC3 operations globally\n- [`DesktopAgent`](ref/DesktopAgent) interface, which exposes FDC3 operations\n- [`Channel`](ref/Channel) interface, for subscribing to specific context channels\n- [`Listener`](ref/Types#listener) interface, which allows unsubscribing intent or context listeners\n\n## Usage\n\nThere are two main ways FDC3 can be used from web applications:\n\n### 1. Direct Usage\n\nSimply rely on the global object being made available by your desktop agent, and address the API directly:\n\n```ts\nfunction sendData() {\n  window.fdc3.broadcast({\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n  })\n}\n\nif (window.fdc3) {\n  sendData();\n} else {\n  window.addEventListener(\"fdc3Ready\", sendData);\n}\n```\n\n\n### 2. NPM Wrapper\n\nThe [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) provides a wrapper around FDC3, allowing you to use it with ES6 import syntax:\n\n```ts\nimport * as fdc3 from '@finos/fdc3'\n\nawait fdc3.raiseIntent('ViewAnalysis', {\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n})\n```\n\nIt also includes a helper function you can use to wait for FDC3 to become available:\n\n```ts\nimport { fdc3Ready, addIntentListener } from '@finos/fdc3'\n\nawait fdc3Ready();\n\nconst listener = addIntentListener('ViewAnalysis', instrument => {\n  // handle intent\n})\n```\n\n#### See also\n* [`fdc3Ready() Function`](ref/Globals#fdc3ready-function)\n\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/AppIntent.md",
    "content": "---\nsidebar_label: AppIntent\ntitle: AppIntent\nhide_title: true\noriginal_id: AppIntent\n---\n# `AppIntent`\n\n```ts\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\nAn interface that represents the binding of an intent to apps, returned as part of intent disocvery. \nFor each intent, it reference the applications that support that intent.\n\n#### See also\n* [`AppMetadata`](AppMetadata)\n* [`IntentMetadata`](IntentMetadata)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/AppMetadata.md",
    "content": "---\nsidebar_label: AppMetadata\ntitle: AppMetadata\nhide_title: true\noriginal_id: AppMetadata\n---\n# `AppMetadata`\n\n```ts\ninterface AppMetadata {\n  name: string;\n  title?: string;\n  tooltip?: string;\n  description?: string;\n  icons?: Array<string>;\n  images?: Array<string>;\n}\n```\n\nApp metadata is provided by the FDC3 App Directory that the desktop agent connects to.\n\nIt always includes at least a `name` property, which can be used with [`open`](DesktopAgent#open) and [`raiseIntent`](DesktopAgent#raiseintent).\n\nOptionally, extra information from the app directory can be returned, to aid in rendering UI elements, e.g. a context menu.\nThis includes a title, description, tooltip and icon and image URLs.\n\n#### See also\n\n* [`AppIntent.apps`](AppIntent)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Channel.md",
    "content": "---\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\noriginal_id: Channel\n---\n# `Channel`\n\nRepresents a context channel that applications can use to send and receive context data.\n\nA channel can be either a well-known \"system\" channel (retrieved with [`getSystemChannels`](DesktopAgent#getsystemchannels)) or a custom \"app\" channel (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)).\n\n:::note\n\nThere are differences in behavior when you interact with a System channel via the `DesktopAgent` interface and the `Channel` interface. Specifically, when 'joining' a System channel or adding a context listener when already joined to a channel via the `DesktopAgent` interface, existing context (matching the type of the context listener) on the channel is received by the context listener immediately. Whereas, when a context listener is added via the `Channel` interface, context is not received automatically, but may be retrieved manually via the [`getCurrentContext()`](#getcurrentcontext) function.\n\n:::\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: string;\n  displayMetadata?: DisplayMetadata;\n\n  // methods\n  broadcast(context: Context): void;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Listener;\n  /**\n   * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Listener;\n}\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`Listener`](Types#listener)\n* [`DesktopAgent.getSystemChannels`](DesktopAgent#getsystemchannels)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`DesktopAgent.joinChannel`](DesktopAgent#joinchannel)\n\n## Properties\n\n### `id`\n\n```ts\npublic readonly id: string;\n```\n\nUniquely identifies the channel. It is either assigned by the desktop agent (system channel) or defined by an application (app channel).\n\n### `type`\n\n```ts\npublic readonly type: string;\n```\n\nCan be _system_ or _app_.\n\n### `displayMetadata`\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\nDisplayMetadata can be used to provide display hints for channels intended to be visualized and selectable by end users.\n\n#### See also\n* [`DisplayMetadata`](Metadata#displaymetadata)\n\n## Methods\n\n\n### `addContextListener`\n```ts\npublic addContextListener(contextType: string | null, handler: ContextHandler): Listener;\n```\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\n```ts\n/**\n * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\npublic addContextListener(handler: ContextHandler): Listener;\n```\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n\n#### Examples\n\nAdd a listener for any context that is broadcast on the channel:\n\n```ts\nconst listener = channel.addContextListener(null, context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n```ts\nconst contactListener = channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n#### See also\n* [`Listener`](Types#listener)\n* [`ContextHandler`](Types#contexthandler)\n* [`broadcast`](#broadcast)\n* [`getCurrentContext`](#getcurrentcontext)\n\n### `broadcast`\n\n```typescript\npublic broadcast(context: Context): void;\n```\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the method will return an `Error` with a string from the [`ChannelError`](Errors#channelerror) enumeration.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\n#### Example\n\n```javascript\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n* [`ChannelError`](Errors#channelerror)\n* [`getCurrentContext`](#getcurrentcontext)\n* [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\n\nIf getting the current context fails, the promise will return an `Error` with a string from the [`ChannelError`](ChannelError) enumeration.\n\n#### Examples\n\nWithout specifying a context type:\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\nSpecifying a context type:\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n* [`ChannelError`](Errors#channelerror)\n* [`broadcast`](#broadcast)\n* [`addContextListener`](#addcontextlistener)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/ChannelError.md",
    "content": "---\nsidebar_label: ChannelError\ntitle: ChannelError\nhide_title: true\noriginal_id: ChannelError\n---\n# `ChannelError`\n\n```typescript\nenum ChannelError {\n  NoChannelFound = \"NoChannelFound\",\n  AccessDenied = \"AccessDenied\",\n  CreationFailed = \"CreationFailed\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinChannel`](DesktopAgent#joinchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n#### See also\n\n* [`DesktopAgent.joinChannel`](DesktopAgent#joinchannel)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\n```typescript\ntype Context = object;\n```\n\nThe base object that all contexts should extend.\n\nThe API specification allows this to be any object, but typically this is supposed to be a context data object adhering to the [Context Data Specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`.\n\nThe `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n#### See also\n\n* [`ContextHandler`](ContextHandler)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/ContextHandler.md",
    "content": "---\nsidebar_label: ContextHandler\ntitle: ContextHandler\nhide_title: true\noriginal_id: ContextHandler\n---\n# `ContextHandler`\n\n```typescript\ntype ContextHandler = (context: Context) => void;\n```\n\nDescribes a callback that handles a context event.\n\nUsed when attaching listeners for context broadcasts and raised intents.\n\n#### See also\n* [`Context`](Context)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\nAn FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nIt is expected that the `DesktopAgent` interface is made available via the [`window.fdc3`](Globals#windowfdc3-object) global object, and that the [`fdc3Ready`](Globals#fdc3ready-event) event fires when it is ready to be used.\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(app: TargetApp, context?: Context): Promise<void>;\n\n  // context\n  broadcast(context: Context): void;\n  addContextListener(contextType: string | null, handler: ContextHandler): Listener;\n  /**\n   * @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Listener;\n\n  // intents\n  findIntent(intent: string, context?: Context): Promise<AppIntent>;\n  findIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: TargetApp): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: ContextHandler): Listener;\n\n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel | null>;\n  leaveCurrentChannel() : Promise<void>;\n\n  //implementation info\n  getInfo(): ImplementationMetadata;\n}\n```\n\n## Methods\n\n### `addContextListener`\n\n```ts\naddContextListener(contextType: string | null, handler: ContextHandler): Listener;\n/**\n * @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\naddContextListener(handler: ContextHandler): Listener;\n```\n\nAdds a listener for incoming context broadcast from the Desktop Agent on the current System Channel. If the consumer is only interested in\na context of a particular type, they can use the relevant overload that allows the type to be specified.\n\n#### Examples\n\n```js\n// any context\nconst listener = fdc3.addContextListener(null, context => { ... });\n\n// listener for a specific type\nconst contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });\n```\n\n#### See also\n\n* [`Listener`](Types#listener)\n* [`Context`](Types#context)\n\n### `addIntentListener`\n\n```ts\naddIntentListener(intent: string, handler: ContextHandler): Listener;\n```\n\n Adds a listener for incoming Intents from the Agent.\n\n#### Examples\n\n```js\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n});\n```\n\n#### See also\n\n* [`Listener`](Types#listener)\n* [`Context`](Types#context)\n\n### `broadcast`\n\n```ts\nbroadcast(context: Context): void;\n```\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever `Channel` the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\nDesktopAgent implementations should ensure that context messages broadcast to a channel by an application joined to it should not be delivered back to that same application.\n\n#### Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n#### See also\n\n* [addContextListener](#addcontextlistener)\n\n### `findIntent`\n\n```ts\nfindIntent(intent: string, context?: Context): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context.\n\n_findIntent_ is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to the intent, its metadata and metadata about the apps that are registered to handle it.\nThis can be used to raise the intent against a specific app.\n\nIf the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n\n#### Examples\n\n```js\n// I know 'StartChat' exists as a concept, and want to know more about it ...\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0].name);\n```\n\n#### See also\n\n* [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```ts\nfindIntentsByContext(context: Context): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context.\n_findIntentsByContext_ is effectively granting programmatic access to the Desktop Agent's resolver.\nA promise resolving to all the intents, their metadata and metadata about the apps that registered as handlers is returned, based on the context types the intents have registered.\n\n If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.\n\n#### Example\n\n```js\n// I have a context object, and I want to know what I can do with it, hence, I look for intents...\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [{\n//     intent: { name: \"StartCall\", displayName: \"Call\" },\n//     apps: [{ name: \"Skype\" }]\n// },\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [{ name: \"Skype\" }, { name: \"Symphony\" }, { name: \"Slack\" }]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app\nconst selectedApp = startChat.apps[0];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp.name);\n```\n\n#### See also\n\n* [`ResolveError`](Errors#resolveerror)\n\n### `getCurrentChannel`\n\n```ts\ngetCurrentChannel() : Promise<Channel | null>;\n```\n\nReturns the `Channel` object for the current channel membership.  Returns `null` if the app is not joined to a channel.\n\n#### Examples\n\n```js\n// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `getInfo`\n\n```ts\ngetInfo(): ImplementationMetadata;\n```\n\nRetrieves information about the FDC3 Desktop Agent implementation, such as the implemented version of the FDC3 specification and the name of the implementation provider.\n\nReturns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.  This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes.\n\n#### Example\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\n#### See also\n\n* [`ImplementationMetadata`](Metadata#implementationmetadata)\n\n### `getOrCreateChannel`\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\nReturns a Channel object for the specified channel, creating it (as an _App_ channel) - if it does not exist.\n`Error` with a string from the [`ChannelError`](Errors#channelerror) enumeration if channel could not be created or access was denied.\n\n#### Example\n\n```js\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  const myChannel.addContextListener(null, context => {});\n}\ncatch (err){\n  //app could not register the channel\n}\n\n```\n\n#### See also\n\n*  [`Channel`](Channel)\n\n### `getSystemChannels`\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\nRetrieves a list of the System channels available for the app to join.  This should include the 'global' channel.\n\n#### Example\n\n```js\nconst systemChannels = await fdc3.getSystemChannels();\nconst redChannel = systemChannels.find(c => c.id === 'red');\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `joinChannel`\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\nJoins the app to the specified channel.\nIf an app is joined to a channel, all _fdc3.broadcast_ calls will go to the channel, and all listeners assigned via _fdc3.addContextListener_ will listen on the channel.\nAn app can only be joined to one channel at a time.\nRejects with error if the channel is unavailable or the join request is denied.\n `Error` with a string from the [`ChannelError`](Errors#channelerror) enumeration.\n\n#### Examples\n\n```js\n// get all system channels\nconst channels = await fdc3.getSystemChannels();\n\n// create UI to pick from the system channels\n\n// join the channel on selection\nfdc3.joinChannel(selectedChannel.id);\n\n```\n\n#### See also\n\n* [`getSystemChannels`](DesktopAgent#getsystemchannels)\n\n### `leaveCurrentChannel`\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\nRemoves the app from any channel membership.  Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be in a no-op when the app is not on a channel.\n\n#### Examples\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(null, context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease recieving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(null, channelListener);\n\n```\n\n### `open`\n\n```ts\nopen(app: TargetApp, context?: Context): Promise<void>;\n```\n\nLaunches an app with target information, which can be either be a string like a name, or an [`AppMetadata`](Metadata#appmetadata) object.\n\nThe `open` method differs in use from [`raiseIntent`](DesktopAgent#raiseintent).  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying the App Directory, `open` would be used to an app returned in the search results.\n\n**Note**, if both the intent and target app name are known, it is recommended to instead use [`raiseIntent`](DesktopAgent#raiseintent) with the `app` argument.\n\nIf a [`Context`](Types#context) object is passed in, this object will be provided to the opened application via a contextListener.\nThe Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n\nIf opening errors, it returns an `Error` with a string from the [`OpenError`](Errors#openerror) enumeration.\n\n#### Example\n\n```js\n// no context\nawait fdc3.open('myApp');\n\n// no context, with AppMetadata object as target\nawait fdc3.open({\n  name: 'myApp',\n  title: 'The title for the application myApp.',\n  description: '...'\n});\n\n// with context\nawait fdc3.open('myApp', context);\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`OpenError`](Errors#openerror)\n\n### `raiseIntent`\n\n```ts\nraiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentResolution>;\n```\n\nRaises a specific intent against a target app.\n\nThe desktop agent will resolve the correct app to target based on the provided intent name and context data.\n\nIf multiple matching apps are found, the user may be presented with an app picker.\nAlternatively, the specific app to target can also be provided (if known).\n\nReturns an `IntentResolution` object with a handle to the app that responded to the intent.\n\nIf a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned.\n\n#### Example\n\n```js\n// find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n// use the name of one of the associated apps returned by findIntent as the specific intent target\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0].name);\n\n// or use the metadata of the app to fully describe the target app for the intent\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`TargetApp`](Types#targetapp)\n* [`IntentResolution`](Metadata#intentresolution)\n* [`ResolveError`](Errors#resolveerror)\n\n### `raiseIntentForContext`\n\n```ts\nraiseIntentForContext(context: Context, app?: TargetApp): Promise<IntentResolution>;\n```\n\nFinds and raises an intent against a target app based purely on context data.\n\nThe desktop agent will resolve the correct app to target based on the provided context.\n\nThis is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose the intent and target app.\n\nReturns an `IntentResolution` object with a handle to the app that responded to the selected intent.\n\nIf a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned.\n\n#### Example\n\n```js\nconst intentResolution = await fdc3.raiseIntentForContext(context);\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`TargetApp`](Types#targetapp)\n* [`IntentResolution`](Metadata#intentresolution)\n* [`ResolveError`](Errors#resolveerror)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/DisplayMetadata.md",
    "content": "---\nsidebar_label: DisplayMetadata\ntitle: DisplayMetadata\nhide_title: true\noriginal_id: DisplayMetadata\n---\n# `DisplayMetadata`\n\n```ts\n public interface DisplayMetadata {\n  name?: string;\n  color?: string;\n  glyph?: string;\n}\n```\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n#### See also\n\n* [`Channel`](Channel)\n* [`DesktopAgent.getSystemChannels`](DesktopAgent#getsystemchannels)\n\n## Properties\n\n### `name`\n\n```ts\nname?: string;\n```\n\nThe display name for the channel.\n\n### `color`\n\n```ts\ncolor?: string;\n```\n\nA name, hex, rgba, etc. that should be associated within the channel when displaying it in a UI.\n\n### `glyph`\n\n```ts\nglyph: string;\n```\n\nA URL of an image that can be used to display this channel."
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Errors.md",
    "content": "---\ntitle: Errors\noriginal_id: Errors\n---\n\nSome FDC3 API operations return promises that can result in errors.\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n\n* [`DesktopAgent.open`](DesktopAgent#open)\n\n## `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `ChannelError`\n\n```typescript\nenum ChannelError {\n  NoChannelFound = \"NoChannelFound\",\n  AccessDenied = \"AccessDenied\",\n  CreationFailed = \"CreationFailed\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinChannel`](DesktopAgent#joinchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n#### See also\n\n* [`DesktopAgent.joinChannel`](DesktopAgent#joinchannel)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Globals.md",
    "content": "---\ntitle: Globals\noriginal_id: Globals\n---\n\nSince FDC3 is typically available to the whole web application, desktop agents are expected to make the [`DesktopAgent`](DesktopAgent) interface available at a global level.\n\n## `window.fdc3` Object\n\nThe global `fdc3` object can be used to access FDC3 API operations, if the current desktop agent supports FDC3.\n\n### Example\n\n```ts\n// check if fdc3 is available\nif (window.fdc3) {\n  // raise an intent\n  await window.fdc3.raiseIntent('StartChat', {\n    type: 'fdc3.contact',\n    id: { email: 'johndoe@mail.com' }\n  })\n}\n```\n\n## `fdc3Ready` Event\n\nThe global `window.fdc3` should only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors should provide an `fdc3Ready` event.\n\n### Example\n\n```ts\nfunction fdc3Action() {\n  // Make some fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Action();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Action);\n}\n```\n\n## `fdc3Ready()` Function\n\nIf you are using the `@finos/fdc3` NPM package, it includes a handy wrapper function that will check for the existence of `window.fdc3` and wait on the `fdc3Ready` event for you.\n\nIt returns a promise that will resolve immediately if the `window.fdc3` global is already defined, or reject with an error if the `fdc3Ready` event doesn't fire after a specified timeout period (default: 5 seconds).\n\n### Example\n\n```ts\nimport { fdc3Ready, broadcast } from '@finos/fdc3'\n\nasync function fdc3Action() {\n  try {\n    await fdc3Ready(1000); // wait for (at most) 1 second\n    broadcast({\n      type: 'fdc3.instrument',\n      id: { ticker: 'AAPL' }\n    })\n  } catch (error) {\n    // handle error\n  }\n}\n```\n\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/IntentMetadata.md",
    "content": "---\nsidebar_label: IntentMetadata\ntitle: IntentMetadata\nhide_title: true\noriginal_id: IntentMetadata\n---\n# `IntentMetadata`\n\n```ts\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n\n#### See also\n* [`AppIntent.intent`](AppIntent)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/IntentResolution.md",
    "content": "---\nsidebar_label: IntentResolution\ntitle: IntentResolution\nhide_title: true\noriginal_id: IntentResolution\n---\n# `IntentResolution`\n\n```ts\ninterface IntentResolution {\n  source: string;\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n \n#### Example\n```js\n//resolve a \"Chain\" type intent\nconst intentResolution = await fdc3.raiseIntent(\"intentName\", context);\n```\n\n#### See also\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Listener.md",
    "content": "---\nsidebar_label: Listener\ntitle: Listener\nhide_title: true\noriginal_id: Listener\n---\n# `Listener`\n\n```typescript\ninterface Listener {\n  unsubscribe(): void;\n}\n```\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\n\n## Methods\n\n### `unsubscribe`\n\n```ts\nunsubscribe(): void;\n```\n\nAllows an application to unsubscribe from listening to intents or context broadcasts. \n\n#### See also\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`ContextHandler`](ContextHandler)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Metadata.md",
    "content": "---\ntitle: Metadata\noriginal_id: Metadata\n---\n\nFDC3 API operations return various types of metadata.\n\n## `AppIntent`\n\n```ts\ninterface AppIntent {\n  intent: IntentMetadata;\n  apps: Array<AppMetadata>;\n}\n```\n\nAn interface that represents the binding of an intent to apps, returned as part of intent disocvery.\nFor each intent, it reference the applications that support that intent.\n\n#### See also\n\n* [`AppMetadata`](#appmetadata)\n* [`IntentMetadata`](#intentmetadata)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `AppMetadata`\n\n```ts\ninterface AppMetadata {\n  name: string;\n  appId?: string;\n  version?: string;\n  title?: string;\n  tooltip?: string;\n  description?: string;\n  icons?: Array<string>;\n  images?: Array<string>;\n}\n```\n\nApp metadata is provided by the FDC3 App Directory that the desktop agent connects to.\n\nIt always includes at least a `name` property, which can be used with [`open`](DesktopAgent#open) and [`raiseIntent`](DesktopAgent#raiseintent).\n\nOptionally, extra information from the app directory can be returned, to aid in rendering UI elements, e.g. a context menu.\nThis includes a title, description, tooltip and icon and image URLs.\n\nIn 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.\n\n#### See also\n\n* [`AppIntent.apps`](#appintent)\n\n## `DisplayMetadata`\n\n```ts\n public interface DisplayMetadata {\n  name?: string;\n  color?: string;\n  glyph?: string;\n}\n```\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n#### See also\n\n* [`Channel`](Channel)\n* [`DesktopAgent.getSystemChannels`](DesktopAgent#getsystemchannels)\n\n### Properties\n\n#### `name`\n\n```ts\nname?: string;\n```\n\nThe display name for the channel.\n\n#### `color`\n\n```ts\ncolor?: string;\n```\n\nA name, hex, rgba, etc. that should be associated within the channel when displaying it in a UI.\n\n#### `glyph`\n\n```ts\nglyph: string;\n```\n\nA URL of an image that can be used to display this channel.\n\n## `ImplementationMetadata`\n\n```typescript\npublic interface ImplementationMetadata {\n  fdc3Version: string;\n  provider: string;\n  providerVersion?: string;\n}\n```\n\nMetadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification and the name of the provider of the implementation.\n\n#### See also\n\n* [`DesktopAgent.getInfo`](DesktopAgent#getinfo)\n\n## `IntentMetadata`\n\n```ts\ninterface IntentMetadata {\n  name: string;\n  displayName: string;\n}\n```\n\nThe Interface used to describe an Intent within the platform.\n\n#### See also\n\n* [`AppIntent.intent`](#appintent)\n\n## `IntentResolution`\n\n```ts\ninterface IntentResolution {\n  source: TargetApp;\n  /**\n  * @deprecated not assignable from intent listeners\n  */\n  data?: object;\n  version: string;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n\n#### Example\n\n```js\n// resolve a \"Chain\" type intent\nconst intentResolution = await fdc3.raiseIntent(\"intentName\", context);\n```\n\n#### See also\n\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`TargetApp`](Types#targetapp)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/OpenError.md",
    "content": "---\nsidebar_label: OpenError\ntitle: OpenError\nhide_title: true\noriginal_id: OpenError\n---\n# `OpenError`\n\n```typescript\nenum OpenError {\n  AppNotFound = \"AppNotFound\",\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n  AppTimeout = \"AppTimeout\",\n  ResolverUnavailable = \"ResolverUnavailable\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n* [`DesktopAgent.open`](DesktopAgent#open)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/ResolveError.md",
    "content": "---\nsidebar_label: ResolveError\ntitle: ResolveError\nhide_title: true\noriginal_id: ResolveError\n---\n# `ResolveError`\n\n```typescript\nenum ResolveError {\n  NoAppsFound = \"NoAppsFound\",\n  ResolverUnavailable = \"ResolverUnavailable\",\n  ResolverTimeout = \"ResolverTimeout\"\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent) or [`findIntentsByContext`](DesktopAgent#findintentsbycontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/ref/Types.md",
    "content": "---\ntitle: Types\noriginal_id: Types\n---\n\nFDC3 API operations make use of several type declarations.\n\n## `Context`\n\n```typescript\ninterface Context {\n  id?: { [key: string]: string };\n  name?: string;\n  type: string;\n}\n```\n\nThe base interface that all contexts should extend: a context data object adhering to the [Context Data Specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n#### See also\n\n* [`ContextHandler`](Types#contexthandler)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `ContextHandler`\n\n```typescript\ntype ContextHandler = (context: Context) => void;\n```\n\nDescribes a callback that handles a context event.\n\nUsed when attaching listeners for context broadcasts and raised intents.\n\n#### See also\n\n* [`Context`](#context)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `Listener`\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\n\n```typescript\ninterface Listener {\n  unsubscribe(): void;\n}\n```\n\n#### `unsubscribe`\n\n```ts\nunsubscribe(): void;\n```\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n#### See also\n\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`ContextHandler`](Types#contexthandler)\n\n## `TargetApp`\n\n```typescript\ntype TargetApp = string | AppMetadata;\n```\n\nOperations that target apps (like `open` or `raiseIntent`) can identify an app just by by its name,\nor pass full app metadata, giving the desktop agent more information about the targeted app.\n\n#### See also\n\n* [`AppMetadata`](Metadata#appmetadata)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`IntentResolution`](Metadata#intentresolution)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/api/spec.md",
    "content": "---\nsidebar_label: API Specification\ntitle: API Specification 1.2\noriginal_id: spec\n---\n\n## Components\n### Desktop Agent\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- Finsemble\n- Glue42\n- OpenFin\n- Refinitiv Eikon\n\nDesktop Agents expose an FDC3 standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n#### Desktop Agent Implementation\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A typical implemention would provide instantiable classes for the following interfaces:\n\n- `DesktopAgent`\n- `Channel`\n- `Listener`\n\nOther interfaces defined in the spec are not critical to define as concrete types.  Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.  These interfaces include:\n\n- `Context`\n- `AppIntent`\n- `IntentResolution`\n- `AppMetadata`\n- `IntentMetadata`\n- `DisplayMetadata`\n\n\n#### API Access\nThe FDC3 API can be made available to an application through a number of different methods.  In the case of web applications, a Desktop Agent SHOULD provide the FDC3 API via a global accessible as _window.fdc3_. Implementors MAY additionally make the API available through modules, imports, or other means.\n\nThe global `window.fdc3` must only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors SHOULD provide a global `fdc3Ready` event. Here is code demonstrating the use of the FDC3 API and the ready event:\n\n```js\nfunction fdc3Stuff() {\n  // Make some fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Stuff();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Stuff);\n}\n```\n\n#### Standards vs. Implementation\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n#### Inter-Agent Communication\nA goal of FDC3 standards is that applications running in different Desktop Agent contexts on the same desktop would be able to interoperate.  And that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\nDesktop Agent interop is supported by common standards for APIs for App discovery and launching.  So, an App in one Desktop Agent context would not need to know a different syntax to call an App in another Desktop Agent context.\n\nThe actual connection protocol between Desktop Agents is not currently in scope for FDC3 standards.  Given that there are a relatively small number of Desktop Agents, and that any given desktop will have a finite and relatively static number of Desktop Agents installed at any given time, the connectivity between different Agents can be adequetly handled for the time being on a case-by-case basis.\n\n### Application\nAn application is any endpoint on the desktop that is:\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of End Points include:\n- Native Applications\n- PWA/Web Applications\n- Headless “services” running on the desktop\n\n## Functional Use Cases\n### Open an Application by Name\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Raising Intents\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that Intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).  Currently, this is the primary focus in FDC3.\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client. Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n#### Intents and Context\nWhen raising an Intent a specific context may be provided. The type of the provided context may determine which applications can resolve the Intent.\n\nA 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.\n\n#### Intent Resolution\nRaising an Intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n##### Resolve\n- Intent was resolved unambiguously and the receiving app was launched successfully.\n- Intent was ambiguous, a resolution was chosen by the end user, and the chosen application was launched successfully.\n\n##### Reject\n- No app matching the intent and context (if specified) was found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n##### Resolution Object\n\n> **Deprecation notice**\n>\n> It is not currently possible to provide a value for the `data` property described below,\nas intent listeners don't currently offer a way to return values.\n>\n> Future versions of FDC3 plan to remove the optional `data` property from the intent resolution object,\nand include a more robust mechanism for intents that need to return data back to the caller.\n\nIf the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format:\n\n```js\n{\n    source: String;\n    data?: Object;\n    version: String;\n}\n```\n- *source* = identifier for the Application resolving the intent (null if the intent could not be resolved)\n- *data* = return data structure - if one is provided for the given intent\n- *version* = the version number of the Intents schema being used\n\n\nFor example, to raise a specific Intent:\n\n```js\ntry {\n    const result = await fdc3.raiseIntent('StageOrder');\n}\ncatch (er){\n    console.log(er.message);\n}\n```\n\nor to raise an Intent for a specific context:\n```js\ntry {\n    const result = await fdc3.raiseIntentForContext(context);\n    if (result.data) {\n        const orderId = result.data.id;\n    }\n}\ncatch (er){\n    console.log(er.message);\n}\n```\n\n##### Upgrading to a Remote API Connection\nThere are a wide range of workflows where decoupled intents and/or context passing do not provide rich enough interactivity and applications are better off exposing proprietary APIs.  In these cases, an App can use the *source* property on the resolution of an intent to connect directly to another App and from there, call remote APIs using the methods available in the Desktop Agent context for the App.  For example:\n\n```js\nconst chart = await fdc3.raiseIntent('ViewChart');\n// construct a vendor wrapper for the App\nconst chartApp = fin.Application.wrap(chart.source);\n// do some vendor-specific stuff\n```\n![Upgrading Connection to Remote API](/assets/api-3.png)\n\n### Register an Intent\nApplications 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.\n\n#### Compliance with Intent Standards\nIntents 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.\n\nIt is expected that App Directories will also curate listed apps and ensure that they are complying with declared intents.\n\nLike FDC3 Context Data, the Intent schemas need to be versioned.  Desktop Agents will be responsible to declare which version of the Intent schema they are using.   Applications may also assert a specific version requirement when raising an Intent.  Version negotation may be supported by a given Desktop Agent.\n\n### Send/broadcast Context\nOn the financial desktop, applications often want to broadcast context to any number of applications.  Context sharing needs to support concepts of different groupings of applications as well as data privacy concerns.  Each Desktop Agent will have its own rules for supporting these features. However, a Desktop Agent should ensure that context messages broadcast to a channel by an application joined to it should not be delivered back to that same application.\n\n### Retrieve Metadata about the Desktop Agent implementation\nFrom version 1.2 of the FDC3 specification, it is possible to retrieve information about the  version of the FDC3 specification supported by a Desktop Agent implementation and the name of the implementation provider. This metadata can be used to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.:\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), '1.2')) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent('ViewChart', context);\n}\n```\n\n## Resolvers\nIntents functionality is dependent on resolver functionality to map the intent to a specific App.  This will often require end-user input.  Resolution can either be performed by the Desktop Agent (raising UI to pick the desired App for the intent) or by the app launching the intent - in which case the calling App will handle the resolution itself (using the findIntents API below) and then invoke an explicit Intent object.\n\n## Context Channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\nThere are two types of channels, which are functionally identical, but have different visibility and discoverability semantics.\n\n1. The 'system' channels, which have a well understood identity.\n\n    > **Deprecation notice:** Earlier versions of FDC3 include the concept of a 'global' system channel\n    for backwards compatibility with FDC3 1.0. In future, there won't be a 'global' channel\n    (see [below](#the-global-channel) for more detail).\n\n2. The 'app' channels, which have a transient identity and need to be revealed\n\n\n### Joining Channels\nApps can join channels.  An app can only be joined to one channel at a time.  When an app joins a channel it will automatically recieve the current context for that channel.\n\nWhen an app is joined to a channel, calls to `fdc3.broadcast` and listeners added through `fdc3.addContextListener` will be routed to that channel. If an app is not joined to a channel `fdc3.broadcast` will be a no-op and handler functions added with `fdc3.addContextListener` will not receive any broadcasts. However, apps can still choose to listen and broadcast to specific channels via the methods on the `Channel` class.\n\nIt is possible that a call to join a channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app.  Always, there SHOULD be a clear UX indicator of what channel an app is joined to.\n\n### The 'global' Channel\n\n> **Deprecation notice**\n>\n> The global channel, which exists only for backward compatibility with FDC3 1.0,\nwill be removed in a future version of the FDC3 API Specification.\n>\n> Instead of relying on being joined to a 'default' channel by the desktop agent on startup,\nan app or system channel should be joined explicitly through the relevant APIs,\nor through a channel selection UI.\n\nThe 'system' channels include a 'global' channel which serves as the backwards compatible layer with the 'send/broadcast context' behavior in FDC3 1.0.  A desktop agent MAY choose to make membership in the 'global' channel the default state for apps on start up.\n\nThe 'global' channel should be returned as part of the response from the `fdc3.getSystemChannels` call.  Desktop Agents may want to filter out the 'global' option in their UI for system channel pickers.\n\n\n### Examples\n\nAn app queries the current context of the `red` channel.\n\n```js\nconst redChannel = await fdc3.getOrCreateChannel('red');\nconst context = await redChannel.getCurrentContext('fdc3.instrument');\n```\n\nAn app can still explicitly receive context events on any channel, regardless of the channel it is currently joined to.\n\n```js\n// check for current fdc3 channel\nlet joinedChannel = await fdc3.getCurrentChannel()\n//current channel is null, as the app is not currently joined to a channel\n\nconst redChannel = await fdc3.getSystemChannels.filter(c => c.id === 'red')\nconst context = await redChannel.getCurrentContext('fdc3.instrument')\n// context is instrument AAPL on the global channel\n\nfdc3.joinChannel('blue')\njoinedChannel = await fdc3.getCurrentChannel()\n//current channel is now the 'blue' channel\n\n```\n\n### Direct Listening and Broadcast on Channels\nWhile joining channels automates a lot of the channel behavior for an app, it has the limitation in that an app can belong to only one channel at a time.  Listening and Broadcasting to channels using the _Channel.addBroadcastListener_ and the _Channel.broadcast_ APIs provides an app with fine-grained controls for specific channels.  This is especially useful for working with dynamic _App Channels_.\n\n### Examples\nTo find a system channel, one calls\n\n```js\n// returns an array of channels\nconst allChannels = await fdc3.getSystemChannels();\nconst redChannel = allChannels.find(c => c.id === 'red');\n```\n#### Joining channels\n\nTo join a channel. one calls\n\n```js\nfdc3.joinChannel(redChannel.id);\n```\n\nCalling _fdc3.broadcast_ will now route context to the joined channel.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\n#### App Channels\n\nApp channels are topics dynamically created by applications connected via FDC3. For example, an app may create a channel to broadcast to others data or status specific to that app.\n\nTo get (or create) a channel reference, then interact with it\n\n```js\nconst appChannel = await fdc3.getOrCreateChannel('my_custom_channel');\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nappChannel.addContextListener(null, context => {...});\n// broadcast to the channel\nappChannel.broadcast(context);\n\n```\n\n## APIs\nThe APIs are defined in TypeScript in [src], with documentation generated in the [docs] folder.\n\n[src]: https://github.com/finos/FDC3/tree/main/src/api\n[docs]: https://github.com/finos/FDC3/tree/main/docs/api\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/app-directory/discovery.md",
    "content": "---\nsidebar_label: App Directory Discovery\ntitle: App Directory Discovery\nhide_title: true\noriginal_id: discovery\n---\n\n# App Directory Discovery\n\n## Simple Definition\n\nThe App Directory (AppD) is a service that provides a financial application definition that includes a trusted identifier(s) and associated metadata. The information registered as part of an application definition supports discovery, launch configuration, intents and context data supporting the use and interoperability of financial applications.\n\n## Topology\n\nAppD services shall support a distributed or detached model to managing application data servicing, where there are (N) AppD services on a network providing information related to a subset of namespace \"zones\" that align with the financial application identifiers. This approach encourages independence, scale and responsive provisioning of application definitions. This is modeled from a subset of the public name service \"Domain Name System\", which has proven reliable and conceptually fit for discovery.\n\n## Service Discovery Approach\n\nIn order to support the discovery of application data stored in a given directory, name space concepts are introduced to both identify the realm of application definitions and AppD service locations that host data. In simple terms, there has to be a way of discovering the location of the AppD service itself and the associated application definitions that are available from that service.\n\n### Application Identifier\n\n- Application data discovery through nested namespace approach and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n### Resolving host system\n\n- AppD service host discovery implementations should support the following requirements;\n  1. Discovery of the AppD location using the fully qualified application ID domain name. This would be the fqdn part of the email structure.\n  2. Discovery of the AppD location using the fully qualified application ID domain name to lookup DNS SRV records identifying the host server location and access TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782) )\n  3. Statically defined URI records for use within client applications directly. This is similar to #1 above, but provides explicit protocol, port and url definitions as part of the defintion.\n\n**Examples:**\n\n*AppD service through DNS / SRV records:*\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/appd_srv.png?version=1&modificationDate=1530189735237&cacheVersion=1&api=v2&width=958&height=250)\n\nAppD Service distribution visual:\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/AppDServiceDistribution.png?version=1&modificationDate=1526307911273&cacheVersion=1&api=v2&width=498&height=250)\n\n## Application data discovery\n\nApplication data discovery shall be accessible through a unique application identifier (AppId) representing a single application represented by a nested namespace syntax using dot notation and email address construction (**name@fqdn**) defining the application identifier as the name part and AppD location as the fully qualified domain name part. The entire address should be considered the fully qualified application ID.\n\n**Example:**\n\n```\ngetAppData(\"app@sub.root\")\n\n    Application {\n      \"appId\": \"app@sub.root\",\n      \"name\": \"App Name\",\n      \"manifest\": \"https://sub.root/app_manifest.json\",\n      \"manifestType\": \"vendor_type\",\n      \"version\": \"1\",\n      \"title\": \"A very cool App\",\n      \"tooltip\": \"A very cool app really\",\n      \"description\": \"Yes..this is the coolest app ever..\",\n      \"images\": [\n        {\n          \"url\": \"string\"\n        }\n      ],\n      \"contactEmail\": \"string\",\n      \"supportEmail\": \"string\",\n      \"publisher\": \"string\",\n      \"icons\": [\n        {\n          \"icon\": \"string\"\n        }\n      ],\n      \"customConfig\": [\n        {\n          \"name\": \"string\",\n          \"value\": \"string\"\n        }\n      ],\n      \"intents\": [\n        {\n          \"name\": \"string\",\n          \"displayName\": \"string\",\n          \"contexts\": [\n            \"string\"\n          ],\n          \"customConfig\": {}\n        }\n      ]\n    }\n```\n\n## Service Discovery (Expanded)\n\nThe following represents the three ways AppD service instances should be discovered over a given network. Again, the view is that AppD services are distributed/decoupled based on associated application namespace on a given network. This takes into account the use of the application identifiers described in previous section. A launcher is required to use a URI (e.g. \"https://appd.foo.com/api/appd/apps/app1@appd.foo.com\") to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required. This proposal focuses on the following approaches to achieve this resolution.\n\n### Application ID namespace syntax host resolution\n\nAn application directory URI can be constructed using a fully qualified application ID (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application name \"app1\" with a fully qualified identifier of \"app1@appd.foo.com\" an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" may resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by;\n\n1. URI protocol is defaulted to https, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default https/443, but can be overridden by the launcher\n4. URI url is by default \"/api/**(service)/(version)\" .**  It is recommended that we identify service label as \"**appd**\" with version being optional. Calls that are made without version automatically default to latest \"/api/appd/app1\" vs \"/api/appd/v1/app1\"\n\nThe resulting URI to retrieve application data for \"app1\" would be \"[https://appd.foo.com/api/appd/v1/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v1/apps/app1.appd.foo.com)\"\n\n###  Application identifiers, Shrinking the URI and AppdD defaults\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID \"app1@appd.foo.com\" is represented as \"app1\" within the application directory.  As a result a launcher can use a shortened URI construct \"[https://appd.foo.com/api/appd/v1/apps/app1](https://appd.foo.com/api/appd/v1/apps/app1)\" to resolve the application data vs \"https://appd.foo.com/api/appd/v1/apps/app1@appd.foo.com\".\n\n### DNS/SRV Records\n\nAnother approach to support AppD service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an AppD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *service*: the symbolic name of the desired service.  For AppD service, this must be identified as \"**_appd**\"\n- *proto*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *name*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *TTL*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *class*: standard DNS class field (this is always *IN*).\n- *priority*: the priority of the target host, lower value means more preferred.\n- *weight*: A relative weight for records with the same priority, higher value means more preferred.\n- *port*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *target*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record **must use** the following definitions:\n\n- service = **_appd**\n- proto = **_tcp**\n- name = must map to the domain of the application identifier . Example:  the **name** for application identifier **\"app1.appd.foo.com\"** would be **\"appd.foo.com\"**\n\n**Known domains:**\n\nAlthough SRV records provide the means of resolving the location of an AppD service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that  the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n\n### Static configuration\n\nAs the name implies, a static configuration for the AppD service location is predefined within the launcher following the same domain:URI model mentioned in previous sections.\n\n![img](https://finosfoundation.atlassian.net/wiki/download/thumbnails/129597550/StaticConfig.png?version=1&modificationDate=1526330937517&cacheVersion=1&api=v2&width=800&height=376)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/app-directory/overview.md",
    "content": "---\nsidebar_label: App Directory Overview\ntitle: App Directory Overview\nhide_title: true\noriginal_id: overview\n---\n\n# App Directory Overview\n\nThe FDC3 App Directory provides trusted identity for financial desktop apps. This identity can be used to prevent spoofing and man-in-the-middle attacks when apps communicate with one another and exchange data. The App Directory also enables service discovery. Apps are registered with a declaration of the intents and context data that can be used when interoperating.\n\n## Core features\n\n- Provide verification of identity for an application running on a desktop - whether it is Native, Web, or Hybrid.\n- Resolve human readable names for applications to the location of and instructions for launching\n- Serve as a repository for application metadata supporting discoverability by intent, context, and other workflow driven facets.\n\n## Sections to review\n\n- [Application Directory Discovery](discovery.md) describes how to resolve the location of the Application Directory using an application identifier.\n- [Application Directory Usage](usage.md) provides a simple view on how application directories can be used.  This also includes links to a reference implementation.\n- [Application Directory specification](spec.md) is the interface definition required to support a compatible application directory.\n\nThe keywords \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in BCP 14, [RFC 2119](https://tools.ietf.org/id/draft-faltstrom-uri-11.html#RFC2119) [RFC2119]."
  },
  {
    "path": "website/versioned_docs/version-1.2/app-directory/spec.md",
    "content": "---\nsidebar_label: App Directory Specification\ntitle: App Directory Specification 1.2\noriginal_id: spec\n---\n## API\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/1.2/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/1.2/app-directory.yaml\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v1/apps`         | POST   | Create a new application definition\n `/v1/apps/{appId}` | GET    | Retrieve an application defintion\n `/v1/apps/search`  | GET    | Retrieve a list of applications\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/app-directory/usage.md",
    "content": "---\nsidebar_label: App Directory Usage\ntitle: App Directory Usage\nhide_title: true\noriginal_id: usage\n---\n\n# App Directory Usage\n\nAn application directory (AppD) provides information about an application's\nidentifiers, intents that provide contexts, and location of metadata providing\ninformation specific to the launching and integration of the application.\n\nIn the real world the AppD would support many use cases as defined in the\n[FDC3 Use Cases](../use-cases/overview)\n\nThe following provides some common use cases and benefits.\n\n## Embedded Launcher\nA desktop application has the ability to launch (or initialize) an application\nby retrieving all necessary data via a REST call(s) to an AppD service\nand metadata location. As described in the [AppD Discovery](discovery)\nsection, this call requires an application identifier (app1@host.appd.com),\nwhich can be used to both locate the AppD service and key to retrieve the\nspecific application data. The resulting application data will describe the\napplication and the metadata URI or the actual\nmetadata in JSON format. If the metadata is a URI, the launcher would\nretrieve the metadata file from the URI.\n\n![img](/assets/appd_launcher_embedded.png)\n\n\n## Standalone Launcher\n\nIn more advanced cases, there could be a need to execute different types\nof desktop applications, such as web browser or general native application\n(exe, binary). A common approach to support this pattern would be to\ncreate a standalone launcher application that has the ability to query\napplication data from the AppD and executes the desktop application that\ncan run the required application. This is also convenient if you wanted\nto display all possible applications to launch in a single view.\n\n![img](/assets/appd_launcher_standalone.png)\n\n\n## Aggregated View\n\nThere could be many different AppD service instances in the world providing\napplication data zoned to the provider or enterprise deployment. The\nAppD specification allows for unique instances of the service with no\nrequirement to aggregate data or define a structured hierarchy. With this\nsaid, a launcher might want to construct an aggregated view of applications\nfrom one or more AppD instances. In this case, the launcher would be\nrequired to retrieve multiple application definitions from one or more\nAppD instances providing a consolidated view of all applications required.\nToday there is no intention to create a single registry of known AppD\ninstances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location (FQDN).\n\n![img](/assets/appd_launcher_aggregated.png)\n\n\n## Enhancing controls\n\nThe AppD API specification defines the optional use of an access token to\nidentify the requesting user/launcher and implement authorizations around which AppD actions can be performed.  Actions are considered standard CRUD operations.\nAgain the specification does not define or make mandatory any authorizations\nor roles that a provider or enterprise can define.\n\nWith this said, it is highly recommended that the implementation take advantage\nand utilize an access token to support these controls. In most cases simple\nuse of roles like \"admin\" and \"user\" would be adequate to create separation\nbetween producer and consumer.\n\nAlternatively a more open approach can be defined, where producers of a new\ndefinition are automatically set to \"owner\" of the the definition.\n\nIn more advanced use cases, actual entitlements can be applied to limit\naccess to specific applications and associated actions based on the source\nuser/launcher identity.\n\nIn all examples, it is up to the implementation to define and engineer the solution\nbased on individual requirements. There are too many variations in approach\nand technology to define a single specification.\n\n\n\n## Reference Implementation\n\n### AppD POC\nPlease view readme on the [AppD POC GitHub](https://github.com/FDC3/appd-poc) .\n\n\n### Launcher\n\nTBD"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/overview.md",
    "content": "---\nsidebar_label: Context Data Overview\ntitle: Context Data Overview\nhide_title: true\noriginal_id: overview\n---\n\n# Context Data Overview\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to one another without any prior knowledge.  \n\nFDC3 Context Data defines a standard for passing common identifiers and data between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [Intents](../intents/overview) and when broadcasting context to other applications.\n\n## Context Object\n\nContext can be summarised as:\n* Having a unique _type_ identifier, used for routing.\n* Optionally providing a name.\n* Optionally providing a map of equivalent identifiers.\n* Any other properties or metadata.\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n## Example Context Object\n\nAn instrument could for example be derived as (note that the name is required and the type is fixed):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" : \n    {  \n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n    \"country\": \"US\"\n}\n```\n It is important to note that the context data specification allows extra identifiers and properties to be added as needed for each interop use case. In the example above, `country` could represent extra data in addition to the agreed instrument representation.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Contact.md",
    "content": "---\nsidebar_label: Contact\ntitle: Contact\nhide_title: true\noriginal_id: Contact\n---\n# `Contact`\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Type\n\n`fdc3.contact`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/contact.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.contact'`  |\n| `name`      | string  | No       | `'Jane Doe'`      |\n| `id.email`  | string  | No       | `'jane@mail.com'` |\n| `id.FDS_ID` | string  | No       | `'ABC123-E'`      |\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane.doe@mail.com'\n    }\n}\n\nfdc3.broadcast(contact)\n```\n\n## See Also\n\nOther Types\n- [ContactList](ContactList)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [ViewContact](../../intents/ref/ViewContact)\n\nFINOS Financial Objects\n- [Contact](https://fo.finos.org/docs/objects/contact)"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/ContactList.md",
    "content": "---\nsidebar_label: ContactList\ntitle: ContactList\nhide_title: true\noriginal_id: ContactList\n---\n# `ContactList`\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nNotes:\n\n- The contact list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.contactList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/contactList.schema.json\n\n## Details\n\n| Property    | Type      | Required | Example Value          |\n|-------------|-----------|----------|------------------------|\n| `type`      | string    | Yes      | `'fdc3.contactList'`   |\n| `id`        | object    | No       | `{ customId: '5576' }` |\n| `name`      | string    | No       | `'My address book'`    |\n| `contacts`  | Contact[] | Yes      | `[contact1, contact2]` |\n\n## Example\n\n```js\nconst contacts = {\n    type: 'fdc3.contactList',\n    contacts: [\n        {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john.doe@mail.com'\n            }\n        },\n    ]\n}\n\n\nfdc3.raiseIntent('StartChat', contacts)\n```\n\n## See Also\n\nOther Types\n- [Contact](Contact)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n\nFINOS Financial Objects\n- [ContactList](https://fo.finos.org/docs/objects/contactlist)"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not \nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/context.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema. \nThe FDC3 [API](../../api/overview) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/overview) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardised FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. \nFor non-standard types, e.g. those defined and used by a particular organisation, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications\nidentify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\n## See Also\n\nFDC3 Specifications\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Country.md",
    "content": "---\nsidebar_label: Country\ntitle: Country\nhide_title: true\noriginal_id: Country\n---\n# `Country`\n\nA country entity.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement\nis for at least one standardised identifier to be provided.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardised and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n\n## Type\n\n`fdc3.country`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/country.schema.json\n\n## Details\n\n| Property         | Type    | Required | Example Value        |\n|------------------|---------|----------|----------------------|\n| `type`           | string  | Yes      | `'fdc3.country'`     |\n| `name`           | string  | No       | `'Sweden'`           |\n| `id.ISOALPHA2`   | string  | No       | `'SE'`               |\n| `id.ISOALPHA3`   | string  | No       | `'SWE'`              |\n\n## Example\n\n```js\nconst country = {\n    type: 'fdc3.country',\n    name: 'Sweden',\n    id: {\n        ISOALPHA3: 'SWE'\n    }\n}\n\nfdc3.broadcast(country)\n```\n\n## See Also\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n- [Country](https://fo.finos.org/docs/objects/country)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Instrument.md",
    "content": "---\nsidebar_label: Instrument\ntitle: Instrument\nhide_title: true\noriginal_id: Instrument\n---\n# `Instrument`\n\nA financial instrument from any asset class.\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match.\n\nNotes:\n\n- Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified.\nIn general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\n- It is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement\nis for at least one instrument identifier to be provided.\n\n- Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant for stock tickers specifically,\nif the identifier you want to share is not a stock ticker, or one of the other standardised ones, rather define \na property that makes it clear what value it is. This makes it easier for target applications.\n\n## Type\n\n`fdc3.instrument`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/instrument.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value       |\n|-------------|---------|----------|---------------------|\n| `type`      | string  | Yes      | `'fdc3.instrument'` |\n| `name`      | string  | No       | `'Microsoft'`       |\n| `id.ticker` | string  | No       | `'MSFT'`            |\n| `id.BBG`    | string  | No       | `'MSFT:US'`         |\n| `id.CUSIP`  | string  | No       | `'594918104'`       |\n| `id.FDS_ID` | string  | No       | `'P8R3C2-R'`        |\n| `id.FIGI`   | string  | No       | `'BBG000BPH459'`    |\n| `id.ISIN`   | string  | No       | `'US5949181045'`    |\n| `id.PERMID` | string  | No       | `'4295907168'`      |\n| `id.RIC`    | string  | No       | `'MSFT.OQ'`         |\n| `id.SEDOL`  | string  | No       | `'2588173'`         |\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Microsoft',\n    id: {\n        ticker: 'MSFT',\n        RIC: 'MSFT.OQ',\n        ISIN: 'US5949181045'\n    }\n}\n\nfdc3.joinChannel('global')\nfdc3.broadcast(instrument)\n```\n\n## See Also\n\nOther Types\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n- [Instrument](https://fo.finos.org/docs/objects/instrument)"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/InstrumentList.md",
    "content": "---\nsidebar_label: InstrumentList\ntitle: InstrumentList\nhide_title: true\noriginal_id: InstrumentList\n---\n# `InstrumentList`\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist).\n\nWhen holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type, though.\n\nNotes:\n\n- The instrument list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.instrumentList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/instrumentList.schema.json\n\n## Details\n\n| Property      | Type         | Required | Example Value                  |\n|---------------|--------------|----------|--------------------------------|\n| `type`        | string       | Yes      | `'fdc3.instrumentList'`        |\n| `name`        | string       | No       | `'Interesting instruments...'` |\n| `id`          | object       | No       | `{ customId: '5464' }`         |\n| `instruments` | Instrument[] | Yes      | `[instrument1, instrument2]`   |\n\n## Example\n\n```js\nconst instruments = {\n    type: 'fdc3.instrumentList',\n    instruments: [\n        {\n            type: 'fdc3.instrument',\n            id: {\n                ticker: 'AAPL'\n            }\n        },\n        {\n            type: 'fdc3.instrument',\n            id: {\n                ticker: 'MSFT'\n            }\n        },\n    ]\n}\n\nfdc3.joinChannel('global')\nfdc3.broadcast(instruments)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n- [InstrumentList](https://fo.finos.org/docs/objects/instrumentlist)"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Organization.md",
    "content": "---\nsidebar_label: Organization\ntitle: Organization\nhide_title: true\noriginal_id: Organization\n---\n# `Organization`\n\nAn entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement\nis for at least one specified identifier to be provided.\n\n## Type\n\n`fdc3.organization`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/organization.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value             |\n|-------------|---------|----------|---------------------------|\n| `type`      | string  | Yes      | `'fdc3.organization'`     |\n| `name`      | string  | No       | `'Cargill, Incorporated'` |\n| `id.LEI`    | string  | No       | `'QXZYQNMR4JZ5RIRN4T31'`  |\n| `id.PERMID` | string  | No       | `'4296555324'`            |\n| `id.FDS_ID` | string  | No       | `'00161G-E'`              |\n\n## Example\n\n```js\nconst organization = {\n    type: 'fdc3.organization',\n    name: 'Cargill, Incorporated',\n    id: {\n        LEI: 'QXZYQNMR4JZ5RIRN4T31',\n        FDS_ID: '00161G-E'\n    }\n}\n\nfdc3.broadcast(organization)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n- [Organization](https://fo.finos.org/docs/objects/organization)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Portfolio.md",
    "content": "---\nsidebar_label: Portfolio\ntitle: Portfolio\nhide_title: true\noriginal_id: Portfolio\n---\n# `Portfolio`\n\nA financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this\nwith e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe [Portfolio](Portfolio) type consists of an array of [Position](Position) types, each of which\nrefers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the portfolio can be added, the schema just \nspecifies the minimum contract.\n\n- The portfolio schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.portfolio`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/portfolio.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.portfolio'`        |\n| `id`         | object     | No       | `{ portfolioId: '7381' }` |\n| `name`       | string     | No       | `'My share portfolio'`    |\n| `positions`  | Position[] | Yes      | `[position1, position2]`  |\n\n## Example\n\n```js\nconst portfolio = {\n    type: 'fdc3.portfolio',\n    positions: [\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument',\n                id: {\n                    ticker: 'AAPL'\n                }\n            },\n            holding: 2000000\n        },\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument',\n                id: {\n                    ticker: 'MSFT'\n                }\n            },\n            holding: 1500000\n        },\n        {\n            type: 'fdc3.position',\n            instrument: {\n                type: 'fdc3.instrument',\n                id: {\n                    ticker: 'IBM'\n                }\n            },\n            holding: 3000000\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewAnalysis', portfolio)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/ref/Position.md",
    "content": "---\nsidebar_label: Position\ntitle: Position\nhide_title: true\noriginal_id: Position\n---\n# `Position`\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good\nexample of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents\nmultiple holdings in a combination of instruments.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the position can be added, the schema just \nspecifies the minimum contract.\n\n- The position schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.position`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/1.2/position.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value                      |\n|--------------|------------|----------|------------------------------------|\n| `type`       | string     | Yes      | `'fdc3.position'`                  |\n| `id`         | object     | No       | `{ positionId: '6475' }`           |\n| `name`       | string     | No       | `'My Apple shares'`                |\n| `holding`    | number     | Yes      | `2000000`                          |\n| `instrument` | Instrument | Yes      | `{ type: 'fdc3.instrument', ... }` |\n\n## Example\n\n```js\nconst position = {\n    type: 'fdc3.position',\n    instrument: {\n        type: 'fdc3.instrument',\n        id: {\n            ticker: 'AAPL'\n        }\n    },\n    holding: 2000000\n}\n\nfdc3.raiseIntent('ViewChart', position)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/position)"
  },
  {
    "path": "website/versioned_docs/version-1.2/context/spec.md",
    "content": "---\nsidebar_label: Context Data Specification\ntitle: Context Data Specification 1.2\noriginal_id: spec\n---\n\n## Introduction\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems.\n\nExchanging context is the most basic entry point to desktop interoperability. The barriers to adoption for this interaction must be kept as low as possible.\n\nThere are two main use cases for exchanging context data:\n\n* __Transmitting reference data between applications.__\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n* __Transferring information between applications.__\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there isn't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n## The Context Interface\n\n```ts\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n### Namespacing\n\nAll well-known types at FDC3 level should be prefixed with `fdc3`. For private type definitions, or type definitions issued by other organisations, different namespaces can be used, e.g. `blackrock.fund`, etc.\n\n### Versioning\n\nThe specification recognises that evolving context data definitions over time, and helping applications to deal with changes to types, are very important.\n\nIt may be as simple as adding an optional `$version` property to types, but it could also be a set of guidelines for adding new properties, without removing or changing existing ones. For example, web technologies like REST or GraphQL do not take a particular opinion about versioning.\n\n### Identifiers\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n## Standard Context Types\n\nThe following are standard FDC3 context types.\n __Note:__ The specification for these types are shared with the [FINOS Financial Objects](https://fo.finos.org) definitions, JSON schemas are hosted with FDC3.\n\n- __fdc3.contact__\n    - A person contact that can be engaged with through email, calling, messaging, CMS, etc.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/contact)\n    - [schema](pathname:///schemas/1.2/contact.schema.json)\n- __fd3.contactList__\n    - A collection of contacts.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/contactlist)\n    - [schema](pathname:///schemas/1.2/contactList.schema.json)\n- __fdc3.country__\n    - A standard country entity.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/country)\n    - [schema](pathname:///schemas/1.2/country.schema.json)\n- __fdc3.instrument__\n    - A financial instrument from any asset class.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/instrument)\n    - [schema](pathname:///schemas/1.2/instrument.schema.json)\n- __fdc3.instrumentList__\n    - A collection of instruments.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/instrumentList)\n    - [schema](pathname:///schemas/1.2/instrumentList.schema.json)\n- __fdd3.organization__\n    - A standard organization entity.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/organization)\n    - [schema](pathname:///schemas/1.2/organization.schema.json)\n- __fdc3.portfolio__\n    - A collection of positions.\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/portfolio)\n    - [schema](pathname:///schemas/1.2/portfolio.schema.json)\n- __fdc3.position__\n    - [Financial Objects Specification](https://fo.finos.org/docs/objects/position)\n    - [schema](pathname:///schemas/1.2/position.schema.json)\n\n__Note:__ The below examples show how the base context data interface can be used to define specific context data objects. It is not the purpose of the specification at this stage to define standard representations for objects. It establishes the framework in which such definitions could be created.\n\n### Examples\n\n#### Contact\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### ContactList\n```json\n{\n    \"type\": \"fdc3.contactList\",\n    \"name\": \"client list\",\n    \"contacts\":[\n        {\n            \"type\":\"fdc3.contact\",\n            \"name\":\"joe\",\n            \"id\":{\n                \"email\": \"joe@company1.com\",\n            }\n        },\n        {\n            \"type\":\"fdc3.contact\",\n            \"name\":\"jane\",\n            \"id\":{\n                \"email\": \"jane@company2.com\",\n            }\n        }\n    ]\n}\n```\n\n#### Country\n```json\n{\n    \"type\":\"fdc3.country\",\n    \"name\":\"the USA\",\n    \"id\":{\n        \"ISOALPHA2\":\"US\",\n        \"ISOALPHA3\":\"USA\"\n    }\n}\n```\n\n#### Instrument\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### InstrumentList\n```json\n{\n    \"type\" : \"fdc3.instrumentList\",\n    \"name\" : \"my portfolio\",\n    \"instruments\" : [\n        {\n            \"type\" : \"fdc3.instrument\",\n            \"name\" : \"Apple\",\n            \"id\": {\n               \"ticker\" : \"aapl\"\n            }\n        },\n        {\n            \"type\" : \"fdc3.instrument\",\n            \"name\" : \"International Business Machines\",\n            \"id\": {\n               \"ticker\" : \"ibm\"\n            }\n        }\n    ]\n}\n```\n\n#### Organization\n```json\n{\n    \"type\": \"fdc3.organization\",\n    \"name\": \"IBM\",\n    \"id\": {\n        \"PERMID\" : \"4295904307\",\n        \"LEI\" : \"VGRQXHF3J8VDLUA7XE92\"\n    }\n}\n```\n\n#### Portfolio\n```json\n{\n    \"type\":\"fdc3.portfolio\"\n    \"name\":\"my portfolio\",\n    \"positions\":[\n        {\n            \"type\": \"fdc3.position\",\n            \"instrument\": {\n                \"type\" : \"fdc3.instrument\",\n                \"name\" : \"Apple\",\n                \"id\" :\n                {\n                    \"ISIN\" : \"US0378331005\"\n                }\n            },\n            \"holding\": 500\n        },\n         {\n            \"type\": \"fdc3.position\",\n            \"instrument\": {\n                \"type\" : \"fdc3.instrument\",\n                \"name\" : \"IBM\",\n                \"id\" :\n                {\n                    \"ISIN\" : \"US4592001014\"\n                }\n            },\n            \"holding\": 1000\n        }\n    ]\n}\n```\n\n\n#### Position\n```json\n{\n    \"type\": \"fdc3.position\",\n    \"instrument\": {\n        \"type\" : \"fdc3.instrument\",\n        \"name\" : \"Apple\",\n        \"id\" :\n        {\n            \"ISIN\" : \"US0378331005\"\n        }\n    },\n    \"holding\": 500\n}\n```\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/fdc3-charter.md",
    "content": "---\ntitle: FDC3 Charter\noriginal_id: fdc3-charter\n---\n\n## Summary\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\n## Scope\nFinancial desktop applications include any app used in common financial workflows:\n\n* Traditional native applications implemented in C++, .NET, Java, Python, etc.\n* Hybrid web/native applications - stand alone native apps embedding Chromium (e.g. Electron, CEF, NW.js)\n* Desktop web applications - platform based apps extending Chromium (e.g. OpenFin, Finsemble, Glue42)\n* Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, etc.\n* PWAs & Web applications running in a commercial browser\n\nThis standards group is focused specifically on the desktop.  Activities of the desktop interoperability group do not include:\n\n* Defining financial objects - where existing standards are well established\n* Interoperability between mobile apps\n* Interoperability via REST or other client to server communication\n\nNote: While these areas are out of scope, compatibility with Mobile and/or REST are still valid points of consideration for the FDC3.\n\n## Success Criteria\n* Commitment from major banks and application vendors to support the standards set out by the FDC3\n* Workflow integrations in the wild leveraging the standards\n\n## Deliverables\n* Define criteria and mechanics for secure communication between apps\n* Define key functions that require specific standards for interoperability\n* Create an agreed taxonomy for common app “intents” within financial desktop workflows\n* Create an agreed taxonomy for common data to be shared across apps within financial desktop workflows\n* Provide reference implementations of all standards\n* Maintain the above standards and reference implementations\n\n### Participation\nTo be successful, the FDC3 is expected to have a critical mass of active participants for its duration. Effective participation in FDC3 means participation in the form of research, authoring, editing, and development activities outside the scope of attending regular meetings.\n\n### Licensing\nThe FDC3 will use Apache 2.0 license or similar for all deliverables.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/fdc3-compliance.md",
    "content": "---\ntitle: FDC3 Compliance\noriginal_id: fdc3-compliance\n---\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>   Imperatives of the type defined in this memo must be used with care\n>   and sparingly.  In particular, they MUST only be used where it is\n>   actually required for interoperation or to limit behavior which has\n>   potential for causing harm (e.g., limiting retransmisssions)  For\n>   example, they must not be used to try to impose a particular method\n>  on implementors where the method is not required for\n>   interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers API, App Directory, Context Data, and Intents working groups, it does not apply to the Use Cases working group.\n\n## Personas\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation of the FDC3 API for applications to use. Implicitly, it connects to one or more App Directories.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.\n\nDepending on persona, implementation compliance with FDC3 will mean different things.\n\n### Platform Provider\nTo meet the requirements of FDC3, a platform provider would need to support the following:\n\n* Connection to 1 or more App Directories meeting the FDC3 App Directory standards\n* Provide an API to all applications running in the context of the platform that meets the FDC3 API standards, including:\n    * Support for FDC3 Context Data and Intents standards\n    * Support for Intent and Context resolution using a resolver UI\n* At least one workflow of one of the use cases marked as Accepted by the Use Cases working group SHOULD be satisfied by the implementation.\n\n### Application Provider\nFor application providers FDC3 compliance requires:\n* If intents are supported by the application, they SHOULD favor supporting applicable FDC3 defined intents over proprietary ones.\n* If FDC3 defined intents are supported, they MUST meet the expected context and behavior defined for the intent.\n* If proprietary intents are handled, those intents SHOULD follow the recommended naming conventions in the specification.\n* If intents are supported, the application SHOULD use the addIntentListener API to set up a handler.\n* If Context Data is supported by the application, they SHOULD favor supporting applicable FDC3 defined Context Data over proprietary ones.\n* If FDC3 defined Context Data is supported, it MUST meet the interface defined for the type of Context Data.\n* If proprietary Context Data properties are handled, they SHOULD follow any recommended naming conventions in the specification.\n* If Context Data is supported, the application SHOULD use the addContextListener API to set up a handler.\n\n## References\nThe following specifications and use case references apply to the above:\n* [API](api/spec)\n* [App Directory](app-directory/spec)\n* [Context Data](context/spec)\n* [Intents](intents/spec)\n* [Use Cases](use-cases/overview)\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/fdc3-intro.md",
    "content": "---\ntitle: Welcome to FDC3\nsidebar_label: Introduction\noriginal_id: fdc3-intro\n---\n\nFDC3 aims to provide an **open standard for interoperability** between applications on the financial desktop.\n\nThis includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, a REST-based app directory standard, and standardized API operations.\n\n## Motivation\n\nFDC3 codifies standard patterns that application developers have been using for cross-application workflows between web and native applications\nin the financial industry.\n\nAccording to the [FDC3 Charter](fdc3-charter):\n> The mission of FDC3 is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\nFor more information, see [Why FDC3](why-fdc3).\n## Specifications\n\nThe standard currently consists of four complementary specifications:\n\n- [API](api/spec)\n- [Intents](intents/spec)\n- [Context Data](context/spec)\n- [App Directory](app-directory/spec)\n\n## Use Cases\n\nFrom its inception, the standards have been informed by real-world [business use cases](use-cases/overview), which you can view on this website,\nand form an important part of FDC3.\n## Who is using FDC3?\n\nFDC3 was launched in October 2017 by [OpenFin](http://www.openfin.co) in collaboration with [major industry participants](/users). It includes representatives from over 40 major banks, buy-side firms, consultancies and financial services platforms.\n\n## How is FDC3 governed?\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services.\n\nFDC3 uses the Apache 2.0 open source license for all deliverables.\n\n## Where should I go next?\n\n- Have a look at the [supported platforms](supported-platforms) or [common use cases](use-cases/overview).\n- Visit FDC3 [on GitHub](https://github.com/finos/FDC3).\n- Download and install our [npm package](https://www.npmjs.com/package/@finos/fdc3).\n- Try out an FDC3-compliant implementation, e.g. this [browser extension](https://github.com/finos/fdc3-desktop-agent).\n- Join us in the [mailing list](mailto:fdc3+subscribe@finos.org) or on [Slack](https://app.slack.com/client/T01E7QRQH97/C01R0P7H5LH).\n- [Participate](https://github.com/finos/FDC3#getting-involved) in the evolution of the standard.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/fdc3-standard.md",
    "content": "---\ntitle: FDC3 1.2\nsidebar_label: FDC3 1.2 Abstract\noriginal_id: fdc3-standard\n---\n\n**Status:** Superceded  \n_**adopted:** 1st Apr 2021_  \n_**released:** 19th Apr 2021_  \n_**superseded:** 22nd August 2022_  \n\n## Abstract\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of four complementary parts:\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain. \n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n\n## Versioning\nThis Standard defines FDC3 Version 1.2. The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md). \n\n## Table of Contents\n- [Compliance information](fdc3-compliance)\n- [Supported Platforms](supported-platforms)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part ](app-directory/spec)\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/overview.md",
    "content": "---\nsidebar_label: Intents Overview\ntitle: Intents Overview\nhide_title: true\noriginal_id: overview\n---\n\n# Intents Overview\n\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to another without any prior knowledge.\n\n\nFDC3 Intents define a standard set of verbs that can be used to put together common cross-application workflows on the financial desktop.\n* Applications register the Intents & [Context Data](../context/overview) combinations they support in the [App Directory](../app-directory/overview)\n* The App Directory supports application discovery by Intents and/or Context Data\n* Intents are not full RPC, apps don’t need to enumerate every function with an intent\n* FDC3 Standard Intents are a limited set, organizations can create their own intents\n\n## Using Intents\nCombined with [Context Data](../context/overview) and [App Directory](../app-directory/overview) standards, Intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n type: \"fdc3.contact\",\n name: \"Jane Doe\",\n id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/StartCall.md",
    "content": "---\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\noriginal_id: StartCall\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n- [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/StartChat.md",
    "content": "---\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\noriginal_id: StartChat\n---\n# `StartChat`\n\nInitiate a chat with a contact or list of contacts.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n- [StartCall](StartCall)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewAnalysis.md",
    "content": "---\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\noriginal_id: ViewAnalysis\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewChart.md",
    "content": "---\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\noriginal_id: ViewChart\n---\n# `ViewChart`\n\nDisplay a chart for the provided instrument(s).\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Portfolio](../../context/ref/Portfolio)\n* [Position](../../context/ref/Position)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n- [ViewQuote](ViewQuote)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewContact.md",
    "content": "---\nsidebar_label: ViewContact\ntitle: ViewContact\nhide_title: true\noriginal_id: ViewContact\n---\n# `ViewContact`\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n\nIntents\n- [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewInstrument.md",
    "content": "---\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\noriginal_id: ViewInstrument\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewNews.md",
    "content": "---\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\noriginal_id: ViewNews\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n* [Country](../../context/ref/Country)\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n\nIntents\n- [ViewAnalysis](ViewAnalysis)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/ref/ViewQuote.md",
    "content": "---\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\noriginal_id: ViewQuote\n---\n# `ViewQuote`\n\nDisplay pricing for an instrumen.\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-1.2/intents/spec.md",
    "content": "---\nsidebar_label: Intents Specification\ntitle: Intents Specification 1.2\noriginal_id: spec\n---\n\n## Introduction\n\nFDC3 [Intents](overview) define a standard set of nouns and verbs that can be used to put together common cross-application workflows on the financial desktop.\n\n### Naming Syntax\n* Intent names should be free of non-alphanumeric characters.\n* ‘.’ will be used to namespace the intent (see below).\n* Intent names should be in UpperCamelCase.\n\n### Characteristics\n\nIntents shoulde be:\n* Recognizable\n    * Generally self-evident what the thing is\n* Repeatable\n    * Many instances across the industry\n* Stateless\n    * Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n* Specific\n    * Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n* Distinct\n    * Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces ###\nAll standard Intent names are reserved. Applications may use their own Intents ad hoc.\nHowever, there is a need for applications to ensure that their Intents avoid collision. The recommended approach here is to use the app name as the noun. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary Intent.\n\n## Initial Set of Standard Intents ##\n\n### StartCall\n  * Expected Context: Contact\n  * Expected behavior: initiate call with contact(s)\n### StartChat\n  * Expected Context: Contact\n  * Expected behavior: initiate chat with contact(s)\n### ViewChart\n  * Expected Context: Instrument\n  * Expected behavior: display a chart for the context\n### ViewContact\n  * Expected Context: Contact\n  * Expected behavior: display details of a contact\n### ViewQuote\n  * Expected Context: Instrument\n  * Expected behavior: display pricing for an instrument\n### ViewNews\n  * Expected Context: Instrument, Contact, Organisation, etc.\n  * Expected behavior: display news for a given context\n### ViewInstrument\n  * Expected Context: Instrument\n  * Expected behavior: display relevant information for a given instrument\n### ViewAnalysis\n  * Expected Context: Instrument, Organization, etc.\n  * Expected behavior: Send context to receiving application for displaying analysis\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/supported-platforms.md",
    "content": "---\ntitle: Supported Platforms\noriginal_id: supported-platforms\n---\n\nAs an open standard, FDC3 can be implemented on any platform and in any language.\n\nAll that is required is a \"desktop agent\" that supports the FDC3 standard, which is responsible for co-ordinating application interactions.\n\n## Web\n\nFor web applications to be FDC3-enabled, they need to run in the context of an agent that makes the FDC3 API available to the application. This desktop agent is also responsible for launching and co-ordinating applications. It could be a browser extension, web app, or full-fledged desktop container framework.\n\n### Installation\n\nFDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can by used by web applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\n<!--DOCUSAURUS_CODE_TABS-->\n<!--npm -->\n\n```sh\nnpm install @finos/fdc3\n```\n<!--yarn-->\n\n```sh\nyarn add @finos/fdc3\n```\n\n<!--pnpm-->\n\n```sh\npnpm install @finos/fdc3\n```\n\n<!--END_DOCUSAURUS_CODE_TABS-->\n\n### Usage\n\n```javascript\n// declare FDC3-compliant data\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL',\n        ISIN: 'US0378331005',\n        FIGI : 'BBG000B9XRY4'\n    }\n}\n\n// invoke an action in another application, with the required data\nconst result = await fdc3.raiseIntent('ViewAnalysis', instrument)\n\n// join the red channel and broadcast data to subscribers\nawait fdc3.joinChannel('red')\nfdc3.broadcast(instrument)\n\n// set up a listener for incoming data\nconst listener = fdc3.addContextListener('fdc3.contact', contact => { })\n```\n\nFor details about the available API operations, see the [API Referennce](api/ref/DesktopAgent).\n\n## Native\n\nThe FDC3 standard does not define wire formats for communication. Hence, for native applications to be FDC3-enabled, they need to make use of a library (e.g. a DLL in .Net or JAR file in Java) that provides them with an implementation of the FDC3 API. FDC3-enabled native applications are therefore specific to particular desktop container frameworks (or other suitable environments) that provide the necessary libraries.\n\nDespite this limitation, implementing support for FDC3 in a native application can allow it to interact with a wide variety of FDC3-enabled web applications.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\noriginal_id: uc-1\n---\n\n## Preconditions\nOn their desktop, this user has:\n- Their firm's internal research & analytics platform containing liquidity tools and internal research. The product is running and the liquidity tool is open\n- An installed chat application - product is running\n- A third party market data terminal with 3 open applications. These applications are all 'linked' through a channel. \n    - A Watchlist\n    - An Order Book\n    - An Overview of pricing and fundamental data\n- A third party Charting Application access via a browser window. This is not open. \n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\noriginal_id: uc-2\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\noriginal_id: uc-3\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\noriginal_id: uc-4\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\noriginal_id: uc-5\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/009-call-transcription-to-crm.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Call Transcription to CRM\"\nsidebar_label: 9. Call Transcription to CRM\nlayout: use_case\noriginal_id: uc-9\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/010-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Real-Time voice trades -> trade ticket population\"\nsidebar_label: 10. Real-Time voice trades -> trade ticket population\nlayout: use_case\noriginal_id: uc-10\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/013-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-13\ntitle: \"Use Case 13: User launches multiple apps from a single container\"\nsidebar_label: 13. User launches multiple apps from a single container\nlayout: use_case\noriginal_id: uc-13\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/015-sales-floor-base-workflow.md",
    "content": "---\nid: uc-15\ntitle: \"Use Case 15: Sales Floor Base Workflow\"\nsidebar_label: 15. Sales Floor Base Workflow\nlayout: use_case\noriginal_id: uc-15\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/016-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-16\ntitle: \"Use Case 16: Quantifying FDC3 Interactions\"\nsidebar_label: 16. Quantifying FDC3 Interactions\nlayout: use_case\noriginal_id: uc-16\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/017-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-17\ntitle: \"Use Case 17: Fine-tuning InterOp with Channels\"\nsidebar_label: 17. Fine-tuning InterOp with Channels\nlayout: use_case\noriginal_id: uc-17\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-1.2/use-cases/overview.md",
    "content": "---\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\noriginal_id: overview\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-1.2/why-fdc3.md",
    "content": "---\nsidebar_label: Why FDC3\ntitle: Why FDC3\noriginal_id: why-fdc3\n---\n\n## Why look for FDC3-enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go. The main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3 enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context)\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc. Every application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3 enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3 enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration, with an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/App-Channel-Tests.md",
    "content": "---\nid: App-Channel-Tests\nsidebar_label: App Channel Tests\ntitle: App Channel Tests\nhide_title: true\n---\n\n# App Channel Tests  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n## Basic Broadcast\n\n| App | Step               | Details                                                                    |\n|-----|--------------------|----------------------------------------------------------------------------|\n| A   | 1.Retrieve `Channel`    |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2.Add Context Listener |Add an _untyped_ context listener to the channel, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(null, handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(null, handler)` |\n| B   | 3.Retrieve `Channel`     | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4.Broadcast          | Broadcast an `fdc3.instrument` Context to the channel with: <br/>`testChannel.broadcast(<fdc3.instrument context>)`|\n| A   | 5.Receive Context    | The handler added in step 2 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- `ACBasicUsage1` Perform above test.\n\n## Current Context\n\n| App | Step               | Details                                                                    |\n|-----|--------------------|----------------------------------------------------------------------------|\n| B   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2.Broadcast          | Broadcast an `fdc3.instrument` to the channel using: <br/> `testChannel.broadcast(<fdc3.instrument context>)`|\n| A   | 3.Retrieve `Channel`   |Retrieve a `Channel` object representing the same 'App' channel B did (`test-channel`)|\n| A   | 4.Retrieve Current Context    | A gets the _current context_ of the user channel. via:  `await testChannel.getCurrentContext()` <br />Ensure that the instrument received by A is identical to that sent by B    |\n\n-  `ACBasicUsage2` Perform above test\n\n## Filtered Context\n\n| App | Step               | Details                                                         |\n|-----|--------------------|-----------------------------------------------------------------|\n| A   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2.Add Context Listener |Add a _typed_ context listener for `fdc3.instrument`, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(\"fdc3.instrument\", handler)`\n| B   | 3.Retrieve `Channel`   |Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4.Broadcast          | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument context>)` <br /> `testChannel.broadcast(<fdc3.contact context>)`|\n| A   | 5.Receive Context    | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received.                                                                   |\n\n-  `ACFilteredContext1`: Perform above test \n-  `ACFilteredContext2`: Perform above test, but add listeners for both `fdc3.instrument` and `fdc3.contact` in step2.  Ensure that both context objects are received. \n-  `ACFilteredContext3`: Perform above test, except creating a _different_ channel in app B. Check that you _don't_ receive anything (as the channels don't match).\n-  `ACFilteredContext4`: Perform above test, except that after creating the channel **A** creates another channel with a further _different_ channel id and adds a further context listener to it.  Ensure that **A** is still able to receive context on the first channel (i.e. it is unaffected by the additional channel) and does NOT receive anything on the second channel.\n-  `ACUnsubscribe`: Perform above test, except that after creating the channel **A** then `unsubscribe()`s the listener it added to the channel. Check that **A** does NOT receive anything.\n\n### App Channel History\n\n| App | Step               | Details                                                 |\n|-----|--------------------|---------------------------------------------------------|\n| A   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2.Retrieve `Channel` |Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 3.Broadcast          |B broadcasts both the instrument context and a contact context, using: <br /> `testChannel.broadcast(<fdc3.instrument context>)` <br /> `testChannel.broadcast(<fdc3.contact context>)` |\n| A   | 4.Add Context Listener| A adds a context listener to the channel *after* B has completed all its broadcasts, via: <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(\"fdc3.instrument\", handler)` <br /> Ensure that A does NOT receive any context via these listeners (past context is only retrieved via a `getCurrentContext()` call on App channels). |\n| A   | 5.Retrieve Current Context    | A is able to retrieve the most recent context of each context type from the `Channel`  via: <br/>`const instrument = await testChannel.getCurrentContext('fdc3.instrument')`<br/>`const instrument = await testChannel.getCurrentContext('fdc3.contact')`<br />Ensure that both contexts retreived by A are identical to those sent by B|\n\n- `ACContextHistoryTyped`: Perform above test.\n- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types.  Ensure that only the last version of each type is received by **A**.\n- `ACContextHistoryLast`: In step 5. **A** retrieves the _untyped_ current context of the channel via `const currentContext = await testChannel.getCurrentContext()`. Ensure that A receives only the very last broadcast context item _of any type_.\n- `ACClearHistorySpecificContext`: Perform the above test, except after step 3 clear context with `await testChannel.clearContext('fdc3.instrument')`. Ensure that in step 5 nothing is received for `const instrument = await testChannel.getCurrentContext('fdc3.instrument')` and context is received successfully for `const contact = await testChannel.getCurrentContext('fdc3.contact')`\n- `ACClearHistoryAllContexts`: Perform the above test, except after step 3 clear context with `await testChannel.clearContext('fdc3.nothing')`. Ensure that in step 5 nothing is received for `const instrument = await testChannel.getCurrentContext('fdc3.instrument')` and for `const contact = await testChannel.getCurrentContext('fdc3.contact')`\n- `ACClearHistoryAllContextsSubscribedToNothing`: Perform the above test, except after step 3 clear context with `await testChannel.clearContext('fdc3.nothing')` and in step 4 call `await testChannel.addContextListener(\"fdc3.nothing\", handler)` instead. Ensure that after clearing context, the handler is called. \n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/Basic-Tests.md",
    "content": "---\nid: Basic-Tests\nsidebar_label: Basic Tests\ntitle: Basic Tests\nhide_title: true\n---\n\n# Basic Tests ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_These are some basic sanity tests implemented in the FDC3 Conformance Framework.  It is expected that Desktop Agent testers will run these first before commencing the much more thorough tests in section 2 onwards._\n\n- `BasicCL1`: You can create a context listener by calling `fdc3.addContextListener('fdc3.contact',<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicCL2`: You can create an **unfiltered** context listener by calling `fdc3.addContextListener(null,<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicIL1`: You can create an intent listener by calling `fdc3.addIntentListener(<intent name>,<handler>)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicGI1`: An application can retrieve an `ImplementationMetadata` object to find out the version of FDC3 it is using and the provider details by calling:\n    - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getInfo()` \n    - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await fdc3.getInfo()` \n- `BasicAC1`: An application can retrieve a named 'App' channel via the `fdc3.getOrCreateChannel(<name>)` function. The `Channel` object returned conforms to the defined interface.\n- `BasicUC1`: An application can query the available user/system channels, which are returned as an array of `Channel` Objects conforming to the defined interface.  The API call is:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getSystemChannels()`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)`await fdc3.getUserChannels()` \n- `BasicJC1`: The application should be able to join one of the user/system channels with the channel's id.  Having done so, the current channel should NOT be null, and be set for the application _to the channel for the id given_.  After you leave the current channel, it should go back to being `null`.\n  - The channel is joined with:\n    - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.joinChannel(<channelId>)` \n    - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.joinUserChannel(<channelId>)` \n  - A `Channel` object representing the current channel is retrieved with:\n    - `fdc3.getCurrentChannel()` to get the current channel.\n  - The channel is left with: \n    - `fdc3.leaveCurrentChannel()`\n- `BasicRI1`: The application should be able to raise an intent by invoking: \n  - `fdc3.raiseIntent(<intent name>)`\n  - A promise should be returned.\n- `BasicRI2`: The application should be able to raise an intent for some item of context by invoking:\n  - `fdc3.raiseIntentForContext(<context>)`\n  - A promise should be returned.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/Intents-Tests.md",
    "content": "---\nid: Intents-Tests\nsidebar_label: Intents Tests\ntitle: Intents Tests\nhide_title: true\n---\n\n# Intents Tests\n\n## Version 1.2 Intents Tests ![1.2](https://img.shields.io/badge/FDC3-1.2-green)\n\n_NB: Intents received a lot of work in 2.0 version of the specification, so by and large the tests for these are now completely different._\n\n### Setup\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                                                                                                                                    |\n|-----|------------------------------------------------------------------------------------------------------------------------------------------------------|\n| A   | A's AppD Record contains: `aTestingIntent` (with context type `testContextX`, `testContextZ`) and `sharedTestingIntent1` (with context type `testContextX`)    |\n| B   | B's AppD Record contains `bTestingIntent` (with context type `testContextY`) and `sharedTestingIntent1` (with context types `testContextX` and `testContextY`) |\n| C   | C's AppD Record contains `cTestingIntent` (with context type `testContextX`)                                                                             |\n\nAlso we assume a fourth app **D** that is going to discover the intents in the other 3.\n\n### Find Intent From AppD\n\n- `IntentAppD`: Calls `fdc3.findIntent(\"aTestingIntent\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.\n- `WrongIntentAppD`: Calls `fdc3.findIntent(\"nonExistentIntent\")`. Rejects with [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `IntentAppDRightContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextX\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.\n- `IntentAppDWrongContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextY\")`.  Rejects with [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `IntentAppDMultiple1`: Calls `fdc3.findIntent(\"sharedTestingIntent1\")`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.\n- `IntentAppDMultiple2`: Calls `fdc3.findIntent(\"sharedTestingIntent1\", \"testContextX\")`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.\n- `IntentAppDMultiple3`: Calls `fdc3.findIntent(\"sharedTestingIntent1\", \"testContextY\")`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **B** app metadata.\n\n### Find Intents By Context\n\n- `SingleContext`: Call `fdc3.findIntentsByContext(\"testContextX\")`.  Should return `aTestingIntent` (app **A**), `sharedTestingIntent1` (**A**, **B**) and `cTestingIntent` (**C**) AND nothing else.\n- `NoContext`: Call `fdc3.findIntentsByContext()`. Rejects with [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n\n\n### Raise Intent\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| D   | 1. Raise          | `fdc3.raiseIntent(\"sharedTestingIntent1\", {testContextY})`<br />starts app B.                       |\n| B   | 2. Gather Context | `fdc.addIntentListener(\"sharedTestingIntent1\")`<br />Receives testContextY, matching that sent by D |\n\n-  `SingleResolve1`: Perform above test\n-  `TargetedResolve1`: Use `fdc3.raiseIntent(\"aTestingIntent\", {testContextX}, <A's App Name>)` to start app A, otherwise, as above\n-  `TargetedResolve2`: Use `fdc3.raiseIntent(\"aTestingIntent\", {testContextX}, {name: \"<A's App Name>\"})` to start app A, otherwise, as above\n-  `TargetedResolve3`: Use `fdc3.raiseIntent(\"aTestingIntent\", {testContextX}, {name: \"<B's App Name>\", appId: \"<B's App ID>\"})` to start app B, otherwise, as above\n-  `FailedResolve1-3` As with `TargetedResolve1-3`, but use `fdc3.raiseIntent(\"aTestingIntent\", {testContextY}, <A's App Name>)` and variations.  You will receive `NoAppsFound` Error\n-  `FailedResolve4` As above, but use `fdc3.raiseIntent(\"aTestingIntent\", {testContextX}, <C's App Name>)`.  You will receive `NoAppsFound` Error\n\n## Current Intents Tests ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_Please note that API calls (and associated test cases) relating to API calls based on the `name` property of an appD record (used to specify a target application) were deprecated in FDC3 2.0 in favour of those based on `AppIdentifier`. Hence, those API calls have become optional and test cases related to them have been removed._\n\n### Setup\n\nWe assume 6 context types in the below tests (and associated AppD records):\n\n- `testContextX`\n- `testContextY`\n- `testContextZ`\n- `nonExistentContext` (context object with a unique type that does NOT appear in any of the apps (metadata or otherwise).\n- `privateChannelDetails`\n- `privateChannelIsPrivateResult`\n\nThese may be used in a test as a context object `{ \"type\": \"<typeName>\" }` or just the base type name.  Where the base type name is used it is surround with \"quotes\". If not wrapped in quotes assume it is an instance of that context type (generally just an object with a `type` field set to the type name - but occasionally with other data).\n\nYou will need to pre-populate the AppDirectory with the following items (some of which will never be started, but must be configured to confirm correct behavior from various API functions):\n\n| App | Usage                                                 | ListensFor `(pattern: intent([context-types…]) (=> result-type)`)                               | On Startup                                                                   |\n|-----|-------------------------------------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|\n| A   | Raise Intent tests without results                    | `aTestingIntent(testContextX,testContextZ)`<br/>`sharedTestingIntent1(testContextX)` | addIntentListener() for given intents                                       |\n| B   | Raise Intent tests with Context results               | `bTestingIntent(testContextY)`<br/>`sharedTestingIntent1(testContextX, testContextY) => testContextY` | addIntentListener() for given intents                                       |\n| C   | Find Intent tests (never started)                     | `cTestingIntent(testContextX) => testContextZ`                                                  | addIntentListener() for given intents                                       |\n| D   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextX) => testContextZ`                                            | addIntentListener() for given intents                                       |\n| E   | Find Intent & Raise Intent with Channel result        | `sharedTestingIntent2(testContextY) => channel`                                                 | addIntentListener() for given intents                                       |\n| F   | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel<testContextZ>` *                                 | addIntentListener() for given intents                                       |\n| G   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextY)`                                                            | addIntentListener() for given intents                                       |\n| H   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                            | - no action                                                                   |\n| I   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                           | addIntentListener(\"MadeUpIntent\", handler)                          |\n| J   | PrivateChannels are private                           | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult`                   | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |\n| K   | PrivateChannel lifecycle events                       | `kTestingIntent(testContextX) => channel<testContextZ>`                                         | addIntentListener() for given intents                                       |\n\nNB:\n\n- There is no way to indicate in the app directory the difference between a private channel and app channel.\n- We assume a final test app `Test` that will discover the Intent support in the others using the API.\n\nFinally, please note that this is a larger set of apps than were required for 1.2 tests. This is due to an increased number of parameters to API calls and AppD records, which multiplies the number of apps required. The apps are all specified here (rather than broken down over multiple issues) to ensure that clashes between test case sets can be worked out here. For example, adding one additional app that works with a particular intent/context pair might corrupt the results of multiple `findIntent` or `raiseIntent` tests. Hence, please stick to the defined type and report any issues you find so that they can be rectified in these definitions.\n\n### Find Intent basic usage\n\n- `2.0-FindIntentAppD`: Calls `fdc3.findIntent(\"aTestingIntent\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** `AppMetadata`.\n- `2.0-FindNonExistentIntentAppD`: Calls `fdc3.findIntent(\"nonExistentIntent\")`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDRightContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextX\")`.  Receives promise containing an `AppIntent` with metadata containing `aTestingIntent` and only metadata for app **A**.\n- `2.0-FindIntentAppDWrongContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextY\")`.  Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDMultiple1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and metadata for apps  **D**, **E**, **F**, **G**, **H**  and **I** only.\n- `2.0-FindIntentAppDMultiple2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", \"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and `AppMetadata` for apps  **E**, **F**, **G**, **H**  and **I** only.\n\n### Find Intents By Context\n\n- `2.0-FindIntentByContextSingleContext`: Call `fdc3.findIntentsByContext(testContextX)`.  Should return:\n  - `aTestingIntent` (app **A**),\n  - `sharedTestingIntent1` (**A**, **B**)\n  - `cTestingIntent` (**C**),\n  - `sharedTestingIntent2` (**D**)\n  - `kTestingIntent` (**K**),\n  - AND nothing else.\n- `2.0FindIntentByContextWrongIntentAppD`: Calls `fdc3.findIntentsByContext(nonExistentContext)`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n\n### Find Intents By Result Type\n\n- `2.0-FindIntentAppDByResultSingle`: Calls `fdc3.findIntent(\"cTestingIntent\", testContextX, \"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultSingleNullContext`: Calls `fdc3.findIntent(\"cTestingIntent\", null, \"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultMultiple`: Calls `fdc3.findIntent(\"sharedTestingIntent1\", testContextX, \"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **B** app metadata.\n- `2.0-FindIntentAppDByResultChannel1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", testContextY, \"channel\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and only **E** and **F** app metadata.\n- `2.0-FindIntentAppDByResultChannel2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", testContextY, \"channel<testContextZ>\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **F** app metadata.\n\n### Raise Intent (Ignoring any result)\n\n| App   | Step           | Details                                                                                           |\n|-------|----------------|---------------------------------------------------------------------------------------------------|\n| Test  | 1. Raise        | `fdc3.raiseIntent(\"aTestingIntent\", testContextX)`<br />starts app A.                       |\n| A     | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent1\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test  | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.**                       |\n\n- `2.0-RaiseIntentSingleResolve`: Perform above test\n- `2.0-RaiseIntentTargetedAppResolve`: Repeat the above test, but:\n  - In the first step use `fdc3.raiseIntent(\"sharedTestingIntent1\", testContextX, {\"appID\": \"<B's appId>\"})` to start app B,\n  - Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveOpen`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId: \"<A's appId>\"})` to start A and retrieve its `AppIdentifier` with instance details.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveFindInstances`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId: \"<A's appId>\"})` to start A.\n  - Then use `const instances = await fdc3.findInstances({appId: \"<A's appId>\"})` to retrieve a list of instances of app A. Confirm that only one is present and retrieve its `AppIdentifier`, confirming that it contains an `instanceId` field that matches that returned by the `fdc3.open` call.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentFailedResolve`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextY)`.  Note that no app supports this intent and context combination.**\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve1`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextY, {appId: \"<A's appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, {appId: \"NonExistentApp\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.TargetAppUnavailable`.\n- `2.0-RaiseIntentFailTargetedAppResolve3`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<H's appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but does not add any intent listeners).\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppResolve4`: Perform above test, but:\n  - `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<I's appId>\"})`\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but adds intent listeners of the wrong type.\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve1`: Perform above test, but:\n  - First spawn an instance of App **A** and collect its `AppIdentifier` with `const appIdentifier = await fdc3.open({appId: \"<A's appId>\"})`.\n  - Then use `fdc3.raiseIntent(\"aTestingIntent\", testContextY, appIdentifier)` to target that instance.\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound` (since A doesn't support this context type).\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, {appId: \"<A's appId>\", instanceId \"NonExistentInstanceId\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.TargetInstanceUnavailable`.\n\n### Raise Intent Result (void result)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"aTestingIntent\", testContextX)`<br />starts app A.                       |\n| A       | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.                     |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.                        |\n| A       | 5. return void          | A should return `void` after a short delay (e.g. 5 seconds).                        |\n| Test   | 6. receive void result          | The promise received by Test from `resolution.getResult()` should resolve to void. Confirm that the promise could be retrieved before the handler function returned and that the result was received *after* the result was returned by A, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited.                      |\n\n- `2.0-RaiseIntentVoidResult5secs`: Perform above test\n- `2.0-RaiseIntentVoidResult0secs`: Perform above test, but A should return its result immediately (no delay). Ignore test step 6 (as there is too little time between the IntentResolution and IntentHandler completing).\n- `2.0-RaiseIntentVoidResult61secs`: Perform above test, but A should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n### Raise Intent Result (Context result)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"sharedTestingIntent1\", testContextY)`<br />starts app **B**. |\n| B      | 2. Receive Intent & Context | After starting up, B runs `fdc3.addIntentListener(\"sharedTestingIntent1\")` to register its listener.<br />It then receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App B's `appId` and `instanceId` set. |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |\n| B      | 5. return `testContextY`          | B should return a `testContextY` instance after a short delay (e.g. 5 seconds). |\n| Test   | 6. receive context result          | The promise received by Test from `resolution.getResult()` should resolve to the `testContextY` instance. Confirm that the promise could be retrieved before the handler function returned and that the result was received *after* the result was returned by B, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited. |\n\n- `2.0-RaiseIntentContextResult5secs`: Perform the above test.\n- `2.0-RaiseIntentContextResult0secs`: Perform the previous test but B should return its result immediately (no delay).\n- `2.0-RaiseIntentContextResult61secs`: As above, but B should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n### Raise Intent Result (Channel results)\n\n| App   | Step                          | Details                                                                                           |\n|-------|-----------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise Intent          | Test raises an intent with `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<E's appId>\"})`<br />starts app E. |\n| E       | 2. Receive Intent & Context     | After starting up, E runs `fdc3.addIntentListener(\"sharedTestingIntent2\")` to register its listener.<br />It them receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution   | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App E's `appId` and `instanceId` set.   |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| E       | 5. return Channel | E should retrieve a Channel object via `fdc3.getOrCreateChannel(\"someChannelName\")` and return it immediately. |\n| Test   | 6. receive Channel result | The promise received by Test from `resolution.getResult()` should resolve to a `Channel` object with the expected id. Confirm that the `type` of the Channel object is \"app\".\n| Test   | 7. addContextListener | Add a context listener to the Channel object via `channelObj.addContextListener(\"testContextZ\", handler)` |\n| E       | 8. broadcast context | After a short delay (of a few seconds) E should broadcast a `testContextZ` context object over the channel, including an `id` field with a unique identifier set (e.g. a uuid). |\n| Test  | 9. receive context | Test should receive the context broadcast by E and confirm that it contains the expected `id` value. |\n\n- `2.0-RaiseIntentChannelResult`: Perform the above test\n- `2.0-RaiseIntentPrivateChannelResult`: Perform the above test, but:\n  - Substitute app F throughout - which returns a PrivateChannel result instead of channel.\n  - At step 5, the PrivateChannel should be created via`fdc3.createPrivateChannel()`.\n  - At step 6 confirm that the type of the channel is \"private\".\n\n### PrivateChannels cannot be accessed as app channels\n\n| App  | Step                | Details                                                                                                                                    |\n|-------|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Create a private channel | Test creates a PrivateChannel with `const privChan = await fdc3.createPrivateChannel()`. Confirm that the Channel has an `id`.\n| Test   | 2. Confirm private channel `id` is unique | Test creates a second PrivateChannel with `const privChan = await fdc3.createPrivateChannel();`. Confirm that the Channel has an `id` and that it is distinct from the first channel created. |\n| Test   | 3. Retrieve as app channel | Attempt to retrieve the channels as App Channels with `const appChan = await fdc3.getOrCreateChannel(privChan.id)` this should fail with `ChannelError.AccessDenied`  |\n| Test   | 4. Raise Intent & await result | Start app J and pass it the id of the second PrivateChannel with `fdc3.raiseIntent(\"privateChannelIsPrivate\", privateChannelDetails)`, where the context object contains the id of the channel to attempt to retrieve. An IntentResolution should be returned and App J should start. Wait for a result to be returned via `await resolution.getResult()`.\n| J | 5. Receive Intent & Context | J should add an Intent Listener and receive the context with `fdc3.addIntentListener(\"privateChannelIsPrivate\", handler)` |\n| J | 6. Retrieve as app channel | J should attempt to retrieve the channel as an App Channel by `id` with `const appChan = await fdc3.getOrCreateChannel(\"<idPassedInContext>\")` this should fail with `ChannelError.AccessDenied`. Return a `privateChannelIsPrivateResult` back to Test to complete the test. |\n| Test   | 7. Receive result | Test receives the result back from J and confirms that the test was passed. |\n\n- `2.0-PrivateChannelsAreNotAppChannels`: Perform the above test\n\n### PrivateChannel Lifecycle Events\n\n| App  | Step                 | Details                                                                                                                                    |\n|-------|-----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent(\"kTestingIntent\", testContextX, {appId: \"<K's appId>\"})`<br />starts app K. |\n| K       | 2. Receive Intent & Context     | After starting up, K runs `fdc3.addIntentListener(\"kTestingIntent\")` to register its listener.<br />It them receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution   | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set.   |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| K       | 5. Create PrivateChannel and setup event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,<br />it should then add listeners for the 3 events offered + a context listener via:<br />- `const listener1 = await privChan.onAddContextListener(handler1);`<br />- `const listener2 = await privChan.onUnsubscribe(handler2);`<br />- `const listener3 = await privChan.onDisconnect(handler3);`<br />- `const listener4 = await privChan.addContextListener(\"testContextX\", handler4)`<br />it should then return the `PrivateChannel`. |\n| Test   | 6. receive PrivateChannel  | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is \"private\".\n| Test   | 7. addContextListener | Test should add a context listener to the PrivateChannel object via `const listener1 = privChan.addContextListener(\"testContextZ\", handler)` |\n| K       | 8. Receive event & broadcast context | The `onAddContextListener` handler (`listener1`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |\n| Test   | 9. Unsubscribe listener | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `listener1.unsubscribe().` |\n| K       | 10. Receive unsubscribe event | The event handler registered by K via `onUnsubscribe` should fire. If it does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|\n| Test   | 11. Broadcast context | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |\n| K       | 12. Receive context | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|\n| Test   | 13. re-run addContextListener  | Test should (again) add a context listener to the PrivateChannel object via `const listener2 = privChan.addContextListener(\"testContextZ\", handler)` |\n| K       | 14. Receive event & broadcast context | The `onAddContextListener` handler added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |\n| Test   | 15. Disconnect | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |\n| K       | 16. Receive events & cleanup | The `onUnsubscribe` handler added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, the `onDisconnect` handler also added in step 5 should fire. Once it has, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |\n\n- `2.0-PrivateChannelsLifecycleEvents`: Perform the above test.\n\n### Resolving Ambiguous Intents\n\nFDC3 Desktop Agent MUST provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForContext that return multiple options). This is often accomplished by providing a user interface allowing the user to select the desired target application or intent and application.\n\nAs the methods of resolving ambiguous intents are often user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. These tests are based on the same applications defined for and used in other intent tests - however a separate manual test app should be provided to enable the test.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY)` |\n| User | 2. Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousIntentTarget`: Perform above steps to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 2.  Chooser Interaction | Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousContextTarget`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY)` |\n| User | 3. Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousIntentTargetMultiInstance`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 3.  Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousContextTargetMultiInstance`: Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/Metadata-Tests.md",
    "content": "---\nid: Metadata-Tests\nsidebar_label: Metadata Tests\ntitle: Metadata Tests\nhide_title: true\n---\n\n# Metadata & Instance Test Cases\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                        |\n|-----|------------------------------------------|\n| A   | Generic AppD Record which contains at least the following fields:<br />- `name`<br />- `version`<br />- `title`<br />- `tooltip`<br />- `description`<br />- `icons` (`Array<Icon>`)<br />- `screenshots` (`Array<Image>`)<br />- `interop.intents.listensFor` (`aTestingIntent` with at least context type `testContextX`)  |\n\n## Retrieve `AppMetadata` ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.getAppMetadata    | Retrieve metadata for the configured app A with <br/> `const metadata1 = await fdc3.getAppMetadata({appId: \"<A's appId>\"})`  |\n| Test   | 2.Confirm    | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set  |\n\n- `GetAppMetadata`: perform the above steps\n\n## Instance Metadata ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Open1    | Open a first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test   | 2. Open2    |Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test   | 3. getAppMetadata1    | Retrieve metadata for the first instance of the app with<br/> `const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |\n| Test   | 4. Confirm1 | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches.  |\n| Test   | 5. getAppMetadata2    | Retrieve metadata for the second instance of the app with <br/>`const metadata2 = fdc3.getAppMetadata(appIdentifier2)`  |\n| Test   | 6. Confirm2    | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2`  |\n\n- `AppInstanceMetadata`: Perform the above steps\n\n## Finding Instances ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Open1    | Open the first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test   | 2. Open2    |Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test   | 3. FindInstances    | Retrieve details of open instances of app A with <br/> `let instances = await fdc3.findInstances({appId: \"<A's appId>\"})` <br/> confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array.  |\n| Test   | 4. RaiseIntent   | Use `appIdentifier1` to raise an intent and target that instance, with<br/> `const resolution = fdc3.raiseIntent(\"aTestingIntent\", {\"type\": \"testContextX\"}, appIdentifier1)` |\n| Test   | 5. Confirm1 | Check that `resolution.source` matches `appIdentifier1` |\n| A      | 6. ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |\n\n- `FindInstances`: Perform the above steps\n\n## Getting Info For The Agent\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. getInfo    |Retrieve the `ImplementationMetadata` for the DesktopAgent with <br/> - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `let implMetadata = fdc3.getInfo()`  <br/> - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.getInfo().then((implMetadata) => { subsequent steps }`   <br />**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|\n| Test   | 2. CheckVersion  | Check that the `fdc3Version` variable is present and at or greater than:  <br /> -  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) 1.2 <br /> - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) 2.0  <br />(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):<br />`const isFDC3v2 = versionIsAtLeast(implMetadata, \"2.0\")`  |\n| Test   | 3. CheckProvider  | Check that the `provider` variable is present and not an empty string  |\n| Test   | 4. CheckFeatures  | ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values  |\n\n- ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `GetInfo1`: Perform the above steps\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.Open1    | Start an instance of App A with <br/>`const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br /> retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |\n| A | 2.getInfo     |   Retrieve the `ImplementationMetadata` for the DesktopAgent with: <br  />`fdc3.getInfo().then((implMetadata) => {  ... subsequent steps ...}` <br/> This should include `AppMetadata` for the retrieving app. |\n| A + Test | 3.Confirm  | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |\n\n- ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `GetInfo2`: Perform the above steps.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/Open-Tests.md",
    "content": "---\nid: Open-Tests\nsidebar_label: Open Tests\ntitle: Open Tests\nhide_title: true\n---\n\n# Open Tests\n\n## A Opens B  \n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App  | App A calls a function (see below) to open a second app, B |\n| A   | 2. Check Metadata | Ensure that the correct app was opened |\n\n- `AOpensB1`:   ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(\"app B Name\")` \n- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"<app B Name>\"})`\n- `AOpensB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"<app B Name>\", appId: \"<app B ID>\"})`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"})`\n- `AOpensB4`:  ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: \"<app B ID>\"})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.\n\n## A Fails To Open Another App\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App  | App A calls a function (see below) to try and open a non-existent app |\n| A   | 2. Check Error Response | ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open` throws an Error with the message \"App Not Found\"<br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open` returns a promise that rejects with an Error with the message \"App Not Found\" |\n\n- `AFailsToOpenB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(\"non existent app\")`\n- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"non existent app\"})`\n- `AFailsToOpenB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via: \n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"non existent app\", appId: \"non existent app\"})`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"})`\n\n## A Opens B With Context\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App     |App A opens app B with an `fdc3.instrument` Context Object by calling a function (see below) |\n| B   | 2. Receive Context | Add an untyped context listener via: <br />`fdc3.addContextListener(null, handler)` <br /> B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open() call made by A |\n\n- `AOpensBWithContext1`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(\"app B Name\", <fdc3.instrument context>)`\n- `AOpensBWithContext2`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"<app B Name>\"}, <fdc3.instrument context>)`\n- `AOpensBWithContext3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"<app B Name>\", appId: \"<app B ID>\"}, <fdc3.instrument context>)`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"}, <fdc3.instrument context>)`\n- `AOpensBWithSpecificContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener('fdc3.instrument', handler)`\n- `AOpensBMultipleListen`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener('fdc3.contact', handler)` prior to the existing `addContextListener` for `fdc3.instrument`.  The correct context listener should receive the context, and the promise completes successfully. \n- `AOpensBWithWrongContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.\n  - Confirm that NO context is received.\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) the `fdc3.open` call throws an Error with message `AppTimeout`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) The promise returned to **A** by `fdc3.open` rejects with an Error with message `AppTimeout`\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/Overview.md",
    "content": "---\nid: Conformance-Overview\nsidebar_label: Overview\ntitle: FDC3 Conformance Tests\nhide_title: true\n---\n\n# FDC3 Conformance Tests\n\nThis section contains test definitions that are used to test for conformance of a Desktop Agent API implementation with FDC3.\n\nYou can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.\n\nThere are currently 6 sections to the tests.  Where tests apply to a particular version of FDC3, this is labelled with icons in the header, like so: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n- [Basic Tests](Basic-Tests.md)\n- [Open Tests](Open-Tests.md)\n- [User Channel Tests](User-Channel-Tests.md)\n- [App Channel Tests](App-Channel-Tests.md)\n- [Metadata Tests](Metadata-Tests.md)\n- [Intents Tests](Intents-Tests.md)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/conformance/User-Channel-Tests.md",
    "content": "---\nid: User-Channel-Tests\nsidebar_label: User Channel Tests\ntitle: User Channel Tests\nhide_title: true\n---\n\n# User Channel Tests  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_NB:  User Channels were called System Channels in FDC3 1.2.  The new terminology is used in this specification_\n\n## Basic Broadcast\n\n| App | Step               |Details                                                                           |\n|-----|--------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener |A adds an _unfiltered_ Context Listener using `addContextListener(null, handler)`. <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` method. |\n| A   | 2. joinUserChannel     |A joins the first available (non-global) user channel.  The available Channels are retrieved with: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getSystemChannels()` _Check channels are returned._ <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.getUserChannels()` <br/> The first channel (that does not have the id 'global') is joined with: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.joinChannel(<channelId>)` _Check channels are returned._ <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.joinUserChannel(<channelId>)`  |\n| B   | 3. joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast(<the instrument>)`. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the instrument object, matching the one broadcast by B.  |\n\n- `UCBasicUsage1` Perform above test\n- `UCBasicUsage2` Perform steps in order: 2,1,3,4,5 to confirm that the order of `joinUserChannel` and `addContextListener` calls doesn't matter\n- `UCBasicUsage3` Perform steps in order: 3,4,1,2,5 to confirm that the current context is automatically received on joining a channel.\n- `UCBasicUsage4` Perform steps in order: 3,4,2,1,5  to confirm that the current context is automatically received on adding a context listener to an already joined a channel.\n\n## Filtered Broadcast\n\n| App | Step               |Details                                                                           |\n|-----|--------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener |A adds a `fdc3.instrument` _typed_ Context Listener using `addContextListener(\"fdc3.instrument\", handler)`. <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` method.|\n| A   | 2. joinUserChannel     |A joins the first available user channel using: <br/> ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `getSystemChannels()` Check channels are returned. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts: <br/> 1.`fdc3.broadcast(<the instrument>)`. <br/> 2. `fdc3.broadcast(<a contact>)` <br /> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the `fdc3.instrument` object, matching the one broadcast by B. <br />Check that the `fdc3.contact` is NOT received. |\n\n- `UCFilteredUsage1` Perform above test\n- `UCFilteredUsage2` Perform steps in order: 2,1,3,4,5\n- `UCFilteredUsage3` Perform steps in order: 3,4,1,2,5\n- `UCFilteredUsage4` Perform steps in order: 3,4,2,1,5\n\n## Broadcast With Multiple Listeners\n\n| App | Step               | Details                                                                                                     |\n|-----|--------------------|-------------------------------------------------------------------------------------------------------------|\n| A   | 1. addContextListeners | A sets up two Context Listeners.  One for `fdc3.instrument` and one for `fdc3.contact` by calling:  `addContextListener (\"fdc3.instrument\", handler)` <br/> `addContextListener (\"fdc3.contact\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned for each.  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned for each. <br />Check that this has an `unsubscribe` method for each.  |\n| A   | 2. joinUserChannel     |A joins the first available user channel using: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `getSystemChannels()` Check channels are returned. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | `fdc3.broadcast(<instrument context>)` <br/> `fdc3.broadcast(<contact context>)` . |\n| A   | 5.Receive Context    | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.<br />A's `fdc3.contact` object matches the one broadcast  by B, and arrives on the correct listener.   |\n\n- `UCFilteredUsage5`: Perform above test\n- `UCFilteredUsage6`: Perform above test, except B will join a _different_ channel to A. Check that you _don't_ receive anything.\n- `UCFilteredUsageChange`: Perform above test, except that after joining, **A** changes channel to a _different_ channel via a further call to `fdc3.joinUserChannel`.  Check that **A** does NOT receive anything.\n- `UCFilteredUsageUnsubscribe`: Perform above test, except that after joining, **A** then `unsubscribe()`s from the channel using the `listener.unsubscribe` function. Check that **A** does NOT receive anything.\n- `UCFilteredUsageLeave`: Perform above test, except that immediately after joining, **A** _leaves the channel_, and so receives nothing.\n- `UCFilteredUsageNoJoin`: Perform the above test, but skip step 2 so that **A** does NOT join a channel. Confirm that the _current channel_ for **A** is NOT set before continuing with the rest of the test.  **A** should receive nothing.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/overview.md",
    "content": "---\nsidebar_label: API Overview\ntitle: API Overview\nhide_title: true\noriginal_id: overview\n---\n# API Overview\n\nThe API specification of the FDC3 standard support the following goals:\n- Create a consistent developer interface for working with FDC3\n- Standardize interfaces for reference implementations\n- Standardize interfaces between desktop agents\n\nThe role of FDC3 API specification is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications - standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe focus of the FDC3 Standard Working Group has been to create a small but consistent API, the following docs go through the components and API's in detail.\n\n## Key Elements\n\n- [`window.fdc3`](ref/Globals#windowfdc3-object) global object and [`fdc3Ready`](ref/Globals#fdc3ready-event) event, for accessing FDC3 operations globally\n- [`DesktopAgent`](ref/DesktopAgent) interface, which exposes FDC3 operations\n- [`Channel`](ref/Channel) interface, for subscribing to specific context channels\n- [`Listener`](ref/Types#listener) interface, which allows unsubscribing intent or context listeners\n\n## Usage\n\nThere are two main ways FDC3 can be used from web applications:\n\n### 1. Direct Usage\n\nSimply rely on the global object being made available by your desktop agent, and address the API directly:\n\n```ts\nfunction sendData() {\n  window.fdc3.broadcast({\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n  })\n}\n\nif (window.fdc3) {\n  sendData();\n} else {\n  window.addEventListener(\"fdc3Ready\", sendData);\n}\n```\n\n\n### 2. NPM Wrapper\n\nThe [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) provides a wrapper around FDC3, allowing you to use it with ES6 import syntax:\n\n```ts\nimport * as fdc3 from '@finos/fdc3'\n\nawait fdc3.raiseIntent('ViewAnalysis', {\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n})\n```\n\nIt also includes a helper function you can use to wait for FDC3 to become available:\n\n```ts\nimport { fdc3Ready, addIntentListener } from '@finos/fdc3'\n\nawait fdc3Ready();\n\nconst listener = addIntentListener('ViewAnalysis', instrument => {\n  // handle intent\n})\n```\n\n#### See also\n* [`fdc3Ready() Function`](ref/Globals#fdc3ready-function)\n\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/Channel.md",
    "content": "---\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\noriginal_id: Channel\n---\n# `Channel`\n\nRepresents a context channel that applications can use to send and receive context data.\n\nA channel can be either a [\"User\" channel](../spec#joining-user-channels) (retrieved with [`getUserChannels`](DesktopAgent#getuserchannels)), a custom [\"App\" channel](../spec#app-channels) (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)) or a [\"Private\" channel](../spec#private-channels) (obtained via an intent result).\n\n:::note\n\nThere are differences in behavior when you interact with a User channel via the `DesktopAgent` interface and the `Channel` interface. Specifically, when 'joining' a User channel or adding a context listener when already joined to a channel via the `DesktopAgent` interface, existing context (matching the type of the context listener) on the channel is received by the context listener immediately. Whereas, when a context listener is added via the `Channel` interface, context is not received automatically, but may be retrieved manually via the [`getCurrentContext()`](#getcurrentcontext) function.\n\n:::\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: \"user\" | \"app\" | \"private\";\n  displayMetadata?: DisplayMetadata;\n\n  // functions\n  broadcast(context: Context): Promise<void>;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n  \n  //deprecated functions\n  /**\n   * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n}\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`Listener`](Types#listener)\n* [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n\n## Properties\n\n### `id`\n\n```ts\npublic readonly id: string;\n```\n\nUniquely identifies the channel. It is either assigned by the desktop agent (User Channel) or defined by an application (App Channel).\n\n### `type`\n\n```ts\npublic readonly type: \"user\" | \"app\" | \"private\";\n```\n\nCan be _user_,  _app_ or _private_.\n\n### `displayMetadata`\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\nDisplayMetadata can be used to provide display hints for User Channels intended to be visualized and selectable by end users.\n\n#### See also\n\n* [`DisplayMetadata`](Metadata#displaymetadata)\n\n## Functions\n\n### `addContextListener`\n\n```ts\npublic addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\nIf, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the [`getCurrentContext(contextType)`](#getcurrentcontext) function.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n#### Examples\n\nAdd a listener for any context that is broadcast on the channel:\n\n```ts\nconst listener = await channel.addContextListener(null, context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n```ts\nconst contactListener = await channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n#### See also\n\n* [`Listener`](Types#listener)\n* [`ContextHandler`](Types#contexthandler)\n* [`broadcast`](#broadcast)\n* [`getCurrentContext`](#getcurrentcontext)\n\n### `broadcast`\n\n```typescript\npublic broadcast(context: Context): Promise<void>;\n```\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [FDC3 Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\n#### Example\n\n```javascript\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n\n* [`ChannelError`](Errors#channelerror)\n* [`getCurrentContext`](#getcurrentcontext)\n* [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\nIf getting the current context fails, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\n#### Examples\n\nWithout specifying a context type:\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\nSpecifying a context type:\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler errror\n}\n```\n\n#### See also\n\n* [`ChannelError`](Errors#channelerror)\n* [`broadcast`](#broadcast)\n* [`addContextListener`](#addcontextlistener)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n```ts\n/**\n * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\npublic addContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n#### See also\n\n* [`addContextListener`](#addcontextlistener)"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/DesktopAgent.md",
    "content": "---\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\noriginal_id: DesktopAgent\n---\n# `DesktopAgent`\n\nAn FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nIt is expected that the `DesktopAgent` interface is made availabe via the [`window.fdc3`](Globals#windowfdc3-object) global object, and that the [`fdc3Ready`](Globals#fdc3ready-event) event fires when it is ready to be used.\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n\n  // context\n  broadcast(context: Context): Promise<void>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n\n  // intents\n  findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n  findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n\n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  createPrivateChannel(): Promise<PrivateChannel>;\n  getUserChannels(): Promise<Array<Channel>>;\n\n  // OPTIONAL channel management functions\n  joinUserChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel | null>;\n  leaveCurrentChannel() : Promise<void>;\n\n  //implementation info\n  getInfo(): Promise<ImplementationMetadata>;\n\n  //Deprecated functions\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  open(name: String, context?: Context): Promise<AppIdentifier>;\n  raiseIntent(intent: string, context: Context, name: String): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, name: String): Promise<IntentResolution>;\n}\n```\n\n## Functions\n\n### `addContextListener`\n\n```ts\naddContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming context broadcasts from the Desktop Agent on the current User Channel. If the consumer is only interested in a context of a particular type, they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.\n\nContext broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from User channels. If this function is called after the app has already joined a channel and the channel already contains context that matches the type of the context listener, then it will be called immediately and the context passed to the handler function. If `null` was passed as the context type for the listener and the channel contains context, then the handler function will be called immediately with the most recent context - regardless of type.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the Desktop Agent implementation.\n\n#### Examples\n\n```js\n// any context\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n// listener for a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });\n\n// listener that logs metadata for the message a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', (contact, metadata) => {\n  console.log(`Received context message\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n  //do something else with the context\n});\n```\n\n#### See also\n\n* [`Listener`](Types#listener)\n* [`Context`](Types#context)\n* [`ContextHandler`](Types#contexthandler)\n\n### `addIntentListener`\n\n```ts\naddIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming intents from the Desktop Agent. The handler function may return void or a promise that resolves to a [`IntentResult`](Types#intentresult), which is either a [`Context`](Types#context) object, representing any data that should be returned to the app that raised the intent, or a [`Channel`](Channel) or [`PrivateChannel`](PrivateChannel) over which data responses will be sent. The `IntentResult` will be returned to the app that raised the intent via the [`IntentResolution`](Metadata#intentresolution) and retrieved from it using the `getResult()` function.\n\nThe Desktop Agent MUST reject the promise returned by the `getResult()` function of `IntentResolution` if any of the following is true:\n1. The intent handling function's returned promise rejects.\n2. The intent handling function doesn't return a promise.\n3. The returned promise resolves to an invalid type.\n\nThe [`PrivateChannel`](PrivateChannel) type is provided to support synchronisation of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n#### Examples\n\n```js\n//Handle a raised intent\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n  return;\n});\n\n//Handle a raised intent and log the originating app metadata\nconst listener = fdc3.addIntentListener('StartChat', (contact, metadata) => {\n  console.log(`Received intent StartChat\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n    return;\n});\n\n//Handle a raised intent and return Context data via a promise\nfdc3.addIntentListener(\"CreateOrder\", (context) => {\n  return new Promise<Context>((resolve) => {\n    // go create the order\n    resolve({type: \"fdc3.order\", id: { \"orderId\": 1234}});\n  });\n});\n\n//Handle a raised intent and return a PrivateChannel over which response will be sent\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel: PrivateChannel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // Called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // Stop the feed if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n#### See also\n\n* [Register an Intent Handler](../spec#register-an-intent-handler)\n* [`PrivateChannel`](PrivateChannel)\n* [`Listener`](Types#listener)\n* [`Context`](Types#context)\n* [`IntentHandler`](Types#intenthandler)\n\n### `broadcast`\n\n```ts\nbroadcast(context: Context): Promise<void>;\n```\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User Channel_ the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\nDesktopAgent implementations should ensure that context messages broadcast to a channel by an application joined to it are not delivered back to that same application.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\n#### Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n#### See also\n\n* [addContextListener](#addcontextlistener)\n\n### `createPrivateChannel`\n\n```ts\ncreatePrivateChannel(): Promise<PrivateChannel>;\n```\n\nReturns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.\n\nIf the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\nThe `PrivateChannel` type is provided to support synchronisation of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nIt is intended that Desktop Agent implementations:\n\n* SHOULD restrict external apps from listening or publishing on this channel.\n* MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n* MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n#### Example\n\n```js\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // This gets called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  const unsubscriberListener = channel.onUnsubscribe((contextType) => {\n    feed.stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n#### See also\n\n* [`PrivateChannel`](PrivateChannel)\n* [`raiseIntent`](#raiseintent)\n* [`addIntentListener`](#addintentlistener)\n\n### `findInstances`\n\n```ts\nfindInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n```\n\nFind all the available instances for a particular application.\n\nIf there are no instances of the specified application the returned promise should resolve to an empty array.\n\nIf the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the `ResolveError` enumeration.\n\n#### Example\n\n```js\n// Retrieve a list of instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Target a raised intent at a specific instance\nlet resolution = fdc3.raiseIntent(\"ViewInstrument\", context, instances[0]);\n```\n\n### `findIntent`\n\n```ts\nfindIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type.\n\n`findIntent` is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to an `AppIntent` which provides details of the intent, its metadata and metadata about the apps and app instances that are registered to handle it. This can be used to raise the intent against a specific app or app instance.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration. This includes the case where no apps are found that resolve the intent, when the `ResolveError.NoAppsFound` message should be used.\n\nResult types 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.\n\n#### Examples\n\nI know 'StartChat' exists as a concept, and want to know which apps can resolve it:\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//   intent: { name: \"StartChat\", displayName: \"Chat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Slack\" }\n//   ]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0]);\n\n//later, we want to raise 'StartChat' intent again\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns an AppIntent, but with multiple options for resolution,\n// which includes an existing instance of an application:\n// {\n//   intent: { name: \"StartChat\", displayName: \"Chat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//    { appId: \"Slack\" }\n//   ]\n```\n\nAn optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types.\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\", contact);\n\n// returns only apps that support the type of the specified input context:\n// {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: { name: \"Symphony\" }]\n// }\n\nconst appIntent = await fdc3.findIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     intent: { name: \"ViewContact\", displayName: \"View Contact Details\" },\n//     apps: { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }\n\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     intent: { name: \"QuoteStream\", displayName: \"Quotes stream\" },\n//     apps: { appId: \"MyOMS\", resultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n#### See also\n\n* [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```ts\nfindIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context, and optionally a desired result context type.\n\n`findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.\nA 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.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration. This includes the case where no intents with associated apps are found, when the `ResolveError.NoAppsFound` message should be used.\n\nThe 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 without a specified context type, 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.\n\n#### Example\n\nI 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...\n\n```js\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [\n//   {\n//     intent: { name: \"StartCall\", displayName: \"Call\" },\n//     apps: [{ appId: \"Skype\" }]\n//   },\n//   {\n//     intent: { name: \"StartChat\", displayName: \"Chat\" },\n//     apps: [\n//       { appId: \"Skype\" },\n//       { appId: \"Symphony\" },\n//       { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//       { appId: \"Slack\" }\n//     ]\n//   },\n//   {\n//     intent: { name: \"ViewContact\", displayName: \"View Contact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n//   }\n// ];\n```\n\nor I look for only intents that are resolved by apps returning a particular result type\n\n```js\nconst appIntentsForType = await fdc3.findIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     intent: { name: \"ViewContact\", displayName: \"View Contact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app or instance\nconst selectedApp = startChat.apps[2];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp);\n```\n\n#### See also\n\n* [`findIntent()`](#findintent)\n* [`ResolveError`](Errors#resolveerror)\n\n### `getAppMetadata`\n\n```ts\ngetAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n```\n\nRetrieves the [`AppMetadata`](Metadata#appmetadata) for an [`AppIdentifier`](Types#appidentifier), which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes.\n\n#### Examples\n\n```js\nlet appIdentifier = { appId: \"MyAppId@my.appd.com\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n#### See also\n\n* [`AppMetadata`](Metadata#appmetadata)\n* [`AppIdentifier`](Types#appidentifier)\n\n### `getCurrentChannel`\n\n```ts\ngetCurrentChannel() : Promise<Channel | null>;\n```\n\nOPTIONAL function that returns the `Channel` object for the current User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nReturns `null` if the app is not joined to a channel.\n\n#### Examples\n\n```js\n// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `getInfo`\n\n```ts\ngetInfo(): Promise<ImplementationMetadata>;\n```\n\nRetrieves information about the FDC3 Desktop Agent implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent.\n\nReturns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.  This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes.\n\n#### Example\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\nThe `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n```\n\n#### See also\n\n* [`ImplementationMetadata`](Metadata#implementationmetadata)\n* [`AppMetadata`](Metadata#appmetadata)\n\n### `getOrCreateChannel`\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\nReturns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist.\n\nIf the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n\n\n#### Example\n\n```js\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  myChannel.addContextListener(null, context => { /* do something with context */});\n}\ncatch (err){\n  //app could not register the channel\n}\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `getUserChannels`\n\n```ts\ngetUserChannels() : Promise<Array<Channel>>;\n```\n\nRetrieves a list of the User Channels available for the app to join.\n\n#### Example\n\n```js\nconst userChannels = await fdc3.getUserChannels();\nconst redChannel = userChannels.find(c => c.id === 'red');\n```\n\n#### See also\n\n* [`Channel`](Channel)\n\n### `joinUserChannel`\n\n```ts\njoinUserChannel(channelId: string) : Promise<void>;\n```\n\nOPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nIf an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.\n\nIf the channel already contains context that would be passed to context listeners added via `fdc3.addContextListener` then those listeners will be called immediately with that context.\n\nAn app can only be joined to one channel at a time.\n\nIf an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\n#### Examples\n\n```js\n// get all user channels\nconst channels = await fdc3.getUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\nfdc3.joinUserChannel(selectedChannel.id);\n\n```\n\n#### See also\n\n* [`getUserChannels`](#getuserchannels)\n\n### `leaveCurrentChannel`\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\nOPTIONAL function that removes the app from any User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nContext broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel.\n\n#### Examples\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(null, context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(null, channelListener);\n\n```\n\n### `open`\n\n```ts\nopen(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n```\n\nLaunches an app, specified via an [`AppIdentifier`](Types#appidentifier) object.\n\nThe `open` method differs in use from [`raiseIntent`](#raiseintent).  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying an App Directory, `open` would be used to open an app returned in the search results.\n\n**Note**, if the intent, context and target app name are all known, it is recommended to instead use [`raiseIntent`](#raiseintent) with the `target` argument.\n\nIf a [`Context`](Types#context) object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n\nReturns an [`AppIdentifier`](Types#appidentifier) object with the `instanceId` field set to identify the instance of the application opened by this call.\n\nIf an error occurs while opening the app, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`OpenError`](Errors#openerror) enumeration.\n\n\n#### Example\n\n ```js\n// Open an app without context, using an AppIdentifier object to specify the target\nlet appIdentifier = { appId: 'myApp-v1.0.1' };\nlet instanceIdentifier = await fdc3.open(appIdentifier);\n\n// Open an app with context\nlet instanceIdentifier = await fdc3.open(appIdentifier, context);\n```\n\n#### See also\n\n* [`Context`](Types#context)\n* [`AppIdentifier`](Types#appidentifier)\n* [`AppMetadata`](Metadata#appmetadata)\n* [`OpenError`](Errors#openerror)\n\n### `raiseIntent`\n\n```ts\nraiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\nRaises a specific intent for resolution against apps registered with the desktop agent.\n\nThe 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.\nAlternatively, 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).\n\nIf 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, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`.\n\nIf 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.\n\nReturns an [`IntentResolution`](Metadata#intentresolution) object with details of the app instance that was selected (or started) to respond to the intent.\n\nIssuing 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, Channel object or void 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 valid response (a promise or void), or (3) the returned promise resolves to an invalid type.\n\n#### Example\n\n```js\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait fdc3.raiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Raise an intent without a context by using the null context type\nawait fdc3.raiseIntent(\"StartChat\", {type: \"fdc3.nothing\"});\n\n//Raise an intent and retrieve a result from the IntentResolution\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  if (result && result.broadcast) { //detect whether the result is Context or a Channel\n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n```\n\n#### See also\n\n* [Raising Intents](../spec#raising-intents)\n* [`Context`](Types#context)\n* [`AppIdentifier`](Types#appidentifier)\n* [`IntentResult`](Types#intentresult)\n* [`IntentResolution`](Metadata#intentresolution)\n* [`ResolveError`](Errors#resolveerror)\n* [`ResultError`](Errors#resulterror)\n\n### `raiseIntentForContext`\n\n```ts\nraiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\nFinds and raises an intent against apps registered with the desktop agent based purely on the type of the context data.\n\nThe desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context.\nAlternatively, the specific app or app instance to target can also be provided, in which case any method of resolution SHOULD only consider intents supported by the specified application.\n\nUsing `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app.\n\nReturns an `IntentResolution` object, see [`raiseIntent()`](#raiseintent) for details.\n\nIf a target intent and app cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`.\n\n#### Example\n\n```js\n// Display a resolver UI for the user to select an intent and application to resolve it\nconst intentResolution = await fdc3.raiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait fdc3.raiseIntentForContext(context, targetAppIdentifier);\n```\n\n#### See also\n\n* [Raising Intents](../spec#raising-intents)\n* [`raiseIntent()`](#raiseintent)\n* [`Context`](Types#context)\n* [`AppIdentifier`](Types#appidentifier)\n* [`IntentResolution`](Metadata#intentresolution)\n* [`ResolveError`](Errors#resolveerror)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n```ts\naddContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming context broadcasts from the Desktop Agent. Provided for backwards compatibility with versions FDC3 standard &lt;2.0.\n\n#### See also\n\n* [`addContextListener`](#addcontextlistener)\n\n### `getSystemChannels` (deprecated)\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\nAlias to the [`getUserChannels`](#getuserchannels) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n#### See also\n\n* [`getUserChannels`](#getuserchannels)\n\n### `joinChannel` (deprecated)\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\nAlias to the [`joinUserChannel`](#joinuserchannel) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n\n#### See also\n* [`joinUserChannel`](#joinuserchannel)\n\n### `open` (deprecated)\n\n```ts\nopen(name: String, context?: Context): Promise<AppIdentifier>;\n```\n\nVersion of `open` that launches an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n#### See also\n\n* [`open`](#open)\n\n### `raiseIntent` (deprecated)\n\n```ts\nraiseIntent(intent: string, context: Context, name: String): Promise<IntentResolution>;\n```\n\nVersion of `raiseIntent` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n#### See also\n\n* [`raiseIntent`](#raiseintent)\n\n### `raiseIntentForContext` (deprecated)\n\n```ts\nraiseIntentForContext(context: Context, name: String): Promise<IntentResolution>;;\n```\n\nVersion of `raiseIntentForContext` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n#### See also\n\n* [`raiseIntentForContext`](#raiseintentforcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/Errors.md",
    "content": "---\ntitle: Errors\noriginal_id: Errors\n---\n\nFDC3 API operations may sometimes result in an error, which must be returned to the caller. Errors should be returned by rejecting the promise returned by the API with a JavaScript `Error` object (or equivalent for the language of the implementation). The `Error` Object's message should be chosen from the appropriate Error enumeration below.\n\n## `ChannelError`\n\n```typescript\nenum ChannelError {\n  /** Returned if the specified channel is not found when attempting to join a\n   *  channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).\n   */\n  NoChannelFound = 'NoChannelFound',\n\n  /** SHOULD be returned when a request to join a user channel or to a retrieve\n   *  a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods\n   *  of the DesktopAgent (`fdc3`) object is denied. \n   */\n  AccessDenied = 'AccessDenied',\n  \n  /** SHOULD be returned when a channel cannot be created or retrieved via the\n   *  `getOrCreateChannel` method of the DesktopAgent (`fdc3`).\n   */\n  CreationFailed = 'CreationFailed',\n}\n```\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n#### See also\n\n* [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n* [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  /** Returned if the specified application is not found.*/\n  AppNotFound = 'AppNotFound',\n\n  /** Returned if the specified application fails to launch correctly.*/\n  ErrorOnLaunch = 'ErrorOnLaunch',\n\n  /** Returned if the specified application launches but fails to add a context\n   *  listener in order to receive the context passed to the `fdc3.open` call.\n   */\n  AppTimeout = 'AppTimeout',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = 'ResolverUnavailable',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n#### See also\n\n* [`DesktopAgent.open`](DesktopAgent#open)\n\n## `ResolveError`\n\n```typescript\nexport enum ResolveError {\n  /** SHOULD be returned if no apps are available that can resolve the intent\n   *  and context combination.\n   */\n  NoAppsFound = 'NoAppsFound',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = 'ResolverUnavailable',\n\n  /** Returned if the user cancelled the resolution request, for example by\n   *  closing or cancelling a resolver UI.\n   */\n  UserCancelled = 'UserCancelledResolution',\n\n  /** SHOULD be returned if a timeout cancels an intent resolution that\n   *  required user interaction. Please use `ResolverUnavailable` instead for\n   *  situations where a resolver UI or similar fails.\n   */\n  ResolverTimeout = 'ResolverTimeout',\n\n  /** Returned if a specified target application is not available or a new\n   *  instance of it cannot be opened. \n   */\n  TargetAppUnavailable = 'TargetAppUnavailable',\n\n  /** Returned if a specified target application instance is not available,\n   *  for example because it has been closed. \n   */\n  TargetInstanceUnavailable = 'TargetInstanceUnavailable',\n\n  /** Returned if the intent and context could not be delivered to the selected\n   *  application or instance, for example because it has not added an intent\n   *  handler within a timeout.\n   */\n  IntentDeliveryFailed = 'IntentDeliveryFailed',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent), [`findIntentsByContext`](DesktopAgent#findintentsbycontext), [`raiseIntent`](DesktopAgent#raiseintent) or [`raiseIntentForContext`](DesktopAgent#raiseintentforcontext) methods on the [DesktopAgent](DesktopAgent).\n\n#### See also\n\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n\n## `ResultError`\n\n```typescript\nenum ResultError {\n  /** Returned if the intent handler exited without returning a valid result \n   * (a promise resolving to a Context, Channel object or void).\n   */\n  NoResultReturned = 'NoResultReturned',\n\n  /** Returned if the `IntentHandler` function processing the raised intent\n   *  throws an error or rejects the Promise it returned. \n   */\n  IntentHandlerRejected = 'IntentHandlerRejected',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object.\n\n#### See also\n\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`IntentResolution`](Metadata#intentresolution)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/Globals.md",
    "content": "---\ntitle: Globals\noriginal_id: Globals\n---\n\nSince FDC3 is typically available to the whole web application, desktop agents are expected to make the [`DesktopAgent`](DesktopAgent) interface available at a global level.\n\n## `window.fdc3` Object\n\nThe global `fdc3` object can be used to access FDC3 API operations, if the current desktop agent supports FDC3.\n\n### Example\n\n```ts\n// check if fdc3 is available\nif (window.fdc3) {\n  // raise an intent\n  await window.fdc3.raiseIntent('StartChat', {\n    type: 'fdc3.contact',\n    id: { email: 'johndoe@mail.com' }\n  })\n}\n```\n\n## `fdc3Ready` Event\n\nThe global `window.fdc3` should only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors should provide an `fdc3Ready` event.\n\n### Example\n\n```ts\nfunction fdc3Action() {\n  // Make some fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Action();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Action);\n}\n```\n\n## `fdc3Ready()` Function\n\nIf you are using the `@finos/fdc3` NPM package, it includes a handy wrapper function that will check for the existence of `window.fdc3` and wait on the `fdc3Ready` event for you.\n\nIt returns a promise that will resolve immediately if the `window.fdc3` global is already defined, or reject with an error if the `fdc3Ready` event doesn't fire after a specified timeout period (default: 5 seconds).\n\n### Example\n\n```ts\nimport { fdc3Ready, broadcast } from '@finos/fdc3'\n\nasync function fdc3Action() {\n  try {\n    await fdc3Ready(1000); // wait for (at most) 1 second\n    broadcast({\n      type: 'fdc3.instrument',\n      id: { ticker: 'AAPL' }\n    })\n  } catch (error) {\n    // handle error\n  }\n}\n```\n\n\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/Metadata.md",
    "content": "---\ntitle: Metadata\noriginal_id: Metadata\n---\n\nFDC3 API operations return various types of metadata.\n\n## `AppIntent`\n\n```ts\ninterface AppIntent {\n  /** Details of the intent whose relationship to resolving applications is\n   *  being described.\n   */\n  readonly intent: IntentMetadata;\n\n  /** Details of applications that can resolve the intent. */\n  readonly apps: Array<AppMetadata>;\n}\n```\n\nAn interface that represents the binding of an intent to apps, returned as part of intent disocvery.\nFor each intent, it reference the applications that support that intent.\n\n#### See also\n\n* [`AppMetadata`](#appmetadata)\n* [`IntentMetadata`](#intentmetadata)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `AppMetadata`\n\n```ts\ninterface AppMetadata extends AppIdentifier {\n  /**\n   *  The 'friendly' app name. This field was used with the `open` and\n   *  `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier`\n   *  with `appId` set. \n   * \n   *  Note that for display purposes the `title` field should be used, if set,\n   *  in preference to this field.\n   */\n  readonly name?: string;\n\n  /** The version of the application. */\n  readonly version?: string;\n\n  /** An optional set of, implementation specific, metadata fields that can be\n   *  used to disambiguate instances, such as a window title or screen position.\n   *  Must only be set if `instanceId` is set. \n   */\n  readonly instanceMetadata?: Record<string, any>;\n\n  /** A more user-friendly application title that can be used to render UI\n   *  elements.\n   */\n  readonly title?: string;\n\n  /** A tooltip for the application that can be used to render UI elements. */\n  readonly tooltip?: string;\n\n  /** A longer, multi-paragraph description for the application that could\n   *  include mark-up.\n   */\n  readonly description?: string;\n\n  /** A list of icon URLs for the application that can be used to render UI \n   *  elements.\n   */\n  readonly icons?: Array<Icon>;\n\n  /** Images representing the app in common usage scenarios that can be used to render UI elements */\n  readonly screenshots?: Array<Image>;\n  \n  /** The type of result returned for any intent specified during resolution. \n   *  May express a particular context type (e.g. \"fdc3.instrument\"), channel \n   *  (e.g. \"channel\") or a channel that will receive a specified type \n   *  (e.g. \"channel<fdc3.instrument>\").\n   */\n  readonly resultType?: string | null;\n}\n```\n\nExtends an AppIdentifier, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\n\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\n\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc..\n\n#### See also\n\n* [`AppIdentifier`](Types#appidentifier)\n* [`AppIntent.apps`](Metadata#appintent)\n* [`Icon`](Metadata#icon)\n* [`Image`](Metadata#image)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## `ContextMetadata`\n\n```ts\ninterface ContextMetadata {\n  /** Identifier for the app instance that sent the context and/or intent. \n   *  @experimental \n   */\n  readonly source: AppIdentifier;\n}\n```\n\nMetadata relating to a context or intent & context received through the `addContextListener` and `addIntentListener` functions. Currently identifies the app that originated the context or intent message.\n\n[`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy.\n\n#### See also\n\n* [`AppMetadata`](#appmetadata)\n* [`ContextHandler`](Types#contexthandler)\n* [`IntentHandler`](Types#intenthandler)\n* [`addIntentListener`](DesktopAgent#addintentlistener)\n* [`addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DisplayMetadata`\n\n```ts\ninterface DisplayMetadata {\n  /**\n   *  A user-readable name for this channel, e.g: `\"Red\"`. */\n  readonly name?: string;\n\n  /**\n   *  The color that should be associated within this channel when displaying\n   *  this channel in a UI, e.g: `#FF0000`. May be any color value supported by\n   *  CSS, e.g. name, hex, rgba, etc.. */\n  readonly color?: string;\n\n  /**\n   *  A URL of an image that can be used to display this channel. */\n  readonly glyph?: string;\n}\n```\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n#### See also\n\n* [`Channel`](Channel)\n* [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n\n## `Icon`\n\n```typescript\ninterface Icon {\n  src: string;\n  size?: string;\n  type?: string;\n}\n```\n\nMetadata relating to a single icon image at a remote URL, used to represent an application in a user interface.\n\nAppMetadata includes an icons property allowing multiple icon types to be specified. Various properties may be used by the Desktop Agent to decide which icon is the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n#### Example\n\n```js\n\"icons\": [\n  {\n    \"src\": \"https://app.foo.icon/app_icons/lowres.webp\",\n    \"size\": \"48x48\",\n    \"type\": \"image/webp\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_icons/hd_hi.svg\",\n    \"size\": \"72x72\",\n    \"type\": \"image/svg+xml\"\n  }\n]\n```\n\n#### Properties\n\n#### `src`\n\nThe fully qualified url to the icon.\n\n#### `size`\n\nThe dimensions of the Icon formatted as `<height>x<width>`.\n\n#### `type`\n\nThe media type of the icon. If not provided the Desktop Agent may refer to the src file extension.\n\n#### See also\n\n* [`AppMetadata`](Metadata#appmetadata)\n\n## `Image`\n\n```typescript\ninterface Image {\n  src: string;\n  size?: string;\n  type?: string;\n  label?: string;\n}\n```\n\nMetadata relating to a single image at a remote URL, used to represent screenshot images.\n\nAppMetadata includes a screenshots property allowing multiple images to be specified. Various properties may be used by the Desktop Agent to decide which image(s) are the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n#### Example\n\n```js\n\"screenshots\": [\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/dashboard.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Example app dashboard\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/notifications.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Order notifications view\"\n  }\n]\n```\n\n#### Properties\n\n#### `src`\n\nThe fully qualified url to the image.\n\n#### `size`\n\nThe dimensions of the image formatted as `<height>x<width>`.\n\n#### `type`\n\nThe media type of the image. If not provided the Desktop Agent may refer to the src file extension.\n\n#### See also\n\n* [`AppMetadata`](Metadata#appmetadata)\n\n## `ImplementationMetadata`\n\n```ts\ninterface ImplementationMetadata {\n  /** The version number of the FDC3 specification that the implementation\n   *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  readonly fdc3Version: string;\n\n  /** The name of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g.Finsemble, Glue42, OpenFin etc.).\n   */\n  readonly provider: string;\n\n  /** The version of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. 5.3.0).\n   */\n  readonly providerVersion?: string;\n\n  /** Metadata indicating whether the Desktop Agent implements optional features of\n   *  the Desktop Agent API.\n   */\n  readonly optionalFeatures: {\n    /** Used to indicate whether the exposure of 'origninating app metadata' for\n     *  context and intent messages is supported by the Desktop Agent.*/\n    \"OriginatingAppMetadata\": boolean;\n    /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n     *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n     *  the Desktop Agent.*/\n    \"UserChannelMembershipAPIs\": boolean;\n  };\n\n  /** The calling application instance's own metadata, according to the \n   *  Desktop Agent (MUST include at least the `appId` and `instanceId`).\n   */\n  readonly appMetadata: AppMetadata;\n}\n```\n\nMetadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number and the metadata of the calling application according to the desktop agent.\n\n#### See also\n\n* [`AppMetadata`](#appmetadata)\n* [`DesktopAgent.getInfo`](DesktopAgent#getinfo)\n\n## `IntentMetadata`\n\n```ts\ninterface IntentMetadata {\n  /** The unique name of the intent that can be invoked by the raiseIntent call. */\n  readonly name: string;\n\n  /** A friendly display name for the intent that should be used to render UI\n   *  elements.\n   */\n  readonly displayName: string;\n}\n```\n\nThe interface used to describe an intent within the platform.\n\n#### See also\n\n* [`AppIntent.intent`](#appintent)\n\n## `IntentResolution`\n\n```ts\ninterface IntentResolution {\n\n  /** Identifier for the app instance that was selected (or started) to resolve\n   *  the intent. `source.instanceId` MUST be set, indicating the specific app \n   *  instance that received the intent.\n   */\n  readonly source: AppIdentifier;\n\n  /** The intent that was raised. May be used to determine which intent the user\n   *  chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  readonly intent: string;\n\n  /** The version number of the Intents schema being used.\n   */\n  readonly version?: string;\n  \n  /** Retrieves a promise that will resolve to either `Context` data returned \n   *  by the application that resolves the raised intent or a `Channel` \n   *  established and returned by the app resolving the intent. \n   * \n   *  A `Channel` returned MAY be of the `PrivateChannel` type. The \n   *  client can then `addContextListener()` on that channel to, for example, \n   *  receive a stream of data.\n   * \n   *  If an error occurs (i.e. an error is thrown by the handler function,\n   *  the promise it returns is rejected, or the promise resolved to an invalid \n   *  type) then the Desktop Agent MUST reject the promise returned by the \n   *  `getResult()` function of the `IntentResolution` with a string from\n   *  the `ResultError` enumeration.\n   */\n   getResult(): Promise<IntentResult>;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n\n#### Examples\n\n```js\n// Resolve a \"Chain\" type intent\nlet resolution = await agent.raiseIntent(\"intentName\", context);\n\n// Use metadata about the resolving app instance to target a further intent\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //Some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err) { ... }                                    \n                                               \n//Resolve a \"Client-Service\" type intent with a data or channel response\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n    const result = await resolution.getResult();\n    if (result && result.broadcast) { //detect whether the result is Context or a Channel\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\n    } else if (result){\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n    } else {\n        console.error(`${resolution.source} didn't return anything`);\n    }\n} catch(error) {\n    console.error(`${resolution.source} returned an error: ${error}`);\n}\n```\n\n#### See also\n\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`AppIdentifier`](Types#appidentifier)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/PrivateChannel.md",
    "content": "---\nsidebar_label: PrivateChannel\ntitle: PrivateChannel\nhide_title: true\noriginal_id: PrivateChannel\n---\n# `PrivateChannel`\n\nObject representing a private context channel, which is intended to support secure communication between applications, and extends the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n```ts\ninterface  PrivateChannel extends Channel {\n  // methods\n  onAddContextListener(handler: (contextType?: string) => void): Listener;\n  onUnsubscribe(handler: (contextType?: string) => void): Listener;\n  onDisconnect(handler: () => void): Listener;\n  disconnect(): void;\n}\n```\n\n#### See also\n\n- [`Channel`](Channel)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## Examples\n\n### 'Server-side' example:\n\nThe intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextlistener()` on that channel, the intent app receives notice via the handler added with `onAddContextListener()` and knows that the client is ready to start receiving quotes.\n\nThe Desktop Agent knows that a channel is being returned by inspecting the object returned from the handler (e.g. check constructor or look for private member).\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses.\n\n```typescript\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const channel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = channel.onAddContextListener((contextType) => {\n        // broadcast price quotes as they come in from our quote feed\n        feed.onQuote(symbol, (price) => {\n            channel.broadcast({ type: \"price\", price});\n        });\n    });\n\n    // This gets called when the remote side calls Listener.unsubscribe()\n    const unsubscriberListener = channel.onUnsubscribe((contextType) => {\n        feed.stop(symbol);\n    });\n\n    // This gets called if the remote side closes\n    const disconnectListener = channel.onDisconnect(() => {\n        feed.stop(symbol);\n    });\n\n    return channel;\n});\n```\n\n### 'Client-side' example:\n\nThe 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. A listener may also be to clear up if the 'server-side' disconnects from the stream. \n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses.\n\n```javascript\ntry {\n    const resolution3 = await fdc3.raiseIntent(\"QuoteStream\", { type: \"fdc3.instrument\", id : { ticker: \"AAPL\" } });\n    try {\n            const result = await resolution3.getResult();\n            //check that we got a result and that it's a channel\n            if (result && result.addContextListener) {\n                const listener = result.addContextListener(\"price\", (quote) => console.log(quote));\n                \n                //if it's a PrivateChannel\n                if (result.onDisconnect) {\n                    result.onDisconnect(() => {\n                            console.warn(\"Quote feed went down\");\n                    });\n\n                    // Sometime later...\n                    listener.unsubscribe();\n                }\n        } else {\n            console.warn(`${resolution3.source} did not return a channel`);\n        }\n    } catch(channelError) {\n            console.log(`Error: ${resolution3.source} returned an error: ${channelError}`);\n    }\n    } catch (resolverError) {\n    console.error(`Error: Intent was not resolved: ${resolverError}`);\n    }\n```\n\n## Methods\n\n### `onAddContextListener`\n\n```ts\nonAddContextListener(handler: (contextType?: string) => void): Listener;\n```\n\nAdds a listener that will be called each time that the remote app invokes addContextListener on this channel.\n\nDesktop Agents MUST call this for each invocation of addContextListener on this channel, including those that occurred before this handler was registered (to prevent race conditions).\n\n#### See also\n\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n### `onUnsubscribe`\n\n```ts\nonUnsubscribe(handler: (contextType?: string) => void): Listener;\n```\n\nAdds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added.\n\nDesktop Agents MUST call this when disconnect() is called by the other party, for each listener that they had added.\n\n#### See also\n\n- [`Listener`](Types#listener)\n\n### `onDisconnect`\n\n```ts\nonDisconnect(handler: () => void): Listener;\n```\n\nAdds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called. This is in addition to calls that will be made to onUnsubscribe listeners.\n\n#### See also\n\n- [`disconnect`](#disconnect)\n\n### `disconnect`\n\n```ts\ndisconnect(): void;\n```\n\nMay be called to indicate that a participant will no longer interact with this channel.\n\nAfter this function has been called, Desktop Agents SHOULD prevent apps from broadcasting on this channel and MUST automatically call Listener.unsubscribe() for each listener that they've added (causing any `onUnsubscribe` handler added by the other party to be called) before triggering any onDisconnect handler added by the other party.\n\n#### See also\n\n- [`onUnsubscribe`](#onunsubscribe)\n- [`Listener`](Types#listener)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/ref/Types.md",
    "content": "---\ntitle: Types\noriginal_id: Types\n---\n\nFDC3 API operations make use of several type declarations.\n\n## `AppIdentifier`\n\nIdentifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.\nWill always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc..\nIf the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id.\n\n```ts\ninterface AppIdentifier {\n  /** The unique application identifier located within a specific application\n   *  directory instance. An example of an appId might be 'app@sub.root'.\n   */\n  readonly appId: string;\n  \n  /** An optional instance identifier, indicating that this object represents a\n   *  specific instance of the application described.\n   */\n  readonly instanceId?: string;\n}\n```\n\n#### See also\n\n* [`AppMetadata`](Metadata#appmetadata)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`IntentResolution`](Metadata#intentresolution)\n\n## `Context`\n\n```typescript\ninterface Context {\n  id?: { [key: string]: string };\n  name?: string;\n  type: string;\n}\n```\n\nThe base interface that all contexts should extend: a context data object adhering to the [FDC3 Context Data specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n#### See also\n\n* [`ContextHandler`](#contexthandler)\n* [`DesktopAgent.open`](DesktopAgent#open)\n* [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n* [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n* [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n* [`Channel.broadcast`](Channel#broadcast)\n* [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `ContextHandler`\n\n```typescript\ntype ContextHandler = (context: Context, metadata?: ContextMetadata) => void;\n```\n\nDescribes a callback that handles a context event. Optional metadata about the context message, including the app that originated the message, may be provided.\n\nUsed when attaching listeners for context broadcasts.\n\nOptional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n#### See also\n\n* [`Context`](#context)\n* [`ContextMetadata`](Metadata#contextmetadata)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `IntentHandler`\n\n```typescript\ntype IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise<IntentResult> | void;\n```\n\nDescribes a callback that handles a context event and may return a promise of a Context or Channel object to be returned to the application that raised the intent.\n\nUsed when attaching listeners for raised intents.\n\nOptional metadata about the intent & context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n#### See also\n\n* [`Context`](#context)\n* [`ContextMetadata`](Metadata#contextmetadata)\n* [`PrivateChannel`](PrivateChannel)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `IntentResult`\n\n```typescript\ntype IntentResult = Context | Channel | void;\n```\n\nDescribes results that an Intent handler may optionally return that should be communicated back to the app that raised the intent, via the [`IntentResolution`](Metadata#intentresolution).\n\nRepresented as a union type in TypeScript, however, this type may be rendered as an interface in other languages that both the `Context` and `Channel` types implement, allowing either to be returned by an `IntentHandler`.\n\n:::info\n\nThe original release of FDC3 2.0 contained an error in the `IntentResult` type, which omitted `void` as a valid return type. It was intended that an `IntentHandler` be able to return either `void` or a Promise that resolves to `void` and, as these are valid results, no error should be thrown by `IntentResolution.getResult()`. This was corrected in FDC3 2.1 and retrospectively corrected in FDC3 2.0.\n\n:::\n\n#### See also\n\n* [`Context`](#context)\n* [`Channel`](Channel)\n* [`PrivateChannel`](PrivateChannel)\n* [`IntentHandler`](#intenthandler)\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`IntentResolution`](Metadata#intentresolution)\n\n## `Listener`\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\n\n```typescript\ninterface Listener {\n  unsubscribe(): void;\n}\n```\n\n### `unsubscribe`\n\n```ts\nunsubscribe(): void;\n```\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n#### See also\n\n* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n* [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n* [`Channel.addContextListener`](Channel#addcontextlistener)\n* [`ContextHandler`](Types#contexthandler)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/api/spec.md",
    "content": "---\nsidebar_label: Overview\ntitle: API Overview 2.0\noriginal_id: spec\n---\n\nThe role of FDC3 API is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications, standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe following sections examine the API's use-cases and core concepts. The APIs a fully defined in both subsequent pages of this Part and a full set of TypeScript definitions in the [src](https://github.com/finos/FDC3/tree/main/src/api) directory of the [FDC3 GitHub repository](https://github.com/finos/FDC3/).\n\n## Components\n\n### Desktop Agent\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- Finsemble\n- Glue42\n- OpenFin\n- Refinitiv Eikon\n\nAn FDC3-compliant Desktop Agent exposes an FDC3 standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n### Application\n\nAn application is any endpoint on the desktop that is:\n\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of endpoints include:\n\n- Native Applications\n- Web Applications\n- Headless “services” running on the desktop\n\n## Desktop Agent Implementation\n\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A Desktop Agent MUST provide implementations for the following interfaces:\n\n- [`DesktopAgent`](ref/DesktopAgent)\n- [`Channel`](ref/Channel)\n- [`PrivateChannel`](ref/PrivateChannel)\n- [`Listener`](ref/Types#listener)\n\nOther interfaces defined in the spec are not critical to define as concrete types.  Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.\n\n### API Access\n\nThe FDC3 API can be made available to an application through a number of different methods.  In the case of web applications, a Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means.\n\nThe global `window.fdc3` must only be available after the API is ready to use. To enable applications to avoid using the API before it is ready, implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use. Implementations should first check for the existence of the FDC3 API and add a listener for this event if it is not found:\n\n```js\nfunction fdc3Stuff() {\n  // Make fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Stuff();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Stuff);\n}\n```\n\n### Standards vs. Implementation\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n### Inter-Agent Communication\n\nA goal of FDC3 standards is that applications running in different Desktop Agent contexts on the same desktop would be able to interoperate.  And that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\nDesktop Agent interop is supported by common standards for APIs for App discovery and launching.  So, an App in one Desktop Agent context would not need to know a different syntax to call an App in another Desktop Agent context.\n\nAn actual connection protocol between Desktop Agents is not currently available in the FDC3 standard, but work on creating one for a future version of the standard is underway (see [GitHub discussion #544](https://github.com/finos/FDC3/discussions/544) for details).\n\n### Desktop Agent API Standard Compliance\n\nAn FDC3 Standard compliant Desktop Agent implementation **MUST**:\n\n- Provide the FDC3 API to web applications via a global accessible as [`window.fdc3`](#api-access).\n- Provide a global [`fdc3Ready`](#api-access) event that is fired when the API is ready for use.\n- Provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to `raiseIntentForContext` that return multiple options), such as a resolver UI.\n  - Intent resolution MUST take into account any specified input or return context types\n  - Requests for resolution to apps returning a channel MUST include any apps that are registered as returning a channel with a specific type.\n- Return (JavaScript or platform appropriate) Error Objects with messages from the [`ChannelError`](ref/Errors#channelerror), [`OpenError`](ref/Errors#openerror), [`ResolveError`](ref/Errors#resolveerror) and [`ResultError`](ref/Errors#resulterror) enumerations as appropriate.\n- Accept as input and return as output data structures that are compatible with the interfaces defined in this Standard.\n- Include implementations of the following [Desktop Agent](ref/DesktopAgent) API functions, as defined in this Standard:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener)\n  - [`addIntentListener`](ref/DesktopAgent#addintentlistener)\n  - [`broadcast`](ref/DesktopAgent#broadcast)\n  - [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel)\n  - [`findInstances`](ref/DesktopAgent#findinstances)\n  - [`findIntent`](ref/DesktopAgent#findintent)\n  - [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n  - [`getInfo`](ref/DesktopAgent#getinfo)\n  - [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel)\n  - [`getUserChannels`](ref/DesktopAgent#getuserchannels)\n  - [`open`](ref/DesktopAgent#open)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext)\n- Provide an ID for each [`PrivateChannel`](ref/PrivateChannel) created via [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel) and prevent them from being retrieved via [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) by ID.\n- Only require app directories that they connect to to have implemented only the minimum requirements specified in the [App Directory API Part](../app-directory/spec) of this Standard.\n- Provide details of whether they implement optional features of the Desktop Agent API in the `optionalFeatures` property of the [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned by the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function.\n\nAn FDC3 Standard compliant Desktop Agent implementation **SHOULD**:\n\n- Support connection to one or more App Directories meeting the [FDC3 App Directory Standard](../app-directory/overview).\n- Qualify `appId` values received from an app directory with the hostname of the app directory server (e.g. `myAppId@name.domain.com`) [as defined in the app directory standard](../app-directory/overview#application-identifiers).\n- Allow applications to register an [`IntentHandler`](ref/Types#intenthandler) for particular Intent and Context type pairs by providing `interop.intents.listensFor` metadata in their AppD record.\n- Adopt the [recommended set of User channel definitions](#recommended-user-channel-set).\n- Ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.\n- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.\n- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.\n\nAn FDC3 Standard compliant Desktop Agent implementation **MAY**:\n\n- Make the Desktop Agent API available through modules, imports, or other means.\n- Support multiple routes for registration of an [`IntentHandler`](ref/Types#intenthandler) by an app to be considered during Intent resolution, including dynamic registration of apps at runtime.\n- Implement the following OPTIONAL [Desktop Agent](ref/DesktopAgent) API functions:\n  - [`joinUserChannel`](ref/DesktopAgent#joinuserchannel)\n  - [`leaveCurrentChannel`](ref/DesktopAgent#leavecurrentchannel)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n- Implement the following deprecated API functions:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener-deprecated) (without a contextType argument)\n  - [`getSystemChannels`](ref/DesktopAgent#getsystemchannels-deprecated) (renamed getUserChannels)\n  - [`joinChannel`](ref/DesktopAgent#joinchannel-deprecated) (renamed joinUserChannel)\n  - [`open`](ref/DesktopAgent#open-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext-deprecated) (deprecated version that addresses apps via `name` field)\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Functional Use Cases\n\n### Open an Application\n\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Requesting Functionality From Another App\n\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3 and is implemented via the raising of [intents](../intents/spec), which represent a desired action, to be performed with a [context](../context/spec) supplied as input.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).  Currently, this is the primary focus in FDC3.\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client. Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n### Send/broadcast Context\n\nOn the financial desktop, applications often want to broadcast [context](../context/spec) to any number of applications.  Context sharing needs to support different groupings of applications, which is supported via the concept of 'channels', over which context is broadcast and received by other applications listening to the channel.  \n\nIn some cases, an application may want to communicate with a single application or service and to prevent other applications from participating in the communication. For single transactions, this can instead be implemented via a raised intent, which will be delivered to a single application that can, optionally, respond with data. Alternatively, it may instead respond with a [`Channel`](ref/Channel) or [`PrivateChannel`](ref/PrivateChannel) over which a stream of responses or a dialog can be supported.\n\n### Retrieve Metadata about the Desktop Agent implementation\n\nAn application may wish to retrieve information about the version of the FDC3 Standard supported by a Desktop Agent implementation and the name of the implementation provider.\n\nSince version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.:\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent('ViewChart', context);\n}\n```\n\nThe [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n```\n\n### Reference apps or app instance(s) and retrieve their metadata\n\nTo construct workflows between applications, you need to be able to reference specific applications and instances of those applications.\n\nFrom version 2.0 of the FDC3 Standard, Desktop Agent functions that reference or return information about other applications do so via an [`AppIdentifier`](ref/Types#appidentifier) type. [`AppIdentifier`](ref/Types#appidentifier) references specific applications via an `appId` from an [App Directory](../app-directory/overview) record and instances of that application via an `instanceId` assigned by the Desktop Agent.\n\nAdditional metadata for an application can be retrieved via the [`fdc3.getAppMetadata(appIdentifier)`](ref/DesktopAgent#getappmetadata) function, which returns an [`AppMetadata`](ref/Metadata#appmetadata) object. The additional metadata may include a title, description, icons, etc., which may be used for display purposes.\n\nIdentifiers for instances of an application may be retrieved via the [`fdc3.findInstances(appIdentifier)`](ref/DesktopAgent#findinstances) function.\n\n## Raising Intents\n\nRaising an Intent is a method for an application to request functionality from another application and, if desired, defer the discovery and launching of the destination app to the Desktop Agent.\n\n### Intents and Context\n\nWhen raising an intent a specific context is provided as input. The type of the provided context may determine which applications can resolve the intent.\n\nA context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents.\n\nTo raise an intent without a context, use the [`fdc3.nothing`](../context/ref/Nothing) context type. This type exists so that applications can explicitly declare that they support raising an intent without a context (when registering an `IntentHandler` or in an App Directory).\n\nAs an alternative to raising a specific intent, you may also raise an unspecified intent with a known context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent and then to raise it with the specified context for resolution.\n\n### Intent Results\n\nAn optional [`IntentResult`](ref/Types#intentresult) may also be returned as output by an application handling an intent. Results may be a single `Context` object, a `Channel` that may be used to send a stream of responses, or `void` (no result). The [`PrivateChannel`](ref/PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via [raising an intent](ref/DesktopAgent#raiseintent).\n\nFor example, an application handling a `CreateOrder` intent might return a context representing the order and including an ID, allowing the application that raised the intent to make further calls using that ID.\n\nAn optional result type is also supported when programmatically resolving an intent via [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext).\n\n### Resolvers\n\nSuccessful delivery of an intent depends first upon the Desktop Agent's ability to \"resolve the intent\" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentByContext`](ref/DesktopAgent#findintentsbycontext) and then raise the intent with a specific target application, e.g.:\n\n```js\n// Find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Find apps to resolve an intent and return a specified context type\nconst appIntent = await fdc3.findIntent(\"ViewContact\", context, \"fdc3.contact\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  const result = await resolution.getResult();\n  console.log(`${resolution.source} returned ${JSON.stringify(result)}`);\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n\n//Find apps to resolve an intent and return a channel\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", context, \"channel\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  const result = await resolution.getResult();\n  if (result && result.addContextListener) {\n    result.addContextListener(null, (context) => { \n      console.log(`received context: ${JSON.stringify(context)}`); \n    });\n  } else {\n    console.log(`${resolution.source} didn't return a channel! Result: ${JSON.stringify(result)}`);\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n\n//Find apps that can perform any intent with the specified context\nconst appIntents = await fdc3.findIntentByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]);\n```\n\nResult context types requested are represented by their type name. A channel may be requested by passing the string `\"channel\"` or a channel that returns a specific type via the syntax `\"channel<contextType>\"`, e.g. `\"channel<fdc3.instrument>\"`. Requesting intent resolution to an app returning a channel MUST include apps that are registered as returning a channel with a specific type.\n\n### Intent Resolution\n\nRaising an intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n#### Resolve\n\n- Intent was resolved unambiguously and the receiving app was launched successfully (if necessary).\n- Intent was ambiguous, a resolution was chosen by the end user, and the chosen application was launched successfully.\n\n#### Reject\n\n- No app matching the intent and context (if specified) was found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n#### Resolution Object\n\nIf the raising of the intent resolves (or rejects), a standard [`IntentResolution`](ref/Metadata#intentresolution) object will be passed into the resolver function with details of the application that resolved the intent and the means to access any results subsequently returned.\n\nFor example, to raise a specific intent:\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n}\ncatch (err){ ... }\n```\n\nor to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog:\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntentForContext(context);\n  if (resolution.data) {\n    const orderId = resolution.data.id;\n  }\n}\ncatch (err){ ... }\n```\n\nUse metadata about the resolving app instance to target a further intent\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err) { ... }\n```\n\nRaise an intent and retrieve either data or a channel from the IntentResolution:\n\n```js\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  /* Detect whether the result is Context or a Channel by checking for properties unique to Channels. */\n  if (result && result.broadcast) { \n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`);\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a data error: ${error}`);\n}\n```\n\n### Register an Intent Handler\n\nApplications need to let the system know the intents they can support.  Typically, this SHOULD be done via registration with an [App Directory](../app-directory/spec) by providing `interop.intents.listensFor` metadata. However, Desktop Agent implementations MAY support dynamic registration of an [`IntentHandler`](ref/Types#intenthandler) by an app at runtime (for example, when they add an `IntentListener` via the API) to allow for ad-hoc registration which may be helpful at development time.  Although dynamic registration is not part of this specification, a Desktop Agent agent MAY choose to support any number of registration paths.\n\nWhen an instance of an application is launched, it is expected to add an [`IntentHandler`](ref/Types#intenthandler) function to the Desktop Agent for each intent it has registered by calling the [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) function of the Desktop Agent. Doing so allows the Desktop Agent to pass incoming intents and contexts to that instance of the application. Hence, if the application instance was spawned in response to the raised intent, then the Desktop Agent must wait for the relevant intent listener to be added by that instance before it can deliver the intent and context to it. In order to facilitate accurate error responses, calls to `fdc3.raiseIntent` should not return an `IntentResolution` until the intent handler has been added and the intent delivered to the target app.\n\n### Originating App Metadata\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered intent handlers. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n\n### Compliance with Intent Standards\n\nIntents 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.\n\nIt is expected that App Directories SHOULD also curate listed apps and ensure that they are complying with declared intents.\n\n## Context Channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\n### Types of Channel\n\nThere are three types of channels, which have different visibility and discoverability semantics:\n\n1. **User channels**, which:\n    - facilitate the creation of user-controlled context links between applications (often via the selection of a color channel),\n    - are created and named by the desktop agent,\n    - are discoverable (via the [`getUserChannels()`](ref/DesktopAgent#getuserchannels) API call),\n    - can be 'joined' (via the [`joinUserChannel()`](ref/DesktopAgent#joinuserchannel) API call).\n\n    :::note\n    Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels).\n    :::\n\n    :::note\n    Earlier versions of FDC3 included the concept of a 'global' system channel\n    which was deprecated in FDC3 1.2 and removed in FDC3 2.0.\n    :::\n\n2. **App channels**, which:\n    - facilitate developer controlled messaging between applications,\n    - are created and named by applications (via the [`getOrCreateChannel()`](ref/DesktopAgent#getorcreatechannel) API call),\n    - are not discoverable,\n    - are interacted with via the [Channel API](ref/Channel) (accessed via the desktop agent [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API call)\n\n3. **Private** channels, which:\n    - facilitate private communication between two parties,\n    - have an auto-generated identity and can only be retrieved via a raised intent.\n\nChannels are interacted with via `broadcast` and `addContextListener` functions, allowing an application to send and receive Context objects via the channel. For User channels, these functions are provided on the Desktop Agent, e.g. [`fdc3.broadcast(context)`](ref/DesktopAgent#broadcast), and apply to channels joined via [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel). For App channels, a channel object must be retrieved, via [`fdc3.getOrCreateChannel(channelName)`](ref/DesktopAgent#getorcreatechannel), which provides the functions, i.e. [`myChannel.broadcast(context)`](ref/Channel#broadcast) and [`myChannel.addContextListener(context)`](ref/Channel#addcontextlistener). For `PrivateChannels`, a channel object must also be retrieved, but via an intent raised with [`fdc3.raiseIntent(intent, context)`](ref/DesktopAgent#raiseintent) and returned as an [`IntentResult`](ref/Types#intentresult).\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are also listening on the channel.\n\n### Joining User Channels\n\nApps can join *User channels*.  An app can only be joined to one User channel at a time.  \n\nWhen an app is joined to a User channel, calls to [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be routed to that channel and listeners added through [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will receive context broadcasts from other apps also joined to that channel. If an app is not joined to a User channel [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be a no-op and handler functions added with  [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will not receive any broadcasts. However, apps can still choose to listen and broadcast to specific channels (both User and App channels) via the methods on the [`Channel`](ref/Channel) class.\n\nWhen an app joins a User channel, or adds a context listener when already joined to a channel, it will automatically receive the current context for that channel.\n\nIt is possible that a call to join a User channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinUserChannel()`](ref/DesktopAgent#joinuserchannel), [`fdc3.getCurrentChannel()`](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).\n\nThere SHOULD always be a clear UX indicator of what channel an app is joined to.\n\n#### Examples\n\nTo find a User channel, one calls:\n\n```js\n// returns an array of channels\nconst allChannels = await fdc3.getUserChannels();\nconst redChannel = allChannels.find(c => c.id === 'red');\n```\n\nTo join a User channel, one calls:\n\n```js\nfdc3.joinUserChannel(redChannel.id);\n```\n\nCalling `fdc3.broadcast` will now route context to the joined channel.\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n\n  > Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels). The `joinChannel` function was also renamed to `joinUserChannel` to clarify that it is only intended to be used to join 'user', rather than 'app', channels.\n\n### Recommended User Channel Set\n\nDesktop Agent implementations SHOULD use the following set of channels, to enable a consistent user experience across different implementations. Desktop Agent implementation MAY support configuration of the user channels.\n\n:::note\nFuture versions of the FDC3 Standard may support connections between desktop agents, where differing user channel sets may cause user experience issues.\n:::\n\n```javascript\nconst recommendedChannels = [\n  {\n    id: 'fdc3.channel.1',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 1',\n      color: 'red',\n      glyph: '1',\n    },\n  },\n  {\n    id: 'fdc3.channel.2',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 2',\n      color: 'orange',\n      glyph: '2',\n    },\n  },\n  {\n    id: 'fdc3.channel.3',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 3',\n      color: 'yellow',\n      glyph: '3',\n    },\n  },\n  {\n    id: 'fdc3.channel.4',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 4',\n      color: 'green',\n      glyph: '4',\n    },\n  },\n  {\n    id: 'fdc3.channel.5',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 5',\n      color: 'cyan',\n      glyph: '5',\n    },\n  },\n  {\n    id: 'fdc3.channel.6',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 6',\n      color: 'blue',\n      glyph: '6',\n    },\n  },\n  {\n    id: 'fdc3.channel.7',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 7',\n      color: 'magenta',\n      glyph: '7',\n    },\n  },\n  {\n    id: 'fdc3.channel.8',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 8',\n      color: 'purple',\n      glyph: '8',\n    },\n  },\n];\n```\n\n### Direct Listening and Broadcast on Channels\n\nWhile joining User channels (using [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel)) automates a lot of the channel behavior for an app, it has the limitation that an app can only be 'joined' to one channel at a time.  However, an app may instead retrieve an App [`Channel`](ref/Channel) Object via the [`fdc3.getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API, create a [`PrivateChannel`](ref/PrivateChannel) via the [`fdc3.createPrivateChannel`](ref/DesktopAgent#createprivatechannel) API, or by raising an intent that returns a channel created by another app. The `Channel` object may then be used to listen to and broadcast on that channel directly using the [`Channel.addContextListener`](ref/Channel#addcontextlistener) and the [`Channel.broadcast`](ref/Channel#broadcast) APIs. FDC3 imposes no restriction on adding context listeners or broadcasting to multiple channels.\n\n### App Channels\n\nApp Channels are topics dynamically created by applications connected via FDC3. For example, an app may create a named App Channel to broadcast data or status that is specific to that app to other apps that know to connect to the channel with that name.\n\nTo get (or create) a [`Channel`](ref/Channel) reference, then interact with it:\n\n```js\nconst appChannel = await fdc3.getOrCreateChannel('my_custom_channel');\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nawait appChannel.addContextListener(null, context => {...});\n// broadcast to the channel\nawait appChannel.broadcast(context);\n```\n\nAn app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to.\n\n```js\n// check for current fdc3 channel\nlet joinedChannel = await fdc3.getCurrentChannel()\n//current channel is null, as the app is not currently joined to a channel\n\n//add a context listener for channels we join\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n//retrieve an App channel and add a listener that is specific to that channel\nconst myChannel = await fdc3.getOrCreateChannel('my_custom_channel');\nconst myChannelListener = await myChannel.addContextListener(null, context => { ... });\n\nfdc3.joinChannel('blue')\njoinedChannel = await fdc3.getCurrentChannel()\n//current channel is now the 'blue' channel\n```\n\nif another application broadcasts to \"my_custom_channel\" (by retrieving it and broadcasting to it via `myChannel.broadcast()`) then the broadcast will be received by the specific listener (`myChannelListener`) but NOT by the listener for joined channels (`listener`).\n\n### Private Channels\n\nA [`PrivateChannel`](ref/PrivateChannel) is created to support the return of a stream of responses from a raised intent, or private dialog between two applications.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\nThe `PrivateChannel` type also supports synchronization of data transmitted over returned channels. They do so by extending the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\n### Broadcasting and listening for multiple context types\n\nThe [Context specification](../context/spec#assumptions) recommends that complex context objects are defined using simpler context types for particular fields. For example, a `Position` is composed of an `Instrument` and a holding amount. This leads to situations where an application may be able to receive or respond to context objects that are embedded in a more complex type, but not the more complex type itself. For example, a pricing chart might respond to an `Instrument` but doesn't know how to handle a `Position`.\n\nTo facilitate context linking in such situations it is recommended that applications `broadcast` each context type that other apps (listening on a User Channel or App Channel) may wish to process, starting with the simpler types, followed by the complex type. Doing so allows applications to filter the context types they receive by adding listeners for specific context types - but requires that the application broadcasting context make multiple broadcast calls in quick succession when sharing its context.\n\n### Originating App Metadata\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered context handlers on all types of channel. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/app-directory/overview.md",
    "content": "---\nsidebar_label: Overview\ntitle: App Directory Overview 2.0\noriginal_id: overview\n---\n\nAn application directory (appD) is a structured repository of information about apps that can be used in an FDC3-enabled desktop. In other words, it’s a convenient way of storing and managing metadata about apps in your ecosystem.\n\nThe application metadata stored in appD records may include: the app name, type, details about how to run the application, its icons, publisher, support contact details and so on. It may also include links to or embed manifest formats defined elsewhere, such as proprietary manifests for launching the app in a container product or a Web Application Manifest (as [defined by the W3C](https://www.w3.org/TR/appmanifest/)).\n\nAll this information is readily available in one place and can be used both to populate a launcher or app catalog UI for your users, and by the Desktop Agent managing the apps on your desktop. In fact, if your desktop platform supports the FDC3 standard, appD is the primary way that the FDC3 Desktop Agent implementation should receive the details about apps available to run on your desktop. Conversely, if an app is not listed in appD, the Desktop Agent can’t ensure its participation in context sharing or use it to resolve intents.\n\n## Advantages\n\nUsing appD offers many advantages both for financial institutions running an FDC3-enabled desktop container and for vendors that provide FDC3-compliant apps:\n\n### For the user\n\n#### Easier to Find App Info\n\nYour appD is the one place to collect all the information about apps. The more apps you have, the more you’ll appreciate the convenience of not having to chase down details about each. This is particularly important for large institutions with multiple desks.\n\n#### Human Readable\n\nAppD has two types of users. One is the Desktop Agent, but the other is humans administrating and using the smart desktop at your organization. Hence, an appD contains information about apps in both machine- and human-readable forms. For example, it includes both unique identifiers for apps that are used to refer to them in code and human-friendly app names, icons, descriptions and tooltips necessary to populate a launcher menu or app catalog user interface for your users.\n\n#### Apps are Discoverable\n\nFor large institutions, it can be difficult to keep track of all the apps (developed both in-house and by vendors), since a typical desktop could have many. Users can search appD to discover the apps they need. An app might already reside on their system or be available to them over the internet, but if they don’t have a way to search the apps available to them, they won’t be able to find it. An appD provides a way for users to discover the apps they need.\n\nAn appD makes it possible to discover info about apps that reside on various domains, not just the one domain the appD itself is hosted on. In addition, you can find details about how to launch the apps in multiple, diverse environments. This is a different use-case to, for example, the [W3C's Web App Manifest](https://www.w3.org/TR/appmanifest/), which is hosted on the same domain as the app, is limited to web apps, and is generally used to 'install' an app that the user has already accessed.\n\n#### Updating Apps\n\nTypically, software evolves over time. The app versions you are running today will not be the same ones you need tomorrow. Therefore, you will need to upgrade apps periodically. Very few people look forward to upgrading, but appD and web deployment can make it easier for you. To roll out a new version of your app, either update the existing entry for it in appD or add a new entry for that version (allowing users to select the version they will use).\n\n#### Agent-agnostic\n\nAs a part of the FDC3 standard, appD isn't tied to any specific vendor. This is important, as it allows you more flexibility in that you are not tied to any specific container or Desktop Agent implementation. If at any point you want to switch to a different Desktop Agent, the process won’t be prohibitively difficult. The existing appD will work without any additional effort from you, as long as your new Desktop Agent is also FDC3-compliant. This is in contrast with proprietary solutions, where you would have to produce a new configuration and integration for every application.\n\nAppD reduces fragmentation in the market and allows end-users more flexibility in what applications can be included in their desktop.\n\n#### Intent Resolution\n\nAppD provides information to the Desktop Agent on which applications can handle particular [intents](../intents/overview) and the context types they support as input to them. This allows the Desktop Agent to implement an [intent resolver](../api/spec#resolvers) that can launch applications and pass the intent and context to them to operate on, supporting workflows between applications that didn't require prior bilateral agreements between the application providers.\n\n### For an Application Provider\n\nUntil now, we've looked at appD from the perspective of a desktop owner and user. But appD also offers advantages to vendors who develop apps for the financial services desktop.\n\n#### Apps Work Well Together Out-of-the-box\n\nWhen your customers add your FDC3-compliant app to their desktop via an appD record accurately describing it, you can be sure that your app will interoperate with other apps that follow the FDC3 standard. You don’t have to do anything special, or arrange a bilateral agreement with anyone else. The benefit of the open standard is that any app that follows it will work well with any other compliant app.\n\n#### Easy Updates\n\nAs a vendor, you prefer for all your customers to run your latest software. However, many customers will postpone upgrades, sometimes for a long time, because upgrading can be a pain. An advantage of a vendor-hosted appD is that the configuration of an app can be updated at any time and, if your customers need to choose when to upgrade, multiple versions of it can be made available, each with their own configuration. By making it easier for customers to update, you can drive better adoption.\n\n### For the Industry\n\nBy hosting our own appD we can easily combine applications from various providers into one cohesive directory. Alternatively, we can connect to directories from multiple providers (in standardized format) and provide a single view over them. This reduces fragmentation in the market, allows end-users more flexibility in what apps to include in their smart desktop, and obviates the need for vendors to provide application details in diverse formats or for their customers to work out these details for themselves.\n\n## Relationship to Other Standards\n\nThe App Directory's application record is similar to application manifests defined in other standards, in particular the W3C's [Web Application Manifest](https://www.w3.org/TR/appmanifest/). However, the App Directory, and by extension the application record, serve a different set of use-cases specific to application interoperability on financial services desktops, which other standards do not fully address.\n\nWherever possible, FDC3 seeks to draw inspiration from, align itself with and reference other standards - ensuring that conventions and best practices developed by those standards are reused, along with the standard itself (e.g. data formats in ISO standard formats, external links to technology-specific manifest file formats etc.). For a list of standards that FDC3 references, see the [References](../references) page.\n\n## Use Cases\n\nAn application directory provides information about an application's identifiers, publisher details, intents that it supports, and metadata necessary to launch and integrate the application in a Desktop Agent.\n\nThe following provides a summary of use cases.\n\n### Launcher\n\nA Desktop Agent will usually include a user interface allowing the user to select from a set of launchable applications and then allow them to manually launch one. It is also responsible for launching applications necessary to resolve a raised intent. However, it must first retrieve the necessary metadata about the available applications. An app directory provides an endpoint to retrieve a list of the available applications along with their metadata, which may include or link to additional information necessary to launch the application in a specific Desktop Agent.\n\nA launcher will usually be configured with the locations of one or more AppD servers (which is necessary to implement intent resolution), however, as described in the [Service Discovery](#service-discovery) section, a fully qualified application identifier (app1@host.appd.com) may also be used to both locate the appD service and to retrieve the specific application data.\n\n![img](/assets/appd_launcher_embedded.png)\n\n### Aggregated View\n\nThere could be many different appD service instances in the world providing application data zoned to the provider or enterprise deployment. The appD specification allows for unique instances of the service with no requirement to aggregate data or define a structured hierarchy. With this said, a launcher might want to construct an aggregated view of applications from one or more appD instances. In this case, the launcher would be required to retrieve multiple application definitions from one or more appD instances providing a consolidated view of all applications required.\n\nToday, there is no intention to create a single registry of known AppD instances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location.\n\n![img](/assets/appd_launcher_aggregated.png)\n\n### Authentication and Entitlements\n\nThe AppD API specification defines the optional use of an access token to identify the requesting user/launcher and implement authorizations which may affect appD API responses. For example, different subsets of the full list of applications may be returned for different users depending on their role in an organization.  \n\nThe specification does not define or make mandatory any authorizations or roles that a provider or enterprise can define.\n\n## Application Identifiers\n\nApplication Records served by an app directory are each labelled with an identifier, `appId`, which should be unique within the app directory instance and may be used to refer to or retrieve the application's record via the [app directory API](spec). This identifier may be made globally unique through a nested namespace approach and email address construction (`appId@fqdn`) where `@` followed by the app directory instance's host name is appended to it. The resulting globally unique identifier is known as a 'fully qualified application identifier'.\n\nFully qualified appIds may be used to locate the appD instance hosting the application's record. See the [Service Discovery](#service-discovery) section for details.\n\n### Shrinking the URI\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID \"app1@appd.foo.com\" is represented as \"app1\" within the application directory.  As a result a launcher can use a shortened URI construct `\"https://appd.foo.com/api/appd/v2/apps/app1\"` to resolve the application data vs `\"https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com\"`.\n\n## Service Discovery\n\nIn order to support the discovery of applications that can be used with a Desktop Agent, it is necessary to access data stored in one or more app directory instances.\n\n![img](/assets/appd_service_distribution.png)\n\nHowever, in order to do so, you must first discover the location of an app directory service, which you may then use to generate URIs  (e.g. \"https://appd.foo.com/api/appd/v2/app1@appd.foo.com\") to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required.\n\nThree methods for discovering app directory services are defined in this Standard:\n\n  1. **Static configuration:** Statically defined URI records for use within client applications (typically a Desktop Agent implementation) directly.\n  2. **Fully-qualified appID namespace syntax host resolution:** Discovery of the appD location using a fully qualified application ID (appId) domain name.  \n  3. **DNS lookup by domain name:** Discovery of the appD location using a domain name to lookup DNS SRV records identifying the host server location and TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782))\n\nApp directory service host discovery implementations SHOULD support each of these methods and MUST support at least static configuration.\n\n### Static configuration\n\nAs the name implies, a static configuration for an appD service location is defined within a Desktop Agent or launcher application. This is the simplest and most common approach to app directory and application data discovery.\n\n![img](/assets/appd_static_config.png)\n\n### Fully-qualified appID namespace syntax host resolution\n\nAn app directory URI can be constructed using a [fully qualified application ID](overview#application-identifiers) (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application id \"app1\" with a fully qualified identifier of \"app1@appd.foo.com\" an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" MUST resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by:\n\n1. URI protocol is defaulted to `https`, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default `https/443`, but can be overridden by the launcher\n4. URI url is by default `\"/api/appd/(version)/apps\"` . Calls that are made without version MUST automatically default to latest, i.e. `\"/api/appd/apps/app1\"` should return the same result as `\"/api/appd/v2/apps/app1\"`.\n\nThe resulting URI to retrieve application data for \"app1\" would be \"[https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com)\"  \n\n### DNS/SRV Records\n\nAnother approach to support app directory service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an appD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well-known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *service*: the symbolic name of the desired service.  For AppD service, this must be identified as \"**_appd**\"\n- *proto*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *name*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *TTL*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *class*: standard DNS class field (this is always *IN*).\n- *priority*: the priority of the target host, lower value means more preferred.\n- *weight*: A relative weight for records with the same priority, higher value means more preferred.\n- *port*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *target*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record MUST use the following definitions:\n\n- service = **_appd**\n- proto = **_tcp**\n- name = must map to the domain of the application identifier . Example:  the **name** for application identifier **\"app1@appd.foo.com\"** would be **\"appd.foo.com\"**\n\n*AppD service through DNS / SRV records:*\n\n![img](/assets/appd_dns.png)\n\n#### Known domains\n\nAlthough SRV records provide the means of resolving the location of an app directory service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/app-directory/spec.md",
    "content": "---\nsidebar_label: API\ntitle: App Directory API 2.0\noriginal_id: spec\n---\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/2.0/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/2.0/app-directory.yaml\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v2/apps`         | GET    | Retrieve all application definitions\n `/v2/apps/{appId}` | GET    | Retrieve an application defintion\n `/v1/apps`         | POST   | (deprecated v1 API version) Create a new application definition\n `/v1/apps/{appId}` | GET    | (deprecated v1 API version) Retrieve an application defintion\n `/v1/apps/search`  | GET    | (deprecated v1 API version) Retrieve a list of applications\n\nApp Directory implementations MAY extend the list of endpoints to provide other necessary functionality. However, FDC3 Desktop Agent implementations that connect to app directories MUST support connection to app directories that only provide the minimum endpoints listed here.\n\n## App Directory Standard Compliance\n\nAn FDC3 Standard compliant App Directory implementation **MUST**:\n\n* Implement the specified `/v2` endpoints for retrieving app definitions as defined in the [app directory OpenAPI specification](pathname:///schemas/2.0/app-directory.html#tag/Application):\n  * `/v2/apps` (GET)\n  * `/v2/apps/{appId}` (GET)\n* Ensure that `appId` field values assigned to applications are unique within the directory.\n* Ensure that app directory records served meet the minimum requirements specified in the [app directory OpenAPI specification](pathname:///schemas/2.0/app-directory.html#tag/Application)\n* Support retrieval of app directory records via either the raw `appId` (e.g. `myAppId`) or fully-qualified appId (e.g. `myAppId@host.domain.com`) as defined in the [app directory overview](overview#shrinking-the-uri).\n\nAn FDC3 Standard compliant App Directory implementation **SHOULD**:\n\n* Support authentication (where required) via the HTTP Authorization header and Bearer authentication schema (implemented via JWT tokens)\n* Select any `categories` field values from the recommended list.\n* Encourage the use of the `lang` and `localizedVersions` fields in appD records to support localisation and accessibility.\n\nAn FDC3 Standard compliant App Directory implementation **MAY**:\n\n* Support filtering of application records returned by user entitlement, where authentication is enabled.\n* Implement the deprecated `/v1` endpoints provided for backwards compatability with prior version of the standard:\n  * `/v1/apps` (POST)\n  * `/v1/apps/{appId}` (GET)\n  * `/v1/apps/search` (GET)\n* Extend the implementation with additional endpoints.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Chart.md",
    "content": "---\nsidebar_label: Chart\ntitle: Chart\nhide_title: true\noriginal_id: Chart\n---\n# `Chart`\n\nA context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\n\n* A list of instruments for comparison\n* The time period to plot the chart over\n* The style of chart (line, bar, mountain, candle etc.)\n* Other settings such as indicators to calculate, or data representing drawings and annotations\n\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\n\n## Type\n\n`fdc3.chart`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/chart.schema.json\n\n## Details\n\n:::warning\n\nThe `fdc3.timeRange` context type is inconsistently used in FDC3 2.0, occasionally appearing as `fdc3.timerange`. This has been corrected in FDC3 2.1 to always use the camel case form `fdc3.timeRange`.\n\n:::\n\n| Property         | Type            | Required | Example Value        |\n|------------------|-----------------|----------|----------------------|\n| `type`           | string          | Yes      | `'fdc3.chart'`     |\n| `instruments`    | Instrument[]  | Yes      | <pre>[<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.instrument\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"ticker\": \"AAPL\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\},<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.instrument\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"ticker\": \"MSFT\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\}<br/>]</pre> |\n| `range` | TimeRange  | No       | <pre>\\{<br/>&emsp;&emsp;\"type\": \"fdc3.timeRange\",<br/>&emsp;&emsp;\"startTime\": \"2022-03-30T15:44:44+00:00\",<br/>&emsp;&emsp;\"endTime\": \"2022-04-30T23:59:59+00:00\"<br/>\\}</pre>            |\n| `style`    | string  | No       | one of: `'line'`, `'bar'`, `'stacked-bar'`, `'mountain'`, `'candle'`, `'pie'`, `'scatter'`, `'histogram'`, `'heatmap'`, `'custom'`      |\n| `otherConfig`* | object  | No |  `{ /* unstandardized additional config */}`  |\n\n\\* It is common for charts to support other configuration, such as indicators, annotations etc., which do not have standarized formats, but may be included in the `otherConfig` element.\n\n## Example\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: {\n        indicators: [\n            {\n                name: \"ma\",\n                parameters: {\n                    period: 14,\n                    type: \"ema\"\n                }\n            },\n            {\n                name: \"volume\"\n            }\n        ]\n    }\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nOther Types\n\n* [Instrument](Instrument)\n* [TimeRange](TimeRange)\n\nIntents\n\n* [ViewChart](../../intents/ref/ViewChart)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/ChatInitSettings.md",
    "content": "---\nsidebar_label: ChatInitSettings\ntitle: ChatInitSettings\nhide_title: true\noriginal_id: ChatInitSettings\n---\n\n# `ChatInitSettings`\n\nA collection of settings to start a new chat conversation\n\n## Type\n\n`fdc3.chat.initSettings`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/chatInitSettings.schema.json\n\n## Details\n\n| Property                       | Type        | Required | Example Value                                                        |\n| ------------------------------ | ----------- | -------- | -------------------------------------------------------------------- |\n| `type`                         | string      | Yes      | `'fdc3.chat.initSettings'`                                           |\n| `chatName`                     | string      | No       | `'Instrument XYZ'`                                                    |\n| `members`                      | ContactList | No       | ContactList - cf. below                                              |\n| `initMessage`                  | string      | No       | `'Hello!'`                                                           |\n| `options.groupRecipients`      | boolean     | No       | `true`: if false a separate chat will be created for each member     |\n| `options.isPublic`             | boolean     | No       | `true`: the room will be visible to everyone in the chat application |\n| `options.allowHistoryBrowsing` | boolean     | No       | `true`: members will be allowed to browse past messages             |\n| `options.allowMessageCopy`     | boolean     | No       | `true`: members will be allowed to copy/paste messages               |\n| `options.allowAddUser`         | boolean     | No       | `true`: members will be allowed to add other members to the chat     |\n\nIf _members_ or _chatName_ are not provided, the application executing this\nintent is expected to provide a means to enter such information.\n\n## Example\n\n```js\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Chat ABCD',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane@mail.com'\n            }\n        },{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true\n    }\n    initMessage: 'Hello both!'\n}\n\nconst res = fdc3.raiseIntent('StartChat', initSettings);\nconst roomRefs = await res.getResult();\n```\n\n## See Also\n\nOther Types\n\n- [ContactList](ContactList)\n\nIntents\n\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [ViewContact](../../intents/ref/ViewContact)\n\nFINOS Financial Objects\n\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Contact.md",
    "content": "---\nsidebar_label: Contact\ntitle: Contact\nhide_title: true\noriginal_id: Contact\n---\n# `Contact`\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Type\n\n`fdc3.contact`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/contact.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.contact'`  |\n| `name`      | string  | No       | `'Jane Doe'`      |\n| `id.email`  | string  | No       | `'jane@mail.com'` |\n| `id.FDS_ID` | string  | No       | `'ABC123-E'`      |\n\n## Example\n\n```js\nconst contact = {\n    type: \"fdc3.contact\",\n    name: \"Jane Doe\",\n    id: {\n        email: \"jane.doe@mail.com\"\n    }\n}\n\n\nfdc3.broadcast(contact)\n```\n\n## See Also\n\nOther Types\n- [ContactList](ContactList)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/ContactList.md",
    "content": "---\nsidebar_label: ContactList\ntitle: ContactList\nhide_title: true\noriginal_id: ContactList\n---\n# `ContactList`\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nNotes:\n\n- The contact list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.contactList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/contactList.schema.json\n\n## Details\n\n| Property    | Type      | Required | Example Value          |\n|-------------|-----------|----------|------------------------|\n| `type`      | string    | Yes      | `'fdc3.contactList'`   |\n| `id`        | object    | No       | `{ customId: '5576' }` |\n| `name`      | string    | No       | `'My address book'`    |\n| `contacts`  | Contact[] | Yes      | `[contact1, contact2]` |\n\n## Example\n\n```js\nconst contacts = {\n    type: \"fdc3.contactList\",\n    contacts: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.contact\",\n            name: \"John Doe\",\n            id: {\n                email: \"john.doe@mail.com\"\n            }\n        },\n    ]\n}\nfdc3.raiseIntent(\"StartChat\", contacts)\n```\n\n## See Also\n\nOther Types\n- [Contact](Contact)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n\nFINOS Financial Objects\n- [ContactList](https://fo.finos.org/docs/objects/contactlist)"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Context.md",
    "content": "---\nsidebar_label: Context\ntitle: Context\nhide_title: true\noriginal_id: Context\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not \nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/context.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema. \nThe FDC3 [API](../../api/overview) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/overview) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardised FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`. \nFor non-standard types, e.g. those defined and used by a particular organisation, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications\nidentify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\n## See Also\n\nFDC3 Specifications\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Country.md",
    "content": "---\nsidebar_label: Country\ntitle: Country\nhide_title: true\noriginal_id: Country\n---\n# `Country`\n\nA country entity.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement\nis for at least one standardised identifier to be provided.\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardised and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n\n## Type\n\n`fdc3.country`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/country.schema.json\n\n## Details\n\n| Property                 | Type    | Required | Example Value        |\n|--------------------------|---------|----------|----------------------|\n| `type`                   | string  | Yes      | `'fdc3.country'`     |\n| `name`                   | string  | No       | `'Sweden'`           |\n| `id.COUNTRY_ISOALPHA2`   | string  | No       | `'SE'`               |\n| `id.COUNTRY_ISOALPHA3`   | string  | No       | `'SWE'`              |\n| `id.ISOALPHA2` *         | string  | No       | `'SE'`               |\n| `id.ISOALPHA3` *         | string  | No       | `'SWE'`              |\n\n\\* Field names deprecated in FDC3 2.0 in favour of the versions prefixed with `COUNTRY_`.\n## Example\n\n```js\nconst country = {\n    type: \"fdc3.country\",\n    name: \"Sweden\",\n    id: {\n        COUNTRY_ISOALPHA2: \"SE\"\n    }\n}\n\nfdc3.broadcast(country)\n```\n\n## See Also\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n- [Country](https://fo.finos.org/docs/objects/country)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Currency.md",
    "content": "---\nsidebar_label: Currency\ntitle: Currency\nhide_title: true\noriginal_id: Currency\n---\n\n# `Currency`\n\nA context representing an individual Currency. \n\n## Type\n\n`fdc3.currency`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/currency.schema.json\n\n## Details\n\n| Property                | Type    | Required | Example Value     |\n|-------------------------|---------|----------|-------------------|\n| `type`                  | string  | Yes      | `'fdc3.currency'` |\n| `name`                  | string  | No       | `'US Dollar'`     |\n| `id.CURRENCY_ISOCODE` * | string  | Yes      | `'USD'`           |\n\n\\* The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html).\n\n## Example\n\n```js\nconst currency = {\n    type: 'fdc3.currency',\n    name: 'US Dollar',\n    id: {\n        CURRENCY_ISOCODE: \"USD\"\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Email.md",
    "content": "---\nsidebar_label: Email\ntitle: Email\nhide_title: true\noriginal_id: Email\n---\n# `Email`\n\nA collection of information to be used to initiate an email with a Contact or ContactList\n\n## Type\n\n`fdc3.email`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/email.schema.json\n\n## Details\n\n| Property          | Type                                  | Required | Example Value       |\n|-------------------|---------------------------------------|----------|---------------------|\n| `type`            | string                                | Yes      | `'fdc3.email'` |\n| `recipients`      | fdc3.contact or fdc3.contactList      | Yes      | \\{ type: \"fdc3.contact\", name: \"John Doe\", id: \\{ \"email\": \"john@sample.com\"\\}\\} |\n| `subject`         | string                                | No       | `'The information you requested'`            |\n| `textBody`        | string                                | No       | `'Blah, blah, bah`         |\n\n## Example\n\n```js\nconst email = {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n}\n\n\nfdc3.raiseIntent(\"StartEmail\", email)\n```\n\n## See Also\n\nOther Types\n* [Contact](Contact)\n* [ContactList](ContactList)\n\nIntents\n* [StartEmail](../../intents/ref/StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Instrument.md",
    "content": "---\nsidebar_label: Instrument\ntitle: Instrument\nhide_title: true\noriginal_id: Instrument\n---\n# `Instrument`\n\nA financial instrument from any asset class.\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match.\n\nNotes:\n\n- Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified.\nIn general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\n- It is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement\nis for at least one instrument identifier to be provided.\n\n- Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant for stock tickers specifically,\nif the identifier you want to share is not a stock ticker, or one of the other standardised ones, rather define\na property that makes it clear what value it is. This makes it easier for target applications.\n\n## Type\n\n`fdc3.instrument`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/instrument.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value       |\n|-------------|---------|----------|---------------------|\n| `type`      | string  | Yes      | `\"fdc3.instrument\"` |\n| `name`      | string  | No       | `\"Microsoft\"`       |\n| `id.ticker` | string  | No       | `\"MSFT\"`            |\n| `id.BBG`    | string  | No       | `\"MSFT:US\"`         |\n| `id.CUSIP`  | string  | No       | `\"594918104\"`       |\n| `id.FDS_ID` | string  | No       | `\"P8R3C2-R\"`        |\n| `id.FIGI`   | string  | No       | `\"BBG000BPH459\"`    |\n| `id.ISIN`   | string  | No       | `\"US5949181045\"`    |\n| `id.PERMID` | string  | No       | `\"4295907168\"`      |\n| `id.RIC`    | string  | No       | `\"MSFT.OQ\"`         |\n| `id.SEDOL`  | string  | No       | `\"2588173\"`         |\n\n## Example\n\n```js\nconst instrument = {\n    type: \"fdc3.instrument\",\n    name: \"Microsoft\",\n    id: {\n        ticker: \"MSFT\",\n        RIC: \"MSFT.OQ\",\n        ISIN: \"US5949181045\"\n    }\n}\n\nfdc3.joinUserChannel('Channel 1')\nfdc3.broadcast(instrument)\n```\n\n## See Also\n\nOther Types\n\n- [InstrumentList](InstrumentList)\n- [Chart](Chart)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n- [Instrument](https://fo.finos.org/docs/objects/instrument)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/InstrumentList.md",
    "content": "---\nsidebar_label: InstrumentList\ntitle: InstrumentList\nhide_title: true\noriginal_id: InstrumentList\n---\n# `InstrumentList`\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist).\n\nWhen holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type, though.\n\nNotes:\n\n- The instrument list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.instrumentList`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/instrumentList.schema.json\n\n## Details\n\n| Property      | Type         | Required | Example Value                  |\n|---------------|--------------|----------|--------------------------------|\n| `type`        | string       | Yes      | `'fdc3.instrumentList'`        |\n| `name`        | string       | No       | `'Interesting instruments...'` |\n| `id`          | object       | No       | `{ customId: '5464' }`         |\n| `instruments` | Instrument[] | Yes      | `[instrument1, instrument2]`   |\n\n## Example\n\n```js\nconst instruments = {\n    type: \"fdc3.instrumentList\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"MSFT\"\n            }\n        },\n    ]\n}\n\nfdc3.joinUserChannel('Channel 1')\nfdc3.broadcast(instruments)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n- [InstrumentList](https://fo.finos.org/docs/objects/instrumentlist)"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Nothing.md",
    "content": "---\nsidebar_label: Nothing\ntitle: Nothing\nhide_title: true\noriginal_id: Nothing\n---\n# `Nothing`\n\nA type that explicitly represents a lack of context.\n\nNotes:\n\n- Intended to be used in situations where no context is desired. \n- For example:\n  - Raising an intent without context (e.g. opening a blank order form, or chat\n    interface without a contact selected).\n  - Resetting context on a channel (e.g. when context is used to set a filter in\n    other applications a null context might release the filter).\n- An explicit representation of a Null or empty context allows apps to declare support for\n  a lack of context, for example in their intent metadata in an app directory.\n\n## Type\n\n`fdc3.nothing`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/nothing.schema.json\n\n## Example\n\n```js\nconst nullContext = {\n    type: 'fdc3.nothing'\n}\n\nfdc3.joinUserChannel('groupA')\nfdc3.broadcast(nullContext)\n```"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Organization.md",
    "content": "---\nsidebar_label: Organization\ntitle: Organization\nhide_title: true\noriginal_id: Organization\n---\n# `Organization`\n\nAn entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement\nis for at least one specified identifier to be provided.\n\n## Type\n\n`fdc3.organization`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/organization.schema.json\n\n## Details\n\n| Property    | Type    | Required | Example Value             |\n|-------------|---------|----------|---------------------------|\n| `type`      | string  | Yes      | `'fdc3.organization'`     |\n| `name`      | string  | No       | `'Cargill, Incorporated'` |\n| `id.LEI`    | string  | No       | `'QXZYQNMR4JZ5RIRN4T31'`  |\n| `id.PERMID` | string  | No       | `'4296555324'`            |\n| `id.FDS_ID` | string  | No       | `'00161G-E'`              |\n\n## Example\n\n```js\nconst organization = {\n    type: \"fdc3.organization\",\n    name: \"Cargill, Incorporated\",\n    id: {\n        LEI: \"QXZYQNMR4JZ5RIRN4T31\",\n        FDS_ID: \"00161G-E\"\n    }\n}\n\nfdc3.broadcast(organization)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n\nIntents\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n- [Organization](https://fo.finos.org/docs/objects/organization)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Portfolio.md",
    "content": "---\nsidebar_label: Portfolio\ntitle: Portfolio\nhide_title: true\noriginal_id: Portfolio\n---\n# `Portfolio`\n\nA financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this\nwith e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe [Portfolio](Portfolio) type consists of an array of [Position](Position) types, each of which\nrefers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the portfolio can be added, the schema just \nspecifies the minimum contract.\n\n- The portfolio schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.portfolio`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/portfolio.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.portfolio'`        |\n| `id`         | object     | No       | `{ portfolioId: '7381' }` |\n| `name`       | string     | No       | `'My share portfolio'`    |\n| `positions`  | Position[] | Yes      | `[position1, position2]`  |\n\n## Example\n\n```js\nconst portfolio = {\n    type: \"fdc3.portfolio\",\n    positions: [\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"AAPL\"\n                }\n            },\n            holding: 2000000\n        },\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"MSFT\"\n                }\n            },\n            holding: 1500000\n        },\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"IBM\"\n                }\n            },\n            holding: 3000000\n        }\n    ]\n}\nfdc3.raiseIntent(\"ViewAnalysis\", portfolio)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Position.md",
    "content": "---\nsidebar_label: Position\ntitle: Position\nhide_title: true\noriginal_id: Position\n---\n# `Position`\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good\nexample of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents\nmultiple holdings in a combination of instruments.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the position can be added, the schema just \nspecifies the minimum contract.\n\n- The position schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.position`\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/position.schema.json\n\n## Details\n\n| Property     | Type       | Required | Example Value                      |\n|--------------|------------|----------|------------------------------------|\n| `type`       | string     | Yes      | `'fdc3.position'`                  |\n| `id`         | object     | No       | `{ positionId: '6475' }`           |\n| `name`       | string     | No       | `'My Apple shares'`                |\n| `holding`    | number     | Yes      | `2000000`                          |\n| `instrument` | Instrument | Yes      | `{ type: 'fdc3.instrument', ... }` |\n\n## Example\n\n```js\nconst position = {\n    type: \"fdc3.position\",\n    instrument: {\n        type: \"fdc3.instrument\",\n        id: {\n            ticker: \"AAPL\"\n        }\n    },\n    holding: 2000000\n}\n\nfdc3.raiseIntent(\"ViewChart\", position)\n```\n\n## See Also\n\nOther Types\n- [Instrument](Instrument)\n- [Portfolio](Portfolio)\n\nIntents\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n- [Position](https://fo.finos.org/docs/objects/position)"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/TimeRange.md",
    "content": "---\nsidebar_label: TimeRange\ntitle: TimeRange\nhide_title: true\noriginal_id: TimeRange\n---\n# `TimeRange`\n\nA context representing a period of time. Any user interfaces that represent or visualise events or activity over time can be filtered or focused on a particular time period, e.g.:\n\n- A pricing chart\n- A trade blotter\n- A record of client contact/activity in a CRM\n\nExample use cases:\n\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\n- User filters a visualisation (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualisations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\n\nNotes:\n\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\n\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\n\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n  - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or `\"2022-05-12T16:18:03+01:00\"`\n  - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n\n## Type\n\n`fdc3.timeRange`\n\n:::warning\n\nThe `fdc3.timeRange` context type is inconsistently used in FDC3 2.0, occasionally appearing as `fdc3.timerange`. This has been corrected in FDC3 2.1 to always use the camel-case form `fdc3.timeRange`.\n\n:::\n\n## Schema\n\nhttps://fdc3.finos.org/schemas/2.0/timeRange.schema.json\n\n## Details\n\n| Property    | Type      | Required | Example Value                 |\n|-------------|-----------|----------|-------------------------------|\n| `type`      | string    | Yes      | `\"fdc3.timeRange\"`            |\n| `startTime` | string *  | No **    | `\"2022-03-30T15:44:44Z\"`      |\n| `endTime`   | string *  | No **    | `\"2022-04-30T23:59:59+00:00\"` |\n\n\\* Fields representing time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n\\*\\* One of `startTime` or `endTime` MUST be specified.\n\n## Example\n\nA closed range:\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    startTime: \"2022-03-30T15:44:44Z\",\n    endTime: \"2022-04-30T23:59:59ZS\"\n}\n```\n\nOpen ranges:\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    startTime: \"2022-03-30T15:44:44+00:00\"\n}\n```\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    endTime: \"2022-03-30T16:44:44.123Z\"\n}\n```\n\n## See Also\n\nOther Types\n\n- [Chart](Chart)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/ref/Valuation.md",
    "content": "---\nsidebar_label: Valuation\ntitle: Valuation\nhide_title: true\noriginal_id: Valuation\n---\n# `Valuation`\n\nA context type representing the price and value of a holding.\n\n## Type\n\n`fdc3.valuation`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.0/valuation.schema.json](pathname:///schemas/2.0/valuation.schema.json)\n\n## Details\n\n| Property             | Type    | Required | Example Value                 |\n|----------------------|---------|----------|-------------------------------|\n| `type`               | string  | Yes      | `'fdc3.valuation'`            |\n| `value`              | number  | Yes      | `500.0`                       |\n| `price`              | number  | No       | `5.0`                         |\n| `CURRENCY_ISOCODE` * | string  | Yes      | `GBP`                         |\n| `valuationTime` **   | string  | No       | `\"2022-05-12T16:16:24.815Z\"`  |\n| `expiryTime` **      | string  | No       | `\"2022-05-13T16:16:24+01:00\"` |\n\n\\* The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html).\n\n\\*\\* Time fields SHOULD conform to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n## Example\n\n```js\nconst valuation = {\n    type: 'fdc3.valuation',\n    value: 500.0,\n    price: 5.0,\n    CURRENCY_ISOCODE: 'USD',\n    expiryTime: \"2022-05-13T16:16:24+01:00\"\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/context/spec.md",
    "content": "---\nsidebar_label: Overview\ntitle: Context Data 2.0\noriginal_id: spec\n---\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems. FDC3 Context Data defines a standard for passing common identifiers and data between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [intents](../intents/spec) and when broadcasting context to other applications.\n\nThere are two main use cases for exchanging context data:\n\n* **Transmitting reference data between applications.**\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n* **Transferring information between applications.**\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there aren't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n## The Context Interface\n\nContext can be summarised as:\n\n* Having a unique _type_ identifier, used for routing.\n* Optionally providing a name.\n* Optionally providing a map of equivalent identifiers.\n* Any other properties or metadata.\n\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n\n### Namespacing\n\nAll well-known types at FDC3 level should be prefixed with `fdc3`. For private type definitions, or type definitions issued by other organisations, different namespaces can be used, e.g. `blackrock.fund`, etc.\n\n### Versioning\n\nThe specification recognises that evolving context data definitions over time, and helping applications to deal with changes to types, are very important.\n\nIt may be as simple as adding an optional `$version` property to types, but it could also be a set of guidelines for adding new properties, without removing or changing existing ones. For example, web technologies like REST or GraphQL do not take a particular opinion about versioning.\n\n## Field Type Conventions\n\nThis Standard defines a number of conventions for the fields of context types that all context objects SHOULD adhere to in order to reduce or prevent competing conventions from being established in both standardized types and proprietary types created by app developers.\n\n### Identifiers\n\nAn `id` field with type `object` is defined in the base [fdc3.context](ref/Context) type, from which all other context objects are derived, and SHOULD be used to encapsulate identifiers. Specific context types may define subfields for specific identifiers as needed.\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\n\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n### Times\n\nFields representing a point in time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included, e.g.:\n\n* Time in UTC: `\"2022-03-30T15:44:44Z\"`\n* Also time in UTC: `\"2022-03-30T15:44:44+00:00\"`\n* Same time in EDT: `\"2022-03-30T11:44:44-04:00\"`\n\nTimes MAY be expressed with millisecond precision, e.g.:\n\n* `\"2022-03-30T11:44:44.123-04:00\"`\n* `\"2022-03-30T11:44:44.123Z\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30T11:44:44.123-04:00\")\n```\n\n### Dates\n\nFields representing a point in time SHOULD be string encoded using the `YYYY-MM-DD` date format from [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n\nE.g. `\"2022-03-30\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30\")\n```\n\n### Country codes\n\nFields representing a country SHOULD be string encoded using the Alpha-2-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) and field name `COUNTRY_ISOALPHA2`. The Alpha-3-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) MAY be used in addition to the Alpha-2-code with the field name `COUNTRY_ISOALPHA3`.\n\nE.g. `\"COUNTRY_ISOALPHA2\": \"GB\"`\n\n### Currency codes\n\nFields representing a currency SHOULD be string encoded using the Alphabetic code from [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) with the field name `CURRENCY_ISOCODE`.\n\nE.g. `\"CURRENCY_ISOCODE\": \"GBP\"`\n\n:::note\nISO 4217 only includes major currency codes, conversions to minor currencies is the responsibility of the consuming system (where required).\n:::\n\n## Context Data Standard Compliance\n\nAn FDC3 Standard compliant application that supports the use of context data **MUST**:\n\n* Ensure that any FDC3-defined standard context types used meet the interface defined for that type of context data.\n* Where Channels are supported or an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers on start-up (for User channels and for receiving context from [`fdc3.open`](../api/ref/DesktopAgent#open)) or when the channel is first created or retrieved (for App and Private channels).\n\nAn FDC3 Standard compliant application that supports the use of context data **SHOULD**:\n\n* Prefer FDC3-defined standard context types over proprietary contexts, where a suitable FDC3-defined standard context type is available.\n* Ensure that any proprietary context data types defined follow any the recommended [namespacing](#namespacing) and [field type conventions](#field-type-conventions) in the specification.\n\nAn FDC3 Standard compliant application that supports the use of context data **MAY**:\n\n* Define proprietary context data types to support use cases not currently supported via FDC3-defined standard context types.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Context Types\n\nThe following are standard FDC3 context types:\n\n* [`fdc3.chart`](ref/Chart) ([schema](pathname:///schemas/2.0/chart.schema.json))\n* [`fdc3.chat.initSettings`](ref/ChatInitSettings) ([schema](pathname:///schemas/2.0/chatInitSettings.schema.json))\n* [`fdc3.contact`](ref/Contact) ([schema](pathname:///schemas/2.0/contact.schema.json))\n* [`fdc3.contactList`](ref/ContactList) ([schema](pathname:///schemas/2.0/contactList.schema.json))\n* [`fdc3.country`](ref/Country) ([schema](pathname:///schemas/2.0/country.schema.json))\n* [`fdc3.currency`](ref/Currency) ([schema](pathname:///schemas/2.0/currency.schema.json))\n* [`fdc3.email`](ref/Email) ([schema](pathname:///schemas/2.0/email.schema.json))\n* [`fdc3.instrument`](ref/Instrument) ([schema](pathname:///schemas/2.0/instrument.schema.json))\n* [`fdc3.instrumentList`](ref/InstrumentList) ([schema](pathname:///schemas/2.0/instrumentList.schema.json))\n* [`fdc3.organization`](ref/Organization) ([schema](pathname:///schemas/2.0/organization.schema.json))\n* [`fdc3.portfolio`](ref/Portfolio) ([schema](pathname:///schemas/2.0/portfolio.schema.json))\n* [`fdc3.position`](ref/Position) ([schema](pathname:///schemas/2.0/position.schema.json))\n* [`fdc3.nothing`](ref/Nothing) ([schema](pathname:///schemas/2.0/nothing.schema.json))\n* [`fdc3.timeRange`](ref/TimeRange) ([schema](pathname:///schemas/2.0/timeRange.schema.json))\n* [`fdc3.valuation`](ref/Valuation) ([schema](pathname:///schemas/2.0/valuation.schema.json))\n\n:::note\nThe below examples show how the base context data interface can be used to define specific context data objects.\n:::\n\n### Examples\n\n#### Contact\n\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### Email\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n#### Instrument\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### TypeScript definition\n\nThe `Instrument` type is derived from the `Context` type (note that the name becomes a required field, the type is fixed and optional `id` subfields are defined):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" : \n    {  \n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/fdc3-charter.md",
    "content": "---\ntitle: FDC3 Charter\noriginal_id: fdc3-charter\n---\n\n## Scope\nFinancial desktop applications include any app used in common financial workflows:\n\n* Traditional native applications implemented in C++, .NET, Java, Python, etc.\n* Hybrid web/native applications - stand alone native apps embedding Chromium (e.g. Electron, CEF, NW.js)\n* Desktop web applications - platform based apps extending Chromium (e.g. OpenFin, Finsemble, Glue42)\n* Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, etc.\n* PWAs & Web applications running in a commercial browser\n\nThis Standard is focused specifically on the desktop.  Activities of the desktop interoperability group do not include:\n\n* Defining financial objects - where existing standards are well established\n* Interoperability between mobile apps\n* Interoperability via REST or other client to server communication\n\n:::note\nWhile these areas are out of scope, compatibility with Mobile and/or REST are still valid points of consideration for FDC3.\n:::\n\n### Success Criteria\n* Commitment from major banks and application vendors to support the standards set out by the FDC3\n* Workflow integrations in the wild leveraging the standards\n\n### Deliverables\n* Define criteria and mechanics for secure communication between apps\n* Define key functions that require specific standards for interoperability\n* Create an agreed taxonomy for common app “intents” within financial desktop workflows\n* Create an agreed taxonomy for common data to be shared across apps within financial desktop workflows\n* Provide reference implementations of all standards\n* Maintain the above standards and reference implementations\n\n## Participation\nTo be successful, the maintenance and evolution of this Standard needs to have a critical mass of active participants for its duration. Effective participation in FDC3 means participation in the form of research, authoring, editing, and development activities outside the scope of attending regular meetings.\n\n## Licensing\nVersion 1.0 of the FDC3 specification is licensed under the [FDC3 1.0 Final Specification License](https://github.com/finos/FDC3/blob/17892008c26a73ff1fd9f6e40ceb8c8bfd58c610/PATENTS-FDC3-1.0.md).\n\nSubsequent FDC3 specifications and draft specifications are subject to the [FINOS IP Policy](https://github.com/finos/community/blob/main/website/static/governance-docs/IP-Policy.pdf)), which authorizes implementation of FDC3 specifications without charge, on a [RAND basis](https://en.wikipedia.org/wiki/Reasonable_and_non-discriminatory_licensing), subject to the terms of the policy. For details of the IP commitments made by contributors to FDC3, please refer to the policy.\n\nReference implementations and other software contained in FDC3 repositories is licensed under the [Apache License, Version 2.0](https://github.com/finos/FDC3/blob/17892008c26a73ff1fd9f6e40ceb8c8bfd58c610/LICENSE) unless otherwise noted. SPDX-License-Identifier: [Apache-2.0](https://spdx.org/licenses/Apache-2.0).\n\n### Intellectual Property Claims\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide \nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD."
  },
  {
    "path": "website/versioned_docs/version-2.0/fdc3-compliance.md",
    "content": "---\ntitle: Compliance\noriginal_id: fdc3-compliance\n---\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>    Imperatives of the type defined in this memo must be used with care\n>    and sparingly.  In particular, they MUST only be used where it is\n>    actually required for interoperation or to limit behavior which has\n>    potential for causing harm (e.g., limiting retransmisssions)  For\n>    example, they must not be used to try to impose a particular method\n>    on implementors where the method is not required for \n>    interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers the API, App Directory, Context Data, and Intents specifications.\n\n## Personas\n\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation(s) of the FDC3 APIs (The Desktop Agent API and Application Directory) for applications to use.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.\n\nDepending on persona, implementation compliance with FDC3 will mean different things.\n\n### Platform Provider\n\nFor platform providers FDC3 compliance requires that they meet the requirements of the APIs that they implement:\n\n* [Desktop Agent API compliance requirements](api/spec#desktop-agent-api-standard-compliance).\n* [App Directory compliance requirements](app-directory/spec#app-directory-standard-compliance).\n\n### Application Provider\n\nFor application providers FDC3 compliance requires that they interact with the FDC3 APIs as intended and meet the requirements of the Intents and Context Data Standards. Specifically:\n\n* [Intents Standard compliance requirements](intents/spec#intents-standard-compliance)\n* [Context Data Standard compliance requirements](context/spec#context-data-standard-compliance)\n\n## Versioning\n\nTypically, a Standard that has marketplace relevance is revised from time to time, to correct errors and/or to add functionality to support new use cases. Hence, there exist multiple versions of the standard. As FDC3 is a standards project, we don't follow semver, which is meant for libraries. We use the versioning scheme `<major>.<minor>`, e.g. `1.1` or `2.3`.\n\n## Deprecation Policy\n\nOver time, it is not uncommon for certain things in a standard to be marked for removal in a future version, possibly being replaced by an alternative. That is, they are deprecated. Often, they are retained in the standard because of their widespread use, but their use in new projects is discouraged.\n\nFDC3 adopts the following deprecation policy:\n\n1. A feature can be deprecated by any major or minor version. Newly deprecated features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n2. A feature shall only be removed by a major version. Newly removed features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n3. Deprecated features are clearly marked with an `@deprecated` tag and comment in both the documentation and jsDocs applied to the TypeScript sources.\n4. Where possible, changes to the behavior of an existing feature should be avoided; consider deprecating it and replacing it with something with a different name/syntax.\n5. Breaking change should only be made in a major version of the Standard.\n\n## Experimental Features\n\nOccasionally, a change to FDC3 may be proposed where the design is tentative, and because of this, we need feedback from the community to finalise its inclusion in the Standard. In such cases, a feature may be designated as _experimental_ to indicate that its design may change in future and that it is exempted from the normal versioning and deprecation polices in order to facilitate that change.  However, designating a feature as experimental is likely to reduce its uptake by the community, hence, this designation should be used sparingly.\n\nFDC3 adopts the following experimental features policy:\n\n1. A feature may be designated as experimental where feedback is needed to confirm the final design of that feature, with the goal of including it as a full part of the Standard without the experimental label. \n2. A feature should only be designated as experimental where there is a reasonable chance that breaking changes to its design may be applied, based on feedback received; non-breaking changes (refinements) may already be applied to features defined in the Standard without the experimental designation.\n3. Experimental features are clearly marked with an `@experimental` tag and comment in both the documentation and docs applied to the TypeScript sources.\n4. Unless otherwise stated, experimental features should be considered optional for compliance purposes, but recommended for implementation (i.e. the SHOULD keyword is implied).\n5. Experimental features are exempted from the normal versioning and deprecation policies that govern changes to FDC3. I.e. breaking changes may be made to experimental features between versions of the Standard without a major version release.\n6. The experimental designation may be removed from a feature in a minor version release (as this will be considered an additive change).\n\n## Conformance testing\n\nThe FDC3 Standards include a set of [definitions for conformance tests](api/conformance/Conformance-Overview) that may be used to determine if a Desktop Agent API implementation conforms to a particular Standard version, to help disambiguate complex parts of the FDC3 Standard and to enable test-driven development of a Desktop Agent implementation.\n\nThe current set of tests focus on the Desktop Agent API and the interface to it. Tests are not yet defined for the App Directory API or Bridging API Parts of the FDC3 Standard, hence, conformance to those parts of the Standard must be determined manually.\n\nThe FDC3 Conformance tests are implemented for JavaScript/TypeScript web applications by the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework). Desktop Agent implementors working with web interfaces (Desktop Agent Preload or Desktop Agent Proxy) can clone the conformance framework and run the tests locally to determine if their agent is compliant with the Standard.\n\nOnce a Desktop Agent has passed the conformance tests locally, its authors can [apply for a formal certification of compliance with the Standard from FINOS](https://github.com/finos/FDC3-conformance-framework/blob/main/instructions.md). Please note the [Terms and Conditions](https://github.com/finos/FDC3-conformance-framework/blob/main/terms-conditions/FDC3-Certified-Terms.md) of the Conformance Program.\n\nimport badge_12 from '/img/community/certified-1.2.png';\nimport badge_20 from '/img/community/certified-2.0.png';\n\n<img src={badge_12} alt=\"Certified conformant with FDC3 1.2 badge\" style={{width: 200}} />\n<img src={badge_20} alt=\"Certified conformant with FDC3 2.0 badge\" style={{width: 200}} />\n\n## Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide \nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/fdc3-glossary.md",
    "content": "---\ntitle: Glossary of Terms\nsidebar_label: Glossary\noriginal_id: fdc3-glossary\n---\n\nFor the purposes of this Standard, the following definitions apply. Other terms are defined when first used, at which place they appear in bold and italic type. Terms explicitly defined in this Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined are assumed to be well-known in the financial services or software industries.\n\n\n- **app**: Shorthand for application.\n- **app directory**: A repository of application metadata supporting discovery, for example via name or intent, and retrieval of metadata necessary to launch an application.\n- **app directory record**: Metadata relating to a single application, encoded in JSON.\n- **appD**: Shorthand for app directory.\n- **appD record**: Shorthand for app directory record.\n- **application**: Any endpoint on the desktop that is registered with/known by a Desktop Agent, launchable by a Desktop Agent, addressable by a Desktop Agent or otherwise able to interact with the Desktop Agent.\n- **application, hybrid**: Any web application running within the context of a standalone native application that embeds a web view, typically based on Chromium.\n- **application, native**: A non-web-based application; i.e., one that runs outside the context of web browser, web view or web container. A user-written program—typically implemented in a language such as C++, C#, Java, or Python, rather than JavaScript or TypeScript.\n- **application, web**: An application written in TypeScript or JavaScript, HTML and CSS, which runs within the context of a web browser or a web container.\n- **Application Provider**: A downstream consumer of FDC3 Standards that can understand and use the FDC3 API (supplied by a Platform Provider), context data, and/or intents.\n- **application-specific intent**: A custom intent defined by an application or applications, independent of the Standard.\n- **Channel**: A grouping of apps for the purposes of sharing stateful pieces of data. A secondary interface of the FDC3 API.\n- **context channels**: A mechanism to allow sets of apps to share stateful pieces of data among themselves, and to be alerted when that data changes.\n- **context**: Shorthand for context data.\n- **context data**: Objects encoding common identifiers and data in a standardized format that can be passed between apps via context channels or used in conjunction with intents to invoke actions creating a seamless cross-application workflow. Diverse context data types are created to encode different types of data, each having their own _type_ field and unique set of data fields. \n- **Desktop Agent**: A desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain. The primary interface of the FDC3 API.\n- **FDC3 API**: A baseline, consistent developer interface for interoperability between applications.\n- **interop**: Shorthand for interoperability.\n- **interoperability**: the ability of software applications to exchange and make use of information and invoke specified actions.\n- **intent**: A verb, with a pre-agreed meaning (expected behavior), used to invoke an action between applications. A set of such verbs can, in conjunction with Context Data acting as nouns, be used to put together common cross-application workflows on the financial desktop.\n- **Listener**: API interface which allows unsubscribing from Intents or Context Channels.\n- **Originating App**: The application that sent a particular context message or raised an intent.\n- **Platform Provider**: An environment that provides an implementation of the FDC3 API that applications can use.\n- **raising an intent**: The act of requesting, via the FDC3 API/Desktop Agent that a specified action be performed by another application, using specified context data as input.\n- **resolver**: A facility of a Desktop Agent used to map a raised intent and associated context object to an application that will perform the action represented by the intent, using the context object as input. Where multiple applications can resolve the intent, a resolver will often display a user-interface allowing a user to pick from the available applications that support the intent and type of context supplied.\n- **resolving an intent**: The act of mapping a specified intent and context object to an application.\n- **standard intent**: An intent defined by this Standard.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/fdc3-intro.md",
    "content": "---\ntitle: Welcome to FDC3 2.0\nsidebar_label: Introduction\noriginal_id: fdc3-intro\n---\n\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\nFDC3 provides an **open standard for interoperability** between applications on the financial desktop.\n\nThis includes standardized verbs to invoke actions between applications (**intents**), a standardized **context data** format, a REST-based **App Directory** standard, and standardized API operations for a **Desktop Agent**.\n\n## Motivation\n\nFDC3 codifies standard patterns that application developers have been using for cross-application workflows between web and native applications in the financial industry.\n\nFor more information, see [Why FDC3?](why-fdc3)\n\n## Parts of the Standard\n\nThe [Standard](fdc3-standard) currently consists of four complementary parts:\n\n- [API](api/spec)\n- [Intents](intents/spec)\n- [Context Data](context/spec)\n- [App Directory](app-directory/spec)\n\n## Use Cases\n\nFrom its inception, the standards have been informed by real-world [business use cases](use-cases/overview), which you can view on this website, and form an important part of FDC3.\n\n## Who is using FDC3?\n\nThe Financial Desktop Connectivity and Collaboration Consortium (FDC3) standards are created and used by [leading organizations across the financial industry](/users). For more detail on who's using FDC3, developer tools, training and examples, see the [community page](/community).\n\n## How is FDC3 governed?\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services.\n\n- See the [FDC3 Governance document](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md) for details of how FDC3 is governed.\n- See the [FDC3 Contribution Guide](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for details of how to contribute to FDC3.\n- See the [FDC3 Charter](fdc3-charter#licensing) for details of how deliverables are licensed.\n\n## Where should I go next?\n\n- Have a look at the [supported platforms](supported-platforms) or [common use cases](use-cases/overview).\n- Visit FDC3 [on GitHub](https://github.com/finos/FDC3).\n- Download and install our [npm package](https://www.npmjs.com/package/@finos/fdc3).\n- Try out an FDC3-compliant implementation, e.g. this [browser extension](https://github.com/finos/fdc3-desktop-agent).\n- Join us in the [mailing list](mailto:fdc3+subscribe@finos.org) or on [Slack](https://app.slack.com/client/T01E7QRQH97/C01R0P7H5LH).\n- [Participate](https://github.com/finos/FDC3#getting-involved) in the evolution of the standard.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/fdc3-standard.md",
    "content": "---\ntitle: FDC3 2.0\nsidebar_label: Abstract\noriginal_id: fdc3-standard\n---\n\n**Status:** Superceded  \n_**adopted:** 1st July 2022_  \n_**released:** 22nd August 2022_  \n_**superseded:** 31st August 2023_  \n\n## Abstract\n\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of four complementary parts:\n\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain. \n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n\n## Versioning\n\nThis Standard defines FDC3 Version 2.0. The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md). \n\nFor more details on FDC3's versioning, deprecation and experimental features policies see the [Compliance page](./fdc3-compliance#versioning).\n\n## Table of Contents\n\n- [Compliance information](fdc3-compliance)\n- [Glossary](fdc3-glossary)\n- [References](references)\n- [Supported Platforms](supported-platforms)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part](app-directory/spec)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/guides/submit-new-intent.md",
    "content": "---\nsidebar_label: How To Submit New Intent\ntitle: How to Submit a New Intent PR\noriginal_id: SubmitNewIntent\n---\n\n## Getting Started\n\nPrepare to submit a patch as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch) in CONTRIBUTING.md. Use the issue number and issue title as the branch name, e.g.\n\n```git checkout -b 587-intent-proposal-view-research```\n\nTo install all the necessary packages to run the website locally, change to the website directory and run yarn\n\n```\ncd website\nyarn\n```\n\nTo run the website locally\n\n```yarn start```\n\nThis will open the home page or browse to https://localhost:3000\n\nNote that the page opens on the current release version of the docs and you will be changing the latest version. Click the version selector in the top left hand corner\n\n![Version Selector](/assets/version_selector.png)\n\nand then select 'Documentation' under 'Latest Version'\n\n![Latest Version Selector](/assets/latest_version_selector.png)\n\nThe 'next' version will be indicated in the header:\n\n![Next Version](/assets/next_version.png)\n\n## Create Intent File\n\nAdd the new intent markdown file to docs/intents/ref. Use one of the existing intent markdown files as a template. E.g. the [ViewResearch](../intents/ref/ViewResearch) intent was created using [ViewProfile](../intents/ref/ViewProfile) as an example:\n\n![View Research](/assets/view_research.png)\n\n## Link to Intent File\n\nAdd links to your Intent File to the following:\n\n* [src/intents/Intents.ts](https://github.com/finos/FDC3/blob/main/src/intents/Intents.ts)\n* [src/intents/standard intents.json](https://github.com/finos/FDC3/blob/main/src/intents/standard%20intents.json)\n* [website/sidebars.json](https://github.com/finos/FDC3/blob/main/website/sidebars.json) (look for the 'Intents' property and the 'ids' property within it)\n\nAt this point your new Intent should appear on the sidebar (you may need to restart yarn to get this).\n\nAlso add to:\n\n* [docs/intents/spec.md](https://github.com/finos/FDC3/blob/main/docs/intents/spec.md) in the 'Standard Intents' section (also add the summary from your Intent page)\n* Any of the Context documents in [docs/context/ref](https://github.com/finos/FDC3/blob/main/docs/context/ref) that are utilised by the Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent, each of the [Contact](../context/ref/Contact), [Instrument](../context/ref/Instrument) and [Organization](../context/ref/Organization) Contexts are valid and so links were added to their Context pages)\n* Any of the Intents documents in [docs/intents/ref](https://github.com/finos/FDC3/blob/main/docs/intents/ref) that are related or relevant to the new Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent a link was added to the [ViewAnalysis](../intents/ref/ViewAnalysis) document)\n\n## Finishing Off\n\nCommit your changes and push as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch). Then submit the branch as a Pull Request (in github, go to the Branches tab and click 'New Pull Request')\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/overview.md",
    "content": "---\nsidebar_label: Intents Overview\ntitle: Intents Overview\nhide_title: true\noriginal_id: overview\n---\n\n# Intents Overview\n\nExtending APIs from one application to another is powerful. However, it requires bi-lateral agreements where implementors build to proprietary APIs. A standard language for interaction between applications allows us to create workflows on the fly, so that applications can discover and link to another without any prior knowledge.\n\n\nFDC3 Intents define a standard set of verbs that can be used to put together common cross-application workflows on the financial desktop.\n* Applications register the Intents & [Context Data](../context/spec) combinations they support in the [App Directory](../app-directory/overview)\n* The App Directory supports application discovery by Intents and/or Context Data\n* Intents are not full RPC, apps don’t need to enumerate every function with an intent\n* FDC3 Standard Intents are a limited set, organizations can create their own intents\n\n## Using Intents\nCombined with [Context Data](../context/spec) and [App Directory](../app-directory/overview) standards, Intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n type: \"fdc3.instrument\",\n name: \"IBM\",\n id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n type: \"fdc3.contact\",\n name: \"Jane Doe\",\n id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/StartCall.md",
    "content": "---\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\noriginal_id: StartCall\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n* [StartChat](StartChat)\n* [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/StartChat.md",
    "content": "---\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\noriginal_id: StartChat\n---\n# `StartChat`\n\nInitiate a chat with a contact, a list of contacts or detailed initialization settings.  This could be launched from within another application. For example initiating a chat from a research or OMS application.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n* [ChatInitSettings](../../context/ref/ChatInitSettings)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n\n// chat with initialization settings\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Issue #123',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true,\n        allowAddUser: false, // John won't be authorized to add other users to the chat\n    }\n    initMessage: 'Hello John!'\n}\n\nconst resolution = fdc3.raiseIntent('StartChat', initSettings);\nconst chatRooms = await resolution.getResult();\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\nIntents\n* [StartCall](StartCall)\n* [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/StartEmail.md",
    "content": "---\nsidebar_label: StartEmail\ntitle: StartEmail\nhide_title: true\noriginal_id: StartEmail\n---\n# `StartEmail`\n\nInitiate an email with a contact or list of contacts provided as part of an Email context.\n\n## Intent Name\n\n`StartEmail`\n\n## Display Name\n\n`Start Email`\n\n## Possible Contexts\n\n* [Email](../../context/ref/Email)\n\n## Example\n\n```js\nwindow.fdc3.raiseIntent('fdc3.StartEmail', {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n})\n```\n\n## See Also\n\nContext\n* [Email](../../context/ref/Email)\n\nIntents\n* [StartCall](StartCall)\n* [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewAnalysis.md",
    "content": "---\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\noriginal_id: ViewAnalysis\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n- [ViewChart](ViewChart)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewChart.md",
    "content": "---\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\noriginal_id: ViewChart\n---\n# `ViewChart`\n\nDisplay a chart for the provided context.\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n* [Chart](../../context/ref/Chart)\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Portfolio](../../context/ref/Portfolio)\n* [Position](../../context/ref/Position)\n\n## Example\n\nRequest a chart for an instrument:\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\nRequest a specific chart:\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: {\n        indicators: [\n            {\n                name: \"ma\",\n                parameters: {\n                    period: 14,\n                    type: \"ema\"\n                }\n            },\n            {\n                name: \"volume\"\n            }\n        ]\n    }\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nContext\n\n* [Chart](../../context/ref/Chart)\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Portfolio](../../context/ref/Portfolio)\n* [Position](../../context/ref/Position)\n\nIntents\n\n* [ViewQuote](ViewQuote)"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewContact.md",
    "content": "---\nsidebar_label: ViewContact (deprecated)\ntitle: ViewContact\nhide_title: true\noriginal_id: ViewContact\n---\n# `ViewContact`\n:::caution\nViewContact has been deprecated in FDC3 2.0 in favour of the more general [ViewProfile](ViewProfile) intent.\n:::\n\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n\nIntents\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewHoldings.md",
    "content": "---\nsidebar_label: ViewHoldings\ntitle: ViewHoldings\nhide_title: true\noriginal_id: ViewHoldings\n---\n# `ViewHoldings`\n\nDisplay any holdings for the provided instrument, list of instruments, or organization.\n\n## Intent Name\n\n`ViewHoldings`\n\n## Display Name\n\n`View Holdings`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewHoldings', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\nIntents\n- [ViewInstrument](ViewInstrument)\n- [ViewAnalysis](ViewAnalysis)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewInstrument.md",
    "content": "---\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\noriginal_id: ViewInstrument\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewInteractions.md",
    "content": "---\nsidebar_label: ViewInteractions\ntitle: ViewInteractions\nhide_title: true\noriginal_id: ViewInteractions\n---\n# `ViewInteractions`\n\nDisplay interactions (calls, meetings, etc.) related to an individual, an instrument or organization provided as context.\n\n## Intent Name\n\n`ViewInteractions`\n\n## Display Name\n\n`View Interactions`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewInteractions', contact)\n```\n\n## See Also\n\nContext\n* [Contact](../../context/ref/Contact)\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n\nIntents\n* [ViewProfile](ViewProfile)\n* [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewNews.md",
    "content": "---\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\noriginal_id: ViewNews\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n* [Country](../../context/ref/Country)\n* [Instrument](../../context/ref/Instrument)\n* [InstrumentList](../../context/ref/InstrumentList)\n* [Organization](../../context/ref/Organization)\n* [Portfolio](../../context/ref/Portfolio)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n\nIntents\n- [ViewAnalysis](ViewAnalysis)"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewOrders.md",
    "content": "---\nsidebar_label: ViewOrders\ntitle: ViewOrders\nhide_title: true\noriginal_id: ViewOrders\n---\n# `ViewOrders`\n\nDisplay any orders related to the provided contact, instrument, or organization.\n\n## Intent Name\n\n`ViewOrders`\n\n## Display Name\n\n`View Orders`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewOrders', instrument)\n```\n\n## See Also\n\nContext\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n- [ViewHoldings](ViewHoldings)\n- [ViewInstrument](ViewInstrument)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewProfile.md",
    "content": "---\nsidebar_label: ViewProfile\ntitle: ViewProfile\nhide_title: true\noriginal_id: ViewProfile\n---\n# `ViewProfile`\n\nDisplay basic profile information for the individual or organization provided as context.\n\n## Intent Name\n\n`ViewProfile`\n\n## Display Name\n\n`View Profile`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewProfile', contact)\n```\n\n## See Also\n\nContext\n* [Contact](../../context/ref/Contact)\n* [Organization](../../context/ref/Organization)\n\nIntents\n* [ViewHoldings](ViewHoldings)\n* [ViewInteractions](ViewInteractions)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewQuote.md",
    "content": "---\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\noriginal_id: ViewQuote\n---\n# `ViewQuote`\n\nDisplay pricing for an instrumen.\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n* [Instrument](../../context/ref/Instrument)\n\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n- [Instrument](../../context/ref/Instrument)\n\n\nIntents\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/ref/ViewResearch.md",
    "content": "---\nsidebar_label: ViewResearch\ntitle: ViewResearch\nhide_title: true\noriginal_id: ViewResearch\n---\n# `ViewResearch`\n\nShow research related to an instrument, an individual or organization provided as context.\n\n## Intent Name\n\n`ViewResearch`\n\n## Display Name\n\n`View Research`\n\n## Possible Contexts\n\n* [Contact](../../context/ref/Contact)\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewResearch', contact)\n```\n\n## See Also\n\nContext\n* [Contact](../../context/ref/Contact)\n* [Instrument](../../context/ref/Instrument)\n* [Organization](../../context/ref/Organization)\n\nIntents\n* [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/intents/spec.md",
    "content": "---\nsidebar_label: Overview\ntitle: Intents Overview 2.0\noriginal_id: spec\n---\n\nFDC3 Intents define a standard set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n\n* Applications register the intents and [context data](../context/spec) combinations they support in the [App Directory](../app-directory/spec).\n* The App Directory supports application discovery by intents and/or context data.\n* Intents are not full RPC, apps don’t need to enumerate every function with an intent.\n* FDC3 standard intents are a limited set, organizations can create their own intents.\n\n## Naming Conventions\n\nNaming of Intents SHOULD follow the below guidelines:\n\n* Intent names should be free of non-alphanumeric characters.\n* ‘.’ will be used to namespace the intent (see below).\n* Intent names should be in UpperCamelCase.\n\n:::note\nThe naming guidelines should be adhered to when creating future Intents.  This is to ensure they meet the criteria for addition to the FDC3 standard and to provide a consistent user experience.\n:::\n\n### Characteristics\n\nWhen creating Intents they should be:\n\n* Recognizable\n  * Generally self-evident what the thing is\n* Repeatable\n  * Many instances across the industry\n* Stateless\n  * Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n* Specific\n  * Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n* Distinct\n  * Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces\n\nAll standard intent names are reserved. Applications may use their own intents ad hoc.\nHowever, there is occasionally a need for applications to ensure that their intents avoid collision, for example, where a workflow is highly specific to or internal to an application. The recommended approach is to namespace the intent with the application name. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary intent.\n\n### Intent Name Prefixes\n\nEarly versions of the FDC3 standard included 8 intents, which used one of two different prefixes ( `View___` and `Start___`) that are focused on UI interactions.  The prefixes are used to help define the expected behavior of an app when resolving an intent with that prefix. The list of intent name prefixes was expanded in FDC3 2.0 to include prefixes that indicate that CRUD operations should be performed on data.\n\n#### `View___`\n\n* Expected behaviour: Content should be displayed to the user.\n\n#### `Start___`\n  \n* Expected behaviour: An interaction, such as a chat room or email thread, should be initiated.\n\nAs more use cases were identified it was clear further Intents were required.  FDC3 2.0 expanded this set to include the following:\n\n#### `Create___`\n\n* Expected behaviour: A new record or entity should be created. The operation should fail if it already exists.\n\n#### `Update___`\n\n* Expected behaviour: An existing record or entity should be updated. The operation should fail if it does not exist.\n\n#### `CreateOrUpdate___`\n\n* Expected behaviour: A new record or entity should be created, or an existing one updated if it exists.\n\n#### `Delete___`\n\n* Expected behaviour: An existing record or entity should be deleted. The operation should fail if it does not exist.\n\n#### `Get___`\n\n* Expected behaviour: A record or entity should be retrieved and returned as an intent result. The operation should fail if the record does not exist.\n\n#### `Share___`\n\n* Expected behaviour: A record or entity should shared. The operation should fail if it does not exist\n\n## Using Intents\n\nCombined with [context data](../context/spec) and [App Directory](../app-directory/overview) standards, intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.contact\",\n  name: \"Jane Doe\",\n  id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n\n## Intents Standard Compliance\n\nAn FDC3 Standard compliant application that supports intents **MUST**:\n\n* Meet the expected context and behavior defined for any FDC3-defined standard intents used.\n* Use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up a handler for each supported intent as soon as possible when it starts up. This facilitates delivery of raised intents to the application.\n\nAn FDC3 Standard compliant application that supports intents **SHOULD**:\n\n* Prefer FDC3-defined standard intents over proprietary intents, where a suitable standardized intent is available.\n* Ensure that proprietary intents follow the recommended naming conventions in the specification.\n* Apply [namespacing](#namespaces) to proprietary intent names, where it is necessary to avoid collision with those created by other applications.\n\nAn FDC3 Standard compliant application that supports intents **MAY**:\n\n* Define proprietary intents to support use cases not currently supported via FDC3-defined standard intents.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Intents\n\nA list of standardized intents are defined in the following pages:\n\n* [`StartCall`](ref/StartCall)\n* [`StartChat`](ref/StartChat)\n* [`StartEmail`](ref/StartEmail)\n* [`ViewAnalysis`](ref/ViewAnalysis)\n* [`ViewChart`](ref/ViewChart)\n* [`ViewHoldings`](ref/ViewHoldings)\n* [`ViewInstrument`](ref/ViewInstrument)\n* [`ViewInteractions`](ref/ViewInteractions)\n* [`ViewNews`](ref/ViewNews)\n* [`ViewOrders`](ref/ViewOrders)\n* [`ViewProfile`](ref/ViewProfile)\n* [`ViewQuote`](ref/ViewQuote)\n* [`ViewResearch`](ref/ViewResearch)\n\n### Deprecated Intents\n\n* [`ViewContact`](ref/ViewContact)\n\n## Using Intents without a context\n\nAs the [Desktop Agent API](../api/ref/DesktopAgent) and [App Directory](../app-directory/overview) both require a context to be specified wherever intents are used, using an intent without a context is achieved through the use of the explicit `null` context type [`fdc3.nothing`](../context/ref/Nothing). By using an explicit type to represent an absence of context we allow applications to declare their support for an absence of context.\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.nothing\",\n});\n\nconst result = await fdc3.raiseIntent(\"StartChat\", {\n  type: \"fdc3.nothing\"\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/references.md",
    "content": "---\ntitle: References & Bibliography\nsidebar_label: References\noriginal_id: references\n---\n\n\nThe following normative documents contain provisions, which, through reference in this text, constitute provisions of this Standard. For dated references, subsequent amendments to, or revisions of, any of these publications do not apply. However, parties to agreements based on this Standard are encouraged to investigate the possibility of applying the most recent editions of the normative documents indicated below. For undated references, the latest edition of the normative document referred to applies:\n\n- **Apache 2.0 open-source license**, [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0).\n- **Community Specification license**, [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0)\n- **ISO 3166-1**, _Codes for the representation of names of countries and their subdivisions – Part 1: Country codes_, [https://www.iso.org/iso-3166-country-codes.html](https://www.iso.org/iso-3166-country-codes.html).\n- **ISO 8601-1:2019**, _Date and time — Representations for information interchange — Part 1: Basic rules_, [https://www.iso.org/standard/70907.html](https://www.iso.org/standard/70907.html)\n- **JSON Schema**, [https://json-schema.org/](https://json-schema.org/).\n- **OpenAPI Standard v3.0**, [https://www.openapis.org/](https://www.openapis.org/).\n- **RFC 2119**, _Keywords for use in RFCs to Indicate Requirement Levels, March 1997_, [https://datatracker.ietf.org/doc/html/rfc2119](https://datatracker.ietf.org/doc/html/rfc2119).\n- **RFC 2782**, _A DNS RR for specifying the location of services (DNS SRV), February 2000_, [https://datatracker.ietf.org/doc/html/rfc2782].\n- **RFC 5646**, _Tags for Identifying Languages, September 2009_, [https://datatracker.ietf.org/doc/html/rfc5646](https://datatracker.ietf.org/doc/html/rfc5646).\n- **TypeScript Programming Language**, [https://www.typescriptlang.org/](https://www.typescriptlang.org/).\n- **Web Application Manifest**, _W3C Working Draft_, February 2022 [https://www.w3.org/TR/appmanifest/](https://www.w3.org/TR/appmanifest/)\n\nThe following documents may be useful in understanding certain aspects of this Standard; however, knowledge of them is not essential to the creation of a compliant implementation of this Standard:\n\n- **CUSIP**, _Committee on Uniform Security Identification Procedures_, [https://www.cusip.com/identifiers.html#/CUSIP](https://www.cusip.com/identifiers.html#/CUSIP).\n- **FIGI**, _Financial Instrument Global Identifier_, [https://www.openfigi.com/about/figi](https://www.openfigi.com/about/figi).\n- **ISIN**, _International Securities Identification Number_, [https://www.isin.org/isin/](https://www.isin.org/isin/)\n- **LEI**, _Legal Entity Identifier based on the ISO 17442 standard_, [https://www.legalentityidentifier.co.uk/what-is-lei-code/](https://www.legalentityidentifier.co.uk/what-is-lei-code/).\n- **npm**,  [https://docs.npmjs.com/about-npm](https://docs.npmjs.com/about-npm).\n- **PermID**, _Permanent Identifiers_, [https://permid.org/](https://permid.org/).\n- **pnpm**, [https://pnpm.io/motivation](https://pnpm.io/motivation]).\n- **REST**, [https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm), [https://restfulapi.net/](https://restfulapi.net/).\n- **SEDOL**, _Stock Exchange Daily Official List_, [https://www.lseg.com/sedol](https://www.lseg.com/sedol).\n- **yarn**, [https://yarnpkg.com/getting-started](https://yarnpkg.com/getting-started).\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/supported-platforms.md",
    "content": "---\ntitle: Supported Platforms\noriginal_id: supported-platforms\n---\n\nFDC3 is platform- and programming language-independent. An FDC3-capable platform requires a Desktop Agent that supports the FDC3 standard, and that agent is responsible for coordinating application interactions.\n\nThere are two main categories of platform: web and native, both of which are described below. There exists a third category, hybrid, where a web application runs within the context of a standalone native application via a web view.\n\n## Web\n\nFor a web application to be FDC3-enabled, it needs to run in the context of an environment or **_Platform Provider_** that makes the FDC3 API available to the application. This environment could be a browser extension, a web or native app, or fully-fledged desktop container framework.\n\n### Usage\n\nThere are two main ways FDC3 can be used from web applications:\n\n#### 1. Direct Usage\n\nSimply rely on the global object being made available by your desktop agent, and address the API directly:\n\n```javascript\nfunction sendData() {\n  window.fdc3.broadcast({\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n  })\n}\n\nif (window.fdc3) {\n  sendData();\n} else {\n  window.addEventListener(\"fdc3Ready\", sendData);\n}\n```\n\n\n#### 2. NPM Wrapper\nFDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can by used by web applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\n<!--DOCUSAURUS_CODE_TABS-->\n<!--npm -->\n\n```sh\nnpm install @finos/fdc3\n```\n<!--yarn-->\n\n```sh\nyarn add @finos/fdc3\n```\n\n<!--pnpm-->\n\n```sh\npnpm install @finos/fdc3\n```\n\n<!--END_DOCUSAURUS_CODE_TABS-->\n\nThe npm package provides a wrapper around FDC3, allowing you to use it with ES6 import syntax:\n\n```javascript\nimport * as fdc3 from '@finos/fdc3';\n\nawait fdc3.raiseIntent('ViewAnalysis', {\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n});\n```\n\nIt also includes a helper function you can use to wait for FDC3 to become available:\n\n```javascript\nimport { fdc3Ready, addIntentListener } from '@finos/fdc3'\n\nawait fdc3Ready();\n\nconst listener = await addIntentListener('ViewAnalysis', instrument => {\n  // handle intent\n});\n```\n\n##### See also\n* [`fdc3Ready() Function`](api/ref/Globals#fdc3ready-function)\n\n## Native\n\nThe FDC3 standard does not define wire formats for communication, nor does it define language specific API bindings, other than JavaScript and TypeScript. Hence, for a native application to be FDC3-enabled, it needs to make use of a shared library (such as a .NET DLL or JAR file) that provides it with an implementation of the FDC3 API. Therefore, an FDC3-enabled native application is currently specific to a particular desktop container framework (or other suitable environment) that provides the necessary library.\n\nDespite this limitation, implementing support for FDC3 in a native application can allow it to interact with a wide variety of FDC3-enabled web applications.\n\n## Hybrid\nIn a hybrid application, a standalone native application incorporates a web view, within which a web application runs. This may be considered a special case of the web platform where all platform-provider requirements for web applications must be satisfied, but it is the responsibility of the associated native application, rather than a platform provider, to ensure they are fulfilled. This may be achieved, for example, by injecting an implementation of the DesktopAgent API and ensuring that it is accessible at the usual location, `window.fdc3`.\n\n## Compliance\nSupport for each platform is optional and compliance with the FDC3 standard should be assessed for each platform implemented independently of any other, with the exception of ensuring that where applications running on multiple platforms are used together, communication between them still complies with the standard.\n\nThe web API binding is expressed using TypeScript syntax that defines the API interface (for both TypeScript and JavaScript). Adherence to the specific binding is required for web application platforms. No specific API binding for native platforms is currently expressed in the standard. Hence, native applications may be implemented with any programming language binding that supports the constructs required by the API specification, until such time that the FDC3 standard introduces an appropriate language-specific binding."
  },
  {
    "path": "website/versioned_docs/version-2.0/trademarks.md",
    "content": "---\ntitle: Trademarks\noriginal_id: trademarks\n---\n\nThe trademarks, logos, and service marks not owned on behalf of FDC3 and FINOS and that are displayed on the Site are the registered and unregistered marks of their respective owners. No rights are granted by the FDC3 or FINOS to use such marks, whether by implication, estoppel, or otherwise.\n\nTrademarks used within this site and the FDC3 Standard include, but are not limited to:\n\n- Autobahn is a registered trademark of DEUTSCHE BANK AG, LONDON\n- Chromium is a trademark of Google LLC\n- Eikon is a registered trademark of Refinitiv\n- FDC3 is a registered trademark and brand of The Linux Foundation\n- Excel is a Microsoft Corporation product name\n- Finsemble is a registered trademark and product name of Finsemble, Inc.\n- Glue42 is a trademark of Tick42\n- Java is a registered trademark of Oracle America, Inc.\n- JavaScript  is a registered trademark of Oracle America, Inc.\n- .NET is a trademark of Microsoft Corporation\n- npm is a trademark of npm, Inc.\n- OpenFin is a registered trademark of OpenFin Inc.\n- Outlook is a registered trademark of Microsoft Corporation\n- Python is a registered trademark of the Python Software Foundation"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\noriginal_id: uc-1\n---\n\n## Preconditions\nOn their desktop, this user has:\n- Their firm's internal research & analytics platform containing liquidity tools and internal research. The product is running and the liquidity tool is open\n- An installed chat application - product is running\n- A third party market data terminal with 3 open applications. These applications are all 'linked' through a channel. \n    - A Watchlist\n    - An Order Book\n    - An Overview of pricing and fundamental data\n- A third party Charting Application access via a browser window. This is not open. \n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\noriginal_id: uc-2\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\noriginal_id: uc-3\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\noriginal_id: uc-4\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\noriginal_id: uc-5\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/009-call-transcription-to-crm.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Call Transcription to CRM\"\nsidebar_label: 9. Call Transcription to CRM\nlayout: use_case\noriginal_id: uc-9\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/010-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Real-Time voice trades -> trade ticket population\"\nsidebar_label: 10. Real-Time voice trades -> trade ticket population\nlayout: use_case\noriginal_id: uc-10\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/013-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-13\ntitle: \"Use Case 13: User launches multiple apps from a single container\"\nsidebar_label: 13. User launches multiple apps from a single container\nlayout: use_case\noriginal_id: uc-13\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/015-sales-floor-base-workflow.md",
    "content": "---\nid: uc-15\ntitle: \"Use Case 15: Sales Floor Base Workflow\"\nsidebar_label: 15. Sales Floor Base Workflow\nlayout: use_case\noriginal_id: uc-15\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/016-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-16\ntitle: \"Use Case 16: Quantifying FDC3 Interactions\"\nsidebar_label: 16. Quantifying FDC3 Interactions\nlayout: use_case\noriginal_id: uc-16\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/017-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-17\ntitle: \"Use Case 17: Fine-tuning InterOp with Channels\"\nsidebar_label: 17. Fine-tuning InterOp with Channels\nlayout: use_case\noriginal_id: uc-17\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.0/use-cases/overview.md",
    "content": "---\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\noriginal_id: overview\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-2.0/why-fdc3.md",
    "content": "---\nsidebar_label: Why FDC3?\ntitle: Why FDC3?\noriginal_id: why-fdc3\n---\n\n## Why look for FDC3-enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go. \n\nThe main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3-enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context).\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still, much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc..\n\nEvery application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3-enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3-enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration. With an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/.markdownlint.jsonc",
    "content": "{\n\t//Disabled as we often use manual H1 heading for reference pages, \n\t// where the markdown metadata is picked up as the top level heading\n\t\"single-h1\": false,\n\t//Many lines in md files are longer than 80 chars\n\t\"line-length\": false,\n\t//We have repeated headings, like 'Properties' or 'Fields' in reference docs.\n\t\"no-duplicate-header\": {\n\t\t\"siblings_only\": true\n\t},\n\t\"no-inline-html\": {\n\t\t\"allowed_elements\": [\n\t\t\t\"Tabs\",\n\t\t\t\"TabItem\"\n\t\t]\n\t},\n\t\"ul-style\": {\n\t\t\"style\": \"dash\"\n\t}\n}"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.broadcast.md",
    "content": "---\nid: PrivateChannel.broadcast\nsidebar_label: PC.broadcast\ntitle: PrivateChannel.broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast` API call on a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.broadcast(context: Context)`](../../api/ref/Channel#broadcast) (inherited from the [Channel](../../api/ref/Channel#broadcast) class)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.broadcast()\n    DA ->> DAB: PrivateChannel.broadcast\n    DAB ->> DB: PrivateChannel.broadcast\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelBroadcastAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelBroadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelBroadcastBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelBroadcastBridgeRequest.schema.json)\n\n### Example\n\n```javascript\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const privateChannel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = privateChannel.onAddContextListener((contextType) => {\n        // broadcast price quotes as they come in from our quote feed\n        feed.onQuote(symbol, (price) => {\n            privateChannel.broadcast({ type: \"price\", price});\n        });\n    });\n\n    ...\n\n    return channel;\n});\n```\n\nBroadcast messages that are sent from Agents that received the private channel from a remote agent are sent to the Desktop Agent that created the channel and returned it as an `IntentResult`, which is responsible for forwarding them onto other subscribers. If a broadcast message is generated on the Agent that created the channel it simply forwards it onto each subscriber.\n\nHence, the broadcast message should be repeated once for each subscriber, and modified such that it includes a destination, specified as a full `AppIdentifier`, and the `type` should indicate that it is a `PrivateChannel` broadcast:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.broadcast\", //modified type for PrivateChannel broadcasts\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.eventListenerAdded.md",
    "content": "---\nid: PrivateChannel.eventListenerAdded\nsidebar_label: PC.eventListenerAdded\ntitle: PrivateChannel.eventListenerAdded\n---\n\nDesktop Agent bridging message exchange for the addition of an event handler to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.onAddContextListener(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onaddcontextlistener)\n- [`PrivateChannel.onUnsubscribe(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onunsubscribe)\n- [`PrivateChannel.onDisconnect(handler: () => void): Listener`](../../api/ref/PrivateChannel#ondisconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application adds one of these event listeners to a private channel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel to facilitate routing of event messages. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: adds an event listener\n    DA ->> DAB: PrivateChannel.eventListenerAdded\n    DAB ->> DB: PrivateChannel.eventListenerAdded\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerAddedAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelEventListenerAddedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerAdded\",\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.eventListenerRemoved.md",
    "content": "---\nid: PrivateChannel.eventListenerRemoved\nsidebar_label: PC.eventListenerRemoved\ntitle: PrivateChannel.eventListenerRemoved\n---\n\nDesktop Agent bridging message exchange for the removal of an event handler from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe(): void`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) functions:\n    - [`onAddContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onaddcontextlistener)\n    - [`onUnsubscribe(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onunsubscribe)\n    - [`onDisconnect(handler: () => void): Promise<Listener>`](../../api/ref/PrivateChannel#ondisconnect)\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application removes an event listener from a PrivateChannel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel so it can discard retained routing information. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: removes an event listener\n    DA ->> DAB: PrivateChannel.eventListenerRemoved\n    DAB ->> DB: PrivateChannel.eventListenerRemoved\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerRemoved\",\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.onAddContextListener.md",
    "content": "---\nid: PrivateChannel.onAddContextListener\nsidebar_label: PC.onAddContextListener\ntitle: PrivateChannel.onAddContextListener\n---\n\nDesktop Agent bridging message exchange for the addition of a [`ContextHandler`](../../api/ref/Types#contexthandler) to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is added to a `PrivateChannel` any applications that have added an `onAddContextListener` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.addContextListener()\n    DA ->> DAB: PrivateChannel.onAddContextListener\n    DAB ->> DB: PrivateChannel.onAddContextListener\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onAddContextListener\",\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.onDisconnect.md",
    "content": "---\nid: PrivateChannel.onDisconnect\nsidebar_label: PC.onDisconnect\ntitle: PrivateChannel.onDisconnect\n---\n\nDesktop Agent bridging message exchange for a `disconnect()` API call on  [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen the `disconnect` function is is called on a `PrivateChannel` any applications that have added an `onDisconnect` handler or an `onUnsubscribe` handler (which is automatically called when an application disconnects) MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information. If the `PrivateChannel` was created by a remote agent, only the single `PrivateChannel.onDisconnect` is required. It is the responsibility of the Desktop Agent that created the channel to ensure that any relevant `onUnsubscribe` handlers are also called by sending additional `PrivateChannel.onUnsubscribe` messages to them before forwarding the `PrivateChannel.onDisconnect`. This applies whether the disconnection occurred on that agent or on a remote agent.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.disconnect()\n    DA ->> DAB: PrivateChannel.onDisconnect\n    DAB ->> DB: PrivateChannel.onDisconnect\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnDisconnectAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnDisconnectAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnDisconnectBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnDisconnectBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onDisconnect\",\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/PrivateChannel.onUnsubscribe.md",
    "content": "---\nid: PrivateChannel.onUnsubscribe\nsidebar_label: PC.onUnsubscribe\ntitle: PrivateChannel.onUnsubscribe\n---\n\nDesktop Agent bridging message exchange for the removal of a [`ContextHandler`](../../api/ref/Types#contexthandler) from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe()`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) function:\n    - [`addContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n- [`PrivateChannel.disconnect()`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is removed from a `PrivateChannel` (via `listener.unsubscribe`) any applications that have added an `onSubscribe` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: listener.unsubscribe()\n    DA ->>+ DAB: PrivateChannel.onUnsubscribe\n    DAB ->>+ DB: PrivateChannel.onUnsubscribe\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json)\n\n### Example\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.onUnsubscribe\",\n    \"payload\": {\n        \"channel\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/broadcast.md",
    "content": "---\nid: broadcast\nsidebar_label: broadcast\ntitle: broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast()` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent) or a [`Channel`](../../api/ref/Channel). Generated by API calls:\n\n- [`fdc3.broadcast(context: Context): Promise<void>`](../../api/ref/DesktopAgent#broadcast)\n- [`Channel.broadcast(context: Context): Promise<void>`](../../api/ref/Channel#broadcast)\n\n:::caution\n\nBroadcasts on a [`PrivateChannel`](../../api/ref/PrivateChannel) have a separate message exchange, see [`PrivateChannel.broadcast`](PrivateChannel.broadcast).\n\n:::\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\nE.g.\n\n```javascript\nfdc3.broadcast(contextObj);\n```\n\nor\n\n```javascript\n(await fdc3.getOrCreateChannel(\"myChannel\")).broadcast(contextObj)\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.broadcast() / channel.broadcast()\n    DA ->> DAB: broadcastRequest\n    DAB ->> DB: broadcastRequest\n    DAB ->> DC: broadcastRequest\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/broadcastAgentRequest.schema.json](pathname:///schemas/2.1/bridging/broadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/broadcastBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/broadcastBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/ }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2022-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nwhich it repeats on to agent-B AND agent-C with the `source.desktopAgent` metadata added.\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/findInstances.md",
    "content": "---\nid: findInstances\nsidebar_label: findInstances\ntitle: findInstances\n---\n\nDesktop Agent bridging message exchange for a `findInstances` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>`](../../api/ref/DesktopAgent#findinstances)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)** or **Request Response (single)**\n\nA Desktop Agent's [`findInstances`](../../api/ref/DesktopAgent#findinstances) API call should return an empty array for known applications and [`ResolveError.NoAppsFound`](../../api/ref/Errors#resolveerror) for unknown apps. Hence, if a findInstances request is received through bridging for a known app with no instances then a normal response should be returned with an empty array. The bridge should add the responding agent to the `sources` array in the collated response as this is a valid response. If the application is not known to the agent an error response should be used instead with the `ResolveError.NoAppsFound` message and the responding Desktop Agent should be added to the `meta.errorSources` of the bridge response.\n\nIn the event that all agents returned an error response, then the bridge will also return an error response, which is passed back to the calling application. However, if any agent returned a valid response (including with an empty array) then the application was known, but had no instances, resulting in an empty array being returned to the calling application.\nE.g.\n\n```javascript\n// Retrieve a list of all instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Retrieve a list of instances of an application on a specified Desktop Agent\nlet instances = await fdc3.findInstances({appId: \"MyAppId\", desktopAgent: \"agent-A\"});\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findInstances()\n    DA ->> DAB: findInstancesRequest\n    DAB ->> DB: findInstancesRequest\n    DAB ->> DC: findInstancesRequest\n    DB ->> DAB: findInstancesResponse (B)\n    DC ->> DAB: findInstancesResponse (C)\n    DAB ->> DA: findInstancesResponse (B + C)\n    DA --) AA: resolve (AppIdentifier[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentRequest.schema.json](pathname:///schemas/2.1/bridging/findInstancesAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/findInstancesBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n:::note\nIf the `findInstancesRequest` from the requesting agent does not include a `meta.source` field then the Bridge MUST set the `meta.source.desktopAgent` field to attribute the request to the requesting agent. This is the case for all agent request messages that don't require application details.\n:::\n\nIf results should be constrained to a particular Desktop Agent, then set a `desktopAgent` field in `payload.app` and a matching `destination` field in `meta`:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\": \"agent-B\" // destination agent\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"destination\": { \"desktopAgent\": \"agent-B\" }, //destination agent\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nThe Desktop Agent Bridge should only forward the request to the requested Desktop Agent and handle the message exchange as a **Request Response (single)**.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentResponse.schema.json](pathname:///schemas/2.1/bridging/findInstancesAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findInstancesAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/findInstancesBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findInstancesBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findInstancesBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, augmenting each appIdentifier with a `desktopAgent` field, producing the following collated response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n            //\"desktopAgent\" added by DAB\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\", \n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::info\nIf a target Desktop Agent was specified in the request (via a `desktopAgent` field in `payload.app`), then the DAB is not collating responses and does not need to generate a unique `meta.responseUuid` and MUST quote that given by the responding Desktop Agent.\n:::\n\n:::note\nIn the event that an agent times out or returns an error, where others respond, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources`.\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// DAB -> agent-A\n[\n    { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"688dbd5e-21dc-4469-b8cf-4b6a606f9a27\" } //local response\n]\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/findIntent.md",
    "content": "---\nid: findIntent\nsidebar_label: findIntent\ntitle: findIntent\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>`](../../api/ref/DesktopAgent#findintent)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with `appId: \"agentA-app1\"` and `instanceId: \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.findIntent(\"StartChat\", context);\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A \n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntent()\n    DA ->> DAB: findIntentRequest\n    DAB ->> DB: findIntentRequest\n    DAB ->> DC: findIntentRequest\n    DB ->> DAB: findIntentResponse (B)\n    DC ->> DAB: findIntentResponse (C)\n    DAB ->> DA: findIntentResponse (B + C)\n    DA --) AA: resolve (AppIntent)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentRequest.schema.json](pathname:///schemas/2.1/bridging/findIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/findIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C):\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\nNote that the `source.desktopAgent` field has been populated with the id of the agent that raised the requests, enabling the routing of responses.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentBridgeErrorResponse.schema.json)\n\n### Example\n\nNormal response from agent-A, where the request was raised.\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"myChat\" }\n    ]\n}\n```\n\nDA agent-B would produce the following response if the request was generated locally:\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n        { \"appId\": \"Symphony\", \n          \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n          \"title\": \"Symphony\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\" }\n    ]\n}\n```\n\nHence, the response it sends to the bridge is encoded as follows:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */ },\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\" }\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nNote the response UUID generated by the agent-B and the reference to the request UUID produced by agent-A where the request was originated. Further, note that the `AppMetadata` elements in the `AppIntent` do not have a `desktopAgent` field yet, and the `meta` element does not contain a `sources` element, both of which the bridge will add.\n\nDA agent-C would produce the following response locally:\n\n```json\n{\n    \"intent\":  { \"name\": \"StartChat\" },\n    \"apps\": [\n       { \"appId\": \"WebIce\"}\n    ]\n}\n```\n\nwhich is sent back over the bridge as a response to the request message as:\n\n```json\n// agent-C -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"appId\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"WebIce\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentC>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, producing the following collated response which is sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"intent\":  \"StartChat\",\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" }, //desktopAgent added by DAB\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\", \n                  \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::note\n\nIn the event that an agent referred to in the API call is not connected to the bridge, an agent that was connected times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` and the appropriate error ([`ResolveError.DesktopAgentNotFound`](../../api/ref/Errors#resolveerror), [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// agent-A -> requesting App\n{\n    \"intent\":  { \"name\": \"StartChat\", \"displayName\": \"Chat\" },\n    \"apps\": [\n        // local to this agent\n        { \"appId\": \"myChat\" },\n        //agent-B responses\n        { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"Symphony\", \n            \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n        //agent-C responses\n        { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n    ]\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/findIntentsByContext.md",
    "content": "---\nid: findIntentsByContext\nsidebar_label: findIntentsByContext\ntitle: findIntentsByContext\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntentsByContext(context: Context): Promise<Array<AppIntent>>`](../../api/ref/DesktopAgent#findintentsbycontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntentArr = await fdc3.findIntentsByContext(context);\n```\n\n:::note\nThe message exchanges for this API call are nearly identical to that used for [`findIntent()`](findIntent), differing only by the lack of an `intent` field in the request message payload and the structure of the response message (where an array of `AppIntents` is returned).\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntentsByContext\n    DA ->> DAB: findIntentsByContextRequest\n    DAB ->> DB: findIntentsByContextRequest\n    DAB ->> DC: findIntentsByContextRequest\n    DB ->> DAB: findIntentsByContextResponse (B)\n    DC ->> DAB: findIntentsByContextResponse (C)\n    DAB ->> DA: findIntentsByContextResponse (B + C)\n    DA --) AA: resolve (AppIntent[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentRequest.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C).\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/findIntentsByContextBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/findIntentsByContextBridgeErrorResponse.schema.json)\n\n### Example\n\nAn individual agent (for example agentB) would generate a local response as an array of `AppIntent` objects:\n\n```json\n[\n    {\n        \"intent\": { \"name\": \"StartChat\" },\n        \"apps\": [\n            { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n            { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n            { \"appId\": \"Symphony\", \n                \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                \"title\": \"Symphony\" },\n            { \"appId\": \"Slack\", \"title\": \"Slack\" }\n        ]\n    },\n    {\n        \"intent\": { \"name\": \"ViewProfile\" },\n        \"apps\": [\n            { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n            { \"appId\": \"myCRM\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"My CRM\" }\n        ]\n    }\n]\n```\n\nThis response is encoded and sent to the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\" }\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nEach `AppMetadata` object is augmented by the bridge with a `desktopAgent` field, the responding `DesktopAgentIdentifier` value is added to the `meta.sources` element and the message payload is collated with responses from other agents into a response to the requesting agent:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    //agent-B responses\n                    { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\", \n                        \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                    //agent-C response\n                    { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    //agent-A responses\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\",\n                    \"desktopAgent\": \"agent-B\" }\n                    //agent-C responses\n                    { \"appId\": \"riskToolkit\", \"title\": \"Client Risk Toolkit\", \"desktopAgent\": \"agent-C\" },\n                    { \"appId\": \"linkedIn\", \"title\": \"LinkedIn\", \"desktopAgent\": \"agent-C\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [\n            { \"desktopAgent\": \"agent-B\" }, \n            { \"desktopAgent\": \"agent-C\" }\n        ]\n    }\n}\n```\n\nFinally agent-A combines the payload received with it own response and returns it to the requesting application.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/getAppMetadata.md",
    "content": "---\nid: getAppMetadata\nsidebar_label: getAppMetadata\ntitle: getAppMetadata\n---\n\nDesktop Agent bridging message exchange for a `getAppMetadata` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`getAppMetadata(app: AppIdentifier): Promise<AppMetadata>`](../../api/ref/DesktopAgent#getappmetadata)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\nlet appIdentifier = { appId: \"myApp@my.appd.com\", desktopAgent: \"agent-B\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n:::info\n`fdc3.getAppMetadata` calls should only involve the Desktop Agent Bridge where a `desktopAgent` field appears in the AppIdentifier being queried, all other calls should be handled locally by the Desktop Agent. Hence, the `payload.app.desktopAgent` is required on all requests.\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.getAppMetadata()\n    DA ->> DAB: getAppMetadataRequest\n    DAB ->> DB: getAppMetadataRequest\n    DB ->> DAB: getAppMetadataResponse (B)\n    DAB ->> DA: getAppMetadataResponse (B)\n    DA --) AA: resolve (AppMetadata)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentRequest.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentResponse.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/getAppMetadataBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/getAppMetadataBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...] \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives the response, augments the appMetadata with a `desktopAgent` field, producing the following response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...],\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }]\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/open.md",
    "content": "---\nid: open\nsidebar_label: open\ntitle: open\n---\n\nDesktop Agent bridging message exchange for a `open` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>`](../../api/ref/DesktopAgent#open)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\n// Open an app without context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n\n// Open an app with context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier, contextObj);\n```\n\nNote that it is not currently possible to identify resolve all available applications within a Desktop Agent via the FDC3 API. Hence, `fdc3.open` calls without a specified `desktopAgent` field in their `AppIdentifier`, e.g.:\n\n```javascript\n// Open a target app via AppIdentifier, without a specified Desktop Agent \nlet AppIdentifier = {appId: 'myApp-v1.0.1'};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n```\n\nshould always be processed locally without be passed to the bridge.\n\nThe `fdc3.open` command should result in a single copy of the specified app being opened and its instance data returned, or an error if it could not be opened. When receiving a response from invoking `fdc3.open` via the Desktop Agent Bridge, the new app instances MUST be initialized before responding as the responding Desktop Agent will need to return an `AppIdentifier` with an `instanceId` field set.\n\nIf the remote Desktop Agent is not currently connected from the bridge, the [`OpenError.DesktopAgentNotFound` error](../../api/ref/Errors#openerror) should be returned in the response from the bridge and the promise returned  from the call to `fdc3.open` rejected with it.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.open()\n    DA ->> DAB: openRequest\n    DAB ->> DB: openRequest\n    DB ->> DAB: openResponse\n    DAB ->> DA: openResponse\n    DA --) AA: resolve (AppIdentifier)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/openAgentRequest.schema.json](pathname:///schemas/2.1/bridging/openAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/openBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/openBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"agent-B\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"DesktopAgentB\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/openAgentResponse.schema.json](pathname:///schemas/2.1/bridging/openAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/openAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/openAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/openBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/openBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/openBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/openBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from target Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nwhich is augmented and repeated on by the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/ref/raiseIntent.md",
    "content": "---\nid: raiseIntent\nsidebar_label: raiseIntent\ntitle: raiseIntent\n---\n\nDesktop Agent bridging message exchange for a `raiseIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`raiseIntent(intent: string, context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintent)\n- [`raiseIntentForContext(context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintentforcontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Multiple Response (single)**\n\nFor Desktop Agent Bridging, a `raiseIntent` message exchange MUST always pass an `app: AppIdentifier` argument to target the intent. Further, if no `instanceId` is set in the `AppIdentifier`, then it should be interpreted to mean *'spawn a new instance of the target application'*. A local FDC3 API implementation call would normally defer to a resolver UI or similar if there are multiple options for resolving a specified `appId` (i.e. existing instance(s) and the option spawning a new instance), whereas this message exchange assumes that resolution has already taken place on the source Desktop Agent.\n\nHence, if a target [`AppIdentifier`](../../api/ref/Types#appidentifier) is not passed in the original `DesktopAgent` API call, then the [`findIntent`](findIntent) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange may then be used (if a remote option was selected as the resolution) to raise the intent.\n\n:::info\n\nThe same approach applies to `fdc3.raiseIntentForContext` calls, in that a [`findIntentByContext`](findIntentsByContext) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange is then used (if a remote option was selected as the resolution) to raise the intent.\n\n:::\n\ne.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context);\n```\n\nAgent A should then conduct the `findIntent` message exchange as described above, displaying its Intent resolver UI if necessary. Once an option is selected, the `raiseIntent` message exchange is conducted as if the API call had been made with a target app:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context, {\"appId\": \"Slack\", \"desktopAgent\": \"agent-B\"});\n```\n\nIn the event that an agent referred to in the API call is not connected to the bridge, it is connected but times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` in the `raiseIntentResponse` and the appropriate error (which might include any error from the [`ResolveError`](../../api/ref/Errors#resolveerror) enumeration, [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::tip\n\nDesktop Agents MAY support the deprecated `raiseIntent` signature that uses the app `name` field by using the `findIntent` message exchange to attempt to resolve the `name` to an `AppIdentifier`.\n\n:::\n\n## Message exchange\n\n:::note\n\nAgent-C is not involved in the diagram below as the `raiseIntent` is always specified with a target application and Desktop Agent.\n\n:::\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.raiseIntent \n    DA ->> DAB: raiseIntentRequest\n    DAB ->> DB: raiseIntentRequest\n    DB ->> DAB: raiseIntentResponse\n    DAB ->> DA: raiseIntentResponse\n    DA -->> AA: resolve (IntentResolution)\n    AA --) DA: resolution.getResult()\n    DB ->> DAB: raiseIntentResultResponse\n    DAB ->> DA: raiseIntentResultResponse\n    DA --) AA: resolve (IntentResult)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentRequest.schema.json](pathname:///schemas/2.1/bridging/raiseIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeRequest.schema.json](pathname:///schemas/2.1/bridging/raiseIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": { // AppIdentifier for chosen resolution including desktopAgent value\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\nThe bridge fills in the `source.desktopAgent` field and forwards the request to the target Desktop Agent:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": {\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultAgentResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentResultAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultAgentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentResultAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentBridgeErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultBridgeResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentResultBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.1/bridging/raiseIntentResultBridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/raiseIntentResultBridgeErrorResponse.schema.json)\n\n### Example\n\nIf the `raiseIntent` request were made locally, agent-B would deliver the intent and context to the target app's `IntentHandler` and respond to the raising application with an `IntentResolution`:\n\n```javascript\n{\n    \"intent\": \"StartChat\",\n    \"source\": {\n        \"appId\": \"Slack\",\n        \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"   \n    },\n    getResult: ƒ\n}\n```\n\nThis is encoded and sent to the bridge (omitting the `getResult()` function) as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"      \n            }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nWhen producing a response to a `raiseIntent` request, the instance of the receiving application MUST be initialized (if it does not already exist) and an `instanceId` generated for it before the `IntentResolution` is generated so that it can include the `instanceId`.\n\n:::\n\nThe bridge will fill in the `intentResolution.source.DesktopAgent` & `source.desktopAgent` and relay the message back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\",\n                \"desktopAgent\": \"agent-B\" // added by DAB\n            }  \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nWhen `Slack` produces an `IntentResult` from its `IntentHandler`, or the intent handler finishes running without returning a result, it should send a further `raiseIntentResultResponse` message to indicate that it's finished running and to pass any `IntentResult` onto the raising application (setting either `payload.intentResult.context` or `payload.intentResult.channel` to indicate the type of the `IntentResult`, or leaving `payload.intentResult` empty to indicate a `void` result). There is no need to provide a `source` field in this response as the source information was already provided in the `raiseIntentResponse` message preceding it.\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"intentResult\": {\n            \"context\": {/*contextObj*/}\n            /* for a channel IntentResult use:\n            \"channel\": {\n                \"id\": \"app-channel xyz\",\n                \"type\": \"user\"\n            }\n\n            or for a void result use leave this object empty.\n            */\n\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\", //a different UUID should be used for the result response\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nIf intent result is private channel see [PrivateChannels](../spec#privatechannels) for additional message exchanges that may be needed.\n\n:::\n\nFinally, the bridge augments the response with `sources[0].desktopAgent` and passes it back to Agent-A.\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nIf the `IntentHandler` returned `void` rather than an intent result `payload` should be empty, e.g.:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {},\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/agent-bridging/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Agent Bridging Overview (2.1)\n---\n\n:::info _[@experimental](../fdc3-compliance#experimental-features)_\n\nDesktop Agent Bridging is an experimental feature added to FDC3 in 2.1, hence, its design may change in the future and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\n<!-- ## TODO list\n\n* Expand on how the DAB should create the JWT token (and its claims, which must change to avoid replay attacks) which it sends out in the `hello` message for DAs to validate.\n* Link to BackPlane project somewhere \n\n-->\n\nThe FDC3 Desktop Agent API addresses interoperability between apps running within the context of a single Desktop Agent (DA), enabling cross-application workflows and context sharing.\n\n![A single desktop and FDC3 Desktop Agent](/assets/dab-overview-1.png)\n\nIt is clear, however, that user desktops are substantially more complicated in reality. Some Desktop Agent implementations already provide additional features allowing \"external\" applications (e.g. those not launched by the Desktop Agent) to connect in order to participate in interoperability.\n\n![A single desktop and Desktop Agent, with external apps](/assets/dab-overview-2.png)\n\nFirms that make extensive use of FDC3 have also identified use cases where interoperability workflows span different physical desktops, and have built proprietary bridging solutions (e.g. [Backplane](https://backplane.finos.org/) was originally developed as an in-house solution to this problem).\n\n![Two physical desktops with a desktop agent each](/assets/dab-overview-3.png)\n\nWith the success of FDC3, usage of vendor-provided Desktop Agents has increased substantially among banks and buy-side institutions. Buy-side firms who are clients of multiple banks' platforms have multiple desktop agents delivered to their desktops. Several software vendors also deliver FDC3-compatible software: some as apps that can run in any Desktop Agent, but some as self-contained applications running in their own desktop agent. They are often multi-component suites of functionality with a customized user experience, and are not simple to export to a different Desktop Agent. In these cases, being able to provide a single installable platform bundled with a Desktop Agent is a far more practical solution for the vendor and customer.\n\n![Two physical desktops, one with multiple desktop agents](/assets/dab-overview-4.png)\n\nHowever, unless the Desktop Agents themselves can interoperate, unfortunately, this approach prevents interoperability rather than promoting it. To support user workflows spanning the whole environment there needs to be some form of network connectivity between Desktop Agents.\n\nDesktop Agent Bridging addresses the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can also interoperate, allowing workflows to span multiple Desktop Agents. This is achieved, without implementation changes or special handling in the apps, by providing a protocol and service for the Desktop Agents to interoperate with each other instead, allowing application interop to extend across the bridged agents, seamlessly.\n\nIn any Desktop Agent Bridging scenario, it is expected that each DA is being operated by the same user (as the scope of FDC3 contemplates cross-application workflows for a single user, rather than cross-user workflows), although DAs may be run on different machines operated by the same user. Whether a bridge is running for Desktop Agents to connect to, whether it requires the agents to authenticate etc., is in the hands of the user (and their local IT team).\n\n## Bridging Desktop Agents\n\nThe Desktop Agent Bridging Part of the FDC3 Standard is composed of three components:\n\n- **[Connection](#connection)**: A means for Desktop Agents to communicate with a bridge, and through that bridge, with each other.\n- **[Connection Protocol](#connection-protocol)**: A protocol defining message exchanges necessary to connect to a Bridge and to perform initial state synchronization.\n- **[Messaging Protocol](#messaging-protocol)**: A protocol defining message exchanges that allow FDC3 API interop to extend across multiple Desktop Agents.\n\nDetail on each of these components is defined in the following sections.\n\n:::note\n\nAlthough this specification defines a particular [connection](#connection) type (based on a websocket server), it has been divided into parts so that the protocol definitions might be reused to implement a bridge over an alternative connection in future.\n\n::: \n\n:::tip\n\nThe Desktop Agent Bridging protocol has been designed such that an application using the FDC3 API does not need to make any significant changes in order to make use of the Bridging connection between its Desktop Agent and another agent. This is achieved via messaging workflows that allow the bridged agents to cooperate on behalf of the applications, for example, by retrieving options for intent resolution from other agent or forwarding on messages that were broadcast on channels.\n\nHowever, Bridging should still be visible to applications, which is achieved through the addition of a `desktopAgent` field to the `AppIdentifier` type allowing it to indicate that an app or app instance exists on another agent, as well as a number of new error messages that may be returned to indicate bridging issues.\n\n:::\n\n### Agent Bridging Compliance\n\nAgent Bridging is introduced in FDC3 2.1 as an [@experimental](../fdc3-compliance#experimental-features) feature of the FDC3 Standard, included to enable implementation by and feedback from the FDC3 community. As such, it is currently optional for the purposes of compliance and is exempted from the normal versioning and deprecation polices in order to facilitate any refinement needed.\n\n### JSON Message Protocol & JSON Schema\n\nThe connection and messaging protocols that the Desktop Agent Bridging Part defines are based on messages encoded in JSON. [JSON Schema](https://json-schema.org/) is used to define the format of each message in the protocol and should be considered the 'source of truth' for each and may be used to validate that individual messages are in the correct format. However, examples are provided in the documentation in TypeScript and JavaScript formats for convenience. TypeScript interfaces for individual messages, included in the FDC3 NPM module, are generated from the JSON Schema source files using [quicktype](https://quicktype.io/).\n\n## Connection\n\n### Topology\n\nIn order to implement Desktop Agent Bridging some means for Desktop Agents to connect to and communicate with each other is needed. This Standard assumes that Desktop Agent Bridging is implemented via a standalone 'bridge' which each agent connects to and will use to route messages to or from other agents. This topology is similar to a star topology in networking, where the Desktop Agent Bridge (a 'bridge') will be the central node acting as a router.\n\n```mermaid\nflowchart TD;\n    A[DA A]\n    B[DA B]\n    C[DA C]\n    D[DA D]\n    E{Bridge} \n    E <--> |websocket| A\n    E <--> |websocket| B\n    C <--> |websocket| E\n    D <--> |websocket| E\n```\n\nOther possible topologies include peer-to-peer or client/server networks, however, these introduce significant additional complexity into multiple aspects of the bridging protocol that must be implemented by Desktop Agents, (including discovery, authentication and message routing), where a star topology/standalone bridge enables a relatively simple set of protocols, with the most difficult parts being implemented in the bridge itself.\n\nWhilst the standalone bridge represents a single point of failure for the interconnection of Desktop Agents, it will also be significantly simpler than a full Desktop Agent implementation. Further, failures may be mitigated by setting the bridge up as a system service, such that it is started when the user's computer is started and may be restarted automatically if it fails. In the event of a bridge failure or manual shutdown, then Desktop Agents will no longer be bridged and should act as single agents.\n\nBy using the Desktop Agent Bridging Connection and Messaging protocols, a bridge will implement \"server\" behavior by:\n\n- Accepting connections from client Desktop Agents, receiving and authenticating credentials and assigning a name (for routing purposes)\n- Receiving requests from client Desktop Agents.\n- Routing requests to client Desktop Agents.\n- Receiving responses from client Desktop Agents and collating them.\n- Routing responses to client Desktop Agents.\n\nA Desktop Agent will implement \"client\" behavior by:\n\n- Connecting to the bridge, providing authentication credentials and receiving an assigned named (for routing purposes).\n- Forwarding requests to the bridge.\n- Awaiting response(s) from the bridge.\n- Receiving requests from the bridge.\n- Sending responses to the bridge.\n\nHence, message paths and propagation are simple. All messages to other Desktop Agents are passed to the bridge for routing and all messages (both requests and responses) are received back from it, i.e. the bridge is responsible for all message routing.\n\n#### Multi-Machine Use Cases\n\nIn financial services it is not unusual for a single user to be working with applications on more than one desktop. As Desktop Agents do not span desktops bridging Desktop Agents across multiple machines is an additional use case for Desktop Agent bridging. However, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user.\n\n```mermaid\nflowchart LR;\n    A[DA A]\n    B[DA B]\n    B1{Bridge 1} \n    C[DA C]\n    D[DA D]\n    B2{Bridge 2}\n\n    subgraph PC1 [PC 1]\n      direction RL\n      B1 <--> |websocket| A\n      B1 <--> |websocket| B\n    end\n    subgraph PC2 [PC 2]\n      direction LR\n      B2 <--> |websocket| C\n      B2 <--> |websocket| D\n    end\n    PC1 .- |Bridge interconnect| PC2\n```\n\nHowever, cross-machine routing is currently considered to be an internal concern of a Desktop Agent Bridge implementation, with each Desktop Agent simply communicating with a bridge instance located on the same machine. Hence, the connection protocol between bridges themselves is currently beyond the scope of this standard and my be implemented via any suitable means.\n\nFurther, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user. However, methods of verifying the identity of users are currently beyond the scope of the Standard.\n\n### Websocket Connection\n\nConnections between Desktop Agents and the Desktop Agent Bridge will be made via websocket connections, with the bridge acting as the websocket server and each connected Desktop Agent as a client.\n\nThe bridge MUST run on the same machine as the Desktop Agents, and the websocket MUST be bound to the loopback adapter IP address (127.0.0.1), ensuring that the websocket is not exposed to wider networks.\n\nBridge implementations SHOULD default to binding the websocket server to a port in the recommended port range 4475 - 4575, enabling simple discovery of a running bridge via attempting socket connections to ports in that range and attempting a handshake (as defined later in this proposal) that will identify the websocket as belong to a Desktop Agent Bridge. A port range MAY be used, in preference to a single nominated port, in order to enable the automatic resolution of port clashes with other services.\n\nBoth DAs and bridge implementations SHOULD support at least connection to the recommended port range and MAY also support configuration for connection to an alternative bridging port or port range.\n\n#### WebSockets and Multiple Machines\n\nAs the bridge binds its websocket on the loopback address (127.0.0.1) it cannot be connected to from another device. Hence, an instance of the standalone bridge may be run on each device and those instances exchange messages by other means in order to implement the bridge cross-device.\n\n## Connection Protocol\n\nOn connection to the bridge's websocket, a handshake must be completed that may include an authentication step before a name is assigned to the Desktop Agent for use in routing messages. The purpose of the handshake is to allow:\n\n- The Desktop Agent to confirm that it is connecting to the Desktop Agent Bridge, rather than another service exposed via a websocket.\n- The Desktop Agent Bridge to require that the Desktop Agent authenticate itself, allowing it to control access to the network of bridged Desktop Agents.\n- The Desktop Agent to request a particular name by which it will be addressed by other agents and for the bridge to assign the requested name, after confirming that no other agent is connected with that name, or a derivative of that name if it is already in use.\n\nThe bridge is ultimately responsible for assigning each Desktop Agent a name and for routing messages using those names. Desktop Agents MUST accept the name they are assigned by the bridge.\n\nExchange standardized handshake messages that identify:\n\n- That the server is a bridge, including:\n  - implementation details for logging by DA.\n  - supported FDC3 version(s).\n- That the client is an FDC3 DA, including:\n  - implementation details (ImplementationMeta returned by fdc3.getInfo() call) for logging by DA and sharing with other DAs.\n    - already includes supported FDC3 version.\n  - request for a specific agent name.\n\n```mermaid\nsequenceDiagram\n    participant DA as Desktop Agent A\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    DA -->>+ DAB: connect (step 1)\n    DAB ->>+ DA: hello (step 2)\n    DA ->>+ DAB: handshake (steps 3-5)\n    DAB ->>+ DA: connectedAgentsUpdate (step 6)\n    DAB ->>+ DB: connectedAgentsUpdate (step 6)\n    DAB ->>+ DC: connectedAgentsUpdate (step 6)\n```\n\n### Step 1. Connect to Websocket\n\nThe Desktop Agent attempts to connect to the websocket at the first port in the defined port range. If a connection cannot be made on the current port, move to the next port in the range and reattempt connection.\n\nIn the event that there are no ports remaining in the range, the Desktop Agent SHOULD reset to the beginning of the range, SHOULD pause its attempts to connect and resume later (a minimum wait period of 5 seconds SHOULD be used)\n\nNote, if the Desktop Agent is configured to run at startup (of the user's machine) it is possible that the Desktop Agent Bridge may start later (or be restarted at some point). Hence, Desktop Agents SHOULD be capable of connecting to the bridge once they are already running (rather than purely at startup).\n\n### Step 2. Hello\n\nWhen a new connection is made to the Desktop Agent Bridge websocket, it sends a `hello` message, including its metadata.\n\n```typescript\n{\n    type: \"hello\",\n    payload: {\n        desktopAgentBridgeVersion: string,\n        supportedFDC3Versions: string[],\n        authRequired: boolean,\n        /** The DAB JWT authentication token */\n        authToken?: string\n    },\n    meta: {\n        timestamp: date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/connectionStep2Hello.schema.json](pathname:///schemas/2.1/bridging/connectionStep2Hello.schema.json)\n\nA Desktop Agent can use the structure of this message to determine that it has connected to a Desktop Agent Bridge (i.e by checking `msg.type === \"hello\" && msg.payload.desktopAgentBridgeVersion`), whether it supports a compatible FDC3 version and whether it is expected to provide authentication credentials in the next step (`if(msg.payload.authRequired) { ... }`).\n\nAn optional JWT token can be included in the `hello` message to allow the connecting agent to authenticate the bridge. Verification of the supplied JWT by the DA is optional but recommended, meaning that the DA SHOULD verify the received JWT when one is included in the `hello` message.\n\nIf no hello message is received, the message doesn't match the defined format or validation of the optional JWT fails, the Desktop Agent should return to step 1 and attempt connection to the next port in the range.  \n\n### Step 3. Handshake & Authentication\n\nThe DA must then respond to the `hello` message with a `handshake` request to the bridge, including an auth token (JWT) if required.\n\n```typescript\n{\n    type:  \"handshake\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** The JWT authentication token */\n        authToken?: string,\n        /** Metadata about the Desktop Agent connecting, normally retrieved within the \n         *  context of the Desktop Agent via `fdc3.getInfo()`.*/\n        implementationMetadata: {\n          /** The version number of the FDC3 specification that the implementation\n          *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1. */\n          fdc3Version: string,\n          /** The name of the provider of the FDC3 Desktop Agent Implementation\n           *  (e.g.Finsemble, io.Connect, OpenFin etc.). */\n          provider: string,\n          /** The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0). */\n          providerVersion: string,\n          /** Metadata indicating whether the Desktop Agent implements optional features of\n           *  the Desktop Agent API. */\n          readonly optionalFeatures: {\n            /** Used to indicate whether the exposure of 'originating app metadata' for\n             *  context and intent messages is supported by the Desktop Agent.*/\n            \"OriginatingAppMetadata\": boolean;\n            /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n             *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n             *  the Desktop Agent.*/\n            \"UserChannelMembershipAPIs\": boolean;\n          }\n        },\n        /** The requested DA name */\n        requestedName: string,\n        /** The current state of the Desktop Agent's channels, excluding any private channels,\n         *  as a mapping of channel id to an array of Context objects, most recent first.*/\n        channelsState: Record<string, Context[]>\n    },\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/connectionStep3Handshake.schema.json](pathname:///schemas/2.1/bridging/connectionStep3Handshake.schema.json)\n\nNote that the `meta` element of of the handshake message contains both a `timestamp` field (for logging purposes) and a `requestUuid` field that should be populated with a Universally Unique Identifier (UUID), generated by the Desktop Agent. This `responseUuid` will be used to link the handshake message to a response from the Desktop Agent Bridge that assigns it a name. For more details on UUID generation see [Universally Unique Identifier](#universally-unique-identifier) section.\n\nIf requested by the server, the JWT auth token payload should take the form:\n\n```typescript\n{\n    \"sub\": string, // UUID for the key pair used to sign the token\n    \"iat\": date    // timestamp at which the the token was generated as specified in ISO 8601\n}\n```\n\ne.g.\n\n```json\n{\n    \"sub\": \"65141135-7200-47d3-9777-eb8786dd31c7\",\n    \"iat\": \"2022-07-06T10:11:43.492Z\"\n}\n```\n\nNote that the `sub` SHOULD be a UUID that does NOT need to match the name requested by the Desktop Agent. It will be used to identify the key pair that should be used to validate the JWT token. Further, multiple Desktop Agent's MAY share the same keys for authentication and hence the same `sub`, but they will be assigned different names for routing purposes by the Desktop Agent Bridge. If an agent disconnects from the bridge and later re-connects it MAY request and be assigned the same name it connected with before.\n\n### Step 4. Auth Confirmation and Name Assignment\n\nThe Desktop Agent Bridge will extract the authentication token `sub` from the JWT token's claims and then verify the token's signature against any public key it has been configured with. If the signature can't be verified, the bridge should respond with the below authentication failed message and the socket should be disconnected by the bridge.\n\n```typescript\n{\n    type:  \"authenticationFailed\",\n    payload: {\n        message: string\n    },\n    meta: {\n        /** Timestamp at which response was generated */\n        timestamp:  Date,\n        /** UUID for the handshake request */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/connectionStep4AuthenticationFailed.schema.json](pathname:///schemas/2.1/bridging/connectionStep4AuthenticationFailed.schema.json)\n\nIf authentication succeeds (or is not required), then the Desktop Agent Bridge should assign the Desktop Agent the name requested in the `handshake` message, unless another agent is already connected with that name in which case it should generate a new name which MAY be derived from the requested name. Note that the assigned name is not communicated to the connecting agent until step 6.\n\n### Step 5. Synchronize the Bridge's Channel State\n\nChannels are the main stateful mechanism in the FDC3 that we have to consider. A key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync. To do so, the states must be synchronized whenever a new agent connects. Hence, the Bridge MUST process the `channelState` provided by the new agent in the `handshake` request, which MUST contain details of each known User Channel or App Channel and its state. The bridge MUST compare the received channel names and states to its own representation of the current state of channels in connected agents, merge that state with that of the new agent and communicate the updated state to all connected agents to ensure that they are synchronized with it.\n\nHence, if we assume that the state of each channel can be represented by an ordered array of context objects (most recent first - noting that only the first position, that of the most recent context broadcast, matters), the Desktop Agent Bridge MUST merge the incoming `channelsState` with the `existingChannelsState` as follows:\n\n```typescript\nObject.keys(channelsState).forEach((channelId) => {\n    if (!existingChannelsState[channelId]) {\n        //unknown channels: just adopt its state\n        existingChannelsState[channelId] = channelsState[channelId];\n    } else {\n        //known channels: merge state, with existing state taking precedence\n        const currentState = existingChannelsState[channelId];\n        const incoming = channelsState[channelId];\n        incoming.forEach((context) => {\n            //only add previously unknown context types to the state\n            if (!currentState.find(element => element.type === context.type)){\n                //add to end of array to avoid setting most recent context type at the beginning\n                currentState.push(context);\n            } \n            // else ignore any types that are already known          \n        });\n    }\n});\n```\n\nWhen multiple agents attempt to connect to the Desktop Agent Bridge at the same time, steps 3-6 of the connection protocol MUST be handled by the Desktop Agent Bridge serially to ensure correct channel state synchronization.\n\n### Step 6. Connected Agents Update\n\nThe updated `existingChannelsState` will then be shared with all connected agents along with updated details of all connected agents via a `connectedAgentsUpdate` message sent to all connected sockets. The newly connected agent will receive both its assigned name and channel state via this message. The `connectedAgentsUpdate` message will be linked to the handshake request by quoting the `meta.requestUuid` of the `handshake` message.\n\nThe `connectedAgentsUpdate` message will take the form:\n\n```typescript\n{\n    type:  \"connectedAgentsUpdate\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** Should be set when an agent first connects to the bridge and provide \n         * its assigned name. */\n        addAgent?: string,\n        /** Should be set when an agent disconnects from the bridge and provide \n         * the name that no longer is assigned. */\n        removeAgent?: string,\n        /** Desktop Agent Bridge implementation metadata of all connected agents. \n         *  Note that this object is extended to include a `desktopAgent` field \n         *  with the name assigned by the DAB. */\n        allAgents: ImplementationMetadata[],\n        /** The updated state of channels that should be adopted by the agents. \n         *  SHOULD only be set when an agent is connecting to the bridge. */\n        channelsState?: Record<string, Context[]> // see step4\n    },\n    meta: {\n        /** For a new connection, should be the same as the handshake requestUuid. \n         *  Should be the same as the responseUuid for a disconnection.\n        */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n        /** Timestamp at which response was generated */\n        timestamp:  date,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/connectionStep6ConnectedAgentsUpdate.schema.json](pathname:///schemas/2.1/bridging/connectionStep6ConnectedAgentsUpdate.schema.json)\n\nWhen an agent connects to the bridge, it and other agents connected to the bridge, should adopt the state of any channels that do not currently exist or do not currently contain state of a particular type. This synchronization is NOT performed via broadcast as the context being merged would become the most recent context on the channel, when other contexts may have been broadcast subsequently. Rather, it should be adopted internally by each Desktop Agent, merging it such that it would be received by applications that have added a context listener to the channel or call `channel.getCurrentContext()` on it.\n\nIt should be noted that Desktop Agents will not have context listeners for previously unknown channels, and SHOULD simply record that channel's state for use when that channel is first used.\n\nFor known channel names, the Desktop Agents MUST also compare their current state to that which they have just received and may need to internally adopt context of types not previously seen on a channel. As context listeners can be registered for either a specific type or all types some care is necessary when doing so (as only the most recently transmitted Context should be received by un-typed listeners). Hence, the new context MUST only be passed to a context listener if it was registered specifically for that type and a context of that type did not previously exist on the channel.\n\nIn summary, updating listeners for a known channel should be performed as follows:\n\n1. The incoming channel state `channelState` for a particular channel should be processed from last to first (most recent context broadcast).\n2. If there is no current context of that type, broadcast it to any listeners of that specific type only.\n3. If there is a current context of that type, and it does not match the incoming object exactly, broadcast it to listeners of that specific type only.\n4. If the most recent (first in the incoming array) type OR value of that type doesn't match the most recent context broadcast on the channel, broadcast it to un-typed listeners only.\n\nThis procedure is the same for both previously connected and connecting agents, however, the merging procedure used by the Desktop Agent Bridge in step 5 will result in apps managed by previously connected agents only rarely receiving context broadcasts (and only for types they have not yet seen on a channel).\n\nAfter applying the `connectedAgentsUpdate` message, the newly connected Desktop Agent and other already connected agents are able to begin communicating through the bridge.\n\n#### Channels\n\nIt is assumed that Desktop Agents SHOULD adopt the recommended 8 channel set (and the respective display metadata). Desktop Agents MAY support channel customization through configuration.\n\nThe Desktop Agent Bridge MAY support channel mapping ability, to deal with issues caused by differing channel sets.\n\nA key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync, which requires an initial synchronization step as part of the connection protocol.\n\n#### Atomicity and handling concurrent operations\n\nHandling by the Desktop Agent of the synchronization message from the Desktop Agent Bridge in step 6 of the connection protocol should be atomic to prevent message overlap with `fdc3.broadcast`, `channel.broadcast`, `fdc3.addContextListener` or `channel.getCurrentContext`. I.e. the `connectedAgentsUpdate` message must be processed immediately on receipt by Desktop Agents and updates applied before any other messages are sent or responses processed.\n\nSimilarly, the Desktop Agent Bridge must process steps 3-6 of the connection protocol (receiving a `handshake` messages up to issuing the `connectedAgentsUpdate` messages to all participants) as a single atomic unit, allowing no overlap with the processing of other messages from connected agents (as they might modify the state information it is processing during those steps).\n\n#### Notification to users of connection events\n\nDesktop Agents SHOULD provide visual feedback to end users when they or other agents connect or disconnect from the Desktop Agent Bridge (i.e. whenever a `connectedAgentsUpdate` message is received, or a disconnection happens). Doing so will ensure that the end user understands whether their apps and Desktop Agent can communicate with other apps running under other Desktop Agents, and can better attribute any issues with interoperability between them to the probable source.\n\n### Step 7. Disconnects\n\nAlthough not part of the connection protocol, it should be noted that the `connectedAgentsUpdate` message sent in step 6 should also be sent whenever an agent disconnects from the bridge to update other agents. If any agents remain connected, then the `channelState` does not change and can be omitted. However, if the last agent disconnects the bridge SHOULD discard its internal `channelState`, instead of issuing the update.\n\n## Messaging Protocol\n\nIn order for Desktop Agents to communicate with the Desktop Agent Bridge and thereby other Desktop Agents, a messaging protocol is required. FDC3 supports both 'fire and forget' interactions (such as the broadcast of context messages) and interactions with specific responses (such as raising intents and returning a resolution and optional result), both of which must be handled by that messaging protocol and message formats it defines, as described in this section.\n\n### Collating Responses\n\nWhilst some FDC3 requests are 'fire and forget' (e.g. broadcast) the main requests such as `findIntent` or `raiseIntent` expect a response. In a bridging scenario, the response can come from multiple Desktop Agents and therefore need to be aggregated and augmented before they are sent back to the requesting DA.\n\n:::note\nA set of classifications for message exchange types are provided in the [Individual message exchanges](#individual-message-exchanges) section.\n:::\n\nThe Desktop Agent Bridge is the responsible entity for collating responses together from all DAs. Whilst this approach may add some complexity to bridge implementations, it will simplify DA implementations since they only need to handle one response.\n\nThe Desktop Agent Bridge MUST allow for timeout configuration.\n\nThe Bridge SHOULD also implement timeout for waiting on DA responses. Assuming the message exchange will be all intra-machine, a recommended maximum timeout of 1500ms SHOULD be used. Similarly, Desktop Agents SHOULD apply a timeout to requests made to the bridge that require a response (collated or otherwise), to handle situations where the bridge is not responding as expected. A recommended maximum timeout of 3000ms SHOULD be used in this case.\n\n### Message Format\n\nAll messages sent or received by the Desktop Agent Bridge will be encoded in JSON and will have the same basic structure (including those already defined in the connection protocol):\n\n```typescript\n{\n    /** Identifier used to declare what aspect of FDC3 that the message relates to. */\n    type:  string,\n    /** Request body, containing any the arguments to the FDC3 interactions. */\n    payload: { ... },\n    /** Metadata relating to the message, its sender and destination. */\n    meta: { ... }\n}\n```\n\nMessages can be divided into four categories:\n\n- Requests from a Desktop Agent: Messages that initiate a particular interaction.\n- Requests forwarded by the Bridge: Messages augmented and forwarded on by the Bridge.\n- Responses from a Desktop Agent: Messages from a single Desktop Agent that respond to a prior request from the Bridge.\n- Responses collated and forwarded by the Bridge: Messages from the Bridge back to the Desktop Agent that initiated an interaction, which may combine the responses from multiple other Desktop Agents.\n\nDetails specific to each are provided in the following sections.\n\n#### Request Messages\n\nRequest messages from a Desktop Agent use the following format:\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the FDC3\n     * function name that the message relates to, e.g. 'findIntent', with \n     * 'Request' appended. */\n    type:  string,\n    /** Request body, typically containing the arguments to the function called.*/\n    payload: {\n        /** Used to indicate which channel `broadcast` functions were called on.*/\n        channelId?: string,\n        /** Used as an argument to `findIntent` and `raiseIntent` functions.`*/\n        intent?: string,\n        /** Used as an argument to `broadcast`, `findIntent` and `raiseIntent` \n         * functions.*/\n        context?: Context,\n        /** Used as an argument to `open`, `raiseIntent`, `getAppMetadata`, and \n         * `findInstances` functions.*/\n        app?: AppIdentifier,\n        /** Used as an argument to `findIntent` functions. */\n        resultType?: string,\n        /** Context type name used in Private Channel event messages. */\n        contextType?: string\n    },\n    /** Metadata used to uniquely identify the message and its sender. */\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date,\n         /** Field that represents the source application that the request was \n          * received from, or the source Desktop Agent if it issued the request \n          * itself. */\n        source: AppIdentifier | DesktopAgentIdentifier,\n        /** Optional field that represents the destination that the request\n         * should be routed to. Must be set by the Desktop Agent for API calls\n         * that include a target app parameter and must include the name of the\n         * Desktop Agent hosting the target application. */\n        destination?: AppIdentifier | DesktopAgentIdentifier\n    }\n}\n```\n\n**Request Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/agentRequest.schema.json](pathname:///schemas/2.1/bridging/agentRequest.schema.json)\n\nIf the FDC3 API call underlying the request message includes a target (typically defined by an `app` argument, in the form of an AppIdentifier object) it is the responsibility of the Desktop Agent to copy that argument into the `meta.destination` field of the message and to ensure that it includes a `meta.destination.desktopAgent` value. If the target is provided in the FDC3 API call, but without a `meta.destination.desktopAgent` value, the Desktop Agent should assume that the call relates to a local application and does not need to send it to the bridge.\n\nRequests without a `meta.destination` field will be forwarded to all other agents by the bridge, which will also handle the collation of responses which quote the `meta.requestUuid`.\n\n##### Request Messages Forwarded by the Bridge\n\nRequest messages forwarded by the Bridge onto other Desktop Agents use the same format as incoming requests from Desktop Agents, with the exception that the `desktopAgent` properties of the `meta.source` field MUST be provided, and should be overwritten by the Bridge (based on the connection that the message was received from) to prevent spoofing of request message origins.\n\n**Bridge Request Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/bridgeRequest.schema.json](pathname:///schemas/2.1/bridging/bridgeRequest.schema.json)\n\n#### Response Messages\n\nResponse messages from a Desktop Agent back to the Bridge use a similar format that is differentiated from requests by the presence of a `meta.responseUuid` field. They MUST also quote the `meta.requestUuid` that they are responding to.\n\n:::info\nResponse messages do not include a `meta.destination` as the routing of responses is handled by the Bridge via the `meta.requestUuid` field. They also do not include a `source` field as responses are currently always from the Desktop Agent, and the bridge is required to provide this information itself to prevent spoofing.\n:::\n\nThere are two types of each response message, a successful response and an error response.\n\n##### Successful Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/agentResponse.schema.json](pathname:///schemas/2.1/bridging/agentResponse.schema.json)\n\n##### Error Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error strings from an appropriate FDC3 API Error \n         *  enumeration. */\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/agentErrorResponse.schema.json](pathname:///schemas/2.1/bridging/agentErrorResponse.schema.json)\n\n##### Response Messages Collated and Forwarded by the Bridge\n\nResponses from individual Desktop Agents are collated by the Bridge and are forwarded on to the the Desktop Agent that initiated the interaction. The format used is very similar to that used for responses by the Desktop Agents, with the exception of the source information in the `meta` field. Specifically, the `meta.source` field does not need to be provided by agents, as responses are currently always provided by the Desktop Agent, whose details will be provided by the bridge when it receives the response. In responses from the bridge, the `meta.source` is replaced by two arrays, `meta.sources` and `meta.errorSources`, which provide details on the Desktop Agents that responded normally or responded with errors. The detail of any errors returned (in the `payload.error` field of a Desktop Agent's response) is collected up into a `meta.errorDetails` field. Moving the error details from the `payload` to the `meta` field enables the return of a valid response to the originating Desktop Agent in cases where some agents produced valid responses, and others produced errors.\n\nHence, for responses forwarded by the bridge there are two type of response messages from the Bridge returned to agents, one for requests that received at least one successful response, and another for use when all agents (or the targeted agent) returned an error.\n\n##### At Least One Successful Response\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for the sources\n         * that generated responses to the request. Will contain a single value\n         * for individual responses and multiple values for responses that were\n         * collated by the bridge. May be omitted if all sources errored. MUST\n         * include the `desktopAgent` field when returned by the bridge. */\n        sources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. May be omitted if all sources responded. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/bridgeResponse.schema.json](pathname:///schemas/2.1/bridging/bridgeResponse.schema.json)\n\n##### All Responses are Errors\n\n:::info\nIn this case there are no successful responses and the bridge must populate the `payload.error` field in the response to the agent with one of the error messages returned, so that the receiving Desktop Agent may return it to the app that made the original call.\n:::\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error string from an appropriate FDC3 API Error \n         *  enumeration. This should also appear in `meta.errorDetails`.*/\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/2.1/bridging/bridgeErrorResponse.schema.json](pathname:///schemas/2.1/bridging/bridgeErrorResponse.schema.json)\n\n### Identifying Individual Messages\n\nThere are a variety of message types that need to be sent between bridged Desktop Agents, several of which will need to be replied to specifically (e.g. a `fdc3.raiseIntent` call should receive an `IntentResolution` when an app has been chosen, and may subsequently receive an `IntentResult` after the intent handler has run). Hence, messages also need a unique identity, which should be generated at the Desktop Agent that is the source of that message, in the form of a Universally Unique Identifier (UUID). Response messages will include the identity of the request message they are related to, allowing multiple message exchanges to be 'in-flight' at the same time.\n\nHence, whenever a request message is generated by a Desktop Agent it should contain a unique `meta.requestUuid` value. Response messages should quote that same value in the `meta.requestUuid` field and generate a further unique identity for their response, which is included in the `meta.responseUuid` field. Where a response is collated by the Desktop Agent Bridge, the Bridge should generate its own `meta.responseUuid` for the collated response message.\n\nDesktop Agent Bridge implementations should consider request messages that omit `meta.requestUuid` and response messages that omit either `meta.requestUuid` or `meta.responseUuid` to be invalid and should discard them.\n\n#### Universally Unique Identifier\n\nA UUID (Universally Unique IDentifier), also known as a Globally Unique IDentifier (GUID), is a generated 128-bit text string that is intended to be 'unique across space and time', as defined in [IETF RFC 4122](https://www.ietf.org/rfc/rfc4122.txt).  \n\nThere are several types of UUIDs, which vary how they are generated. As Desktop Agents will typically be running on the same machine, system clock and hardware details may not provide sufficient uniqueness in UUIDs generated (including during the connect step, where Desktop Agent name collisions may exist). Hence, it is recommended that both Desktop Agents and Desktop Agent Bridges SHOULD use a version 4 generation type (random).\n\n### Identifying Desktop Agents Identity and Message Sources\n\nDesktop Agents will prepare messages in the above format and transmit them to the bridge. However, to target intents and perform other actions that require specific routing between DAs, DAs need to have an identity. Identities should be assigned to Desktop Agents when they connect to the bridge. This allows for multiple copies of the same underlying Desktop Agent implementation to be bridged and ensures that identity clashes can be avoided.\n\nTo facilitate routing of messages between agents, the `AppIdentifier` is expanded to contain an optional `desktopAgent` field:\n\n```typescript\ninterface AppIdentifier {\n  readonly appId: string;\n  readonly instanceId?: string;\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental Introduced in FDC3 2.1 and may be refined by further changes\n   *  outside the normal FDC3 versioning policy.\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\nFurther, a new `DesktopAgentIdentifier` type is introduced to handle cases where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. This is particularly relevant for `findIntent` message exchanges:\n\n```typescript\n/** @experimental Introduced in FDC3 2.1 and may be refined by further changes\n *  outside the normal FDC3 versioning policy. */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent. */ \n  readonly desktopAgent: string;\n}\n```\n\nHence, either an `AppIdentifier` or `DesktopAgentIdentifier` is used as the `meta.source` value of both request or response messages and the source Desktop Agent identity for bridging messages will always be found at `meta.source.desktopAgent`. To prevent spoofing and to simplify the implementation of clients, the source Desktop Agent identity MUST be added to (or overwritten in) each message by the bridge when received.\n\nA request message may include a `destination` field, set by the source Desktop Agent if the message is intended for a particular Desktop Agent (e.g. to support a `raiseIntent` call with a specified target app or app instance on a particular Desktop Agent).\n\nResponse messages do not include a `destination` field. Instead, a Desktop Agent Bridge implementation MUST retain a record of `requestUuid` fields for request message, until the request is fully resolved, allowing them to determine the destination for the collated responses and effectively enforcing the routing policy for interactions.\n\nFurther, the Desktop Agent Bridge should also inspect the `payload` of both request and response messages and ensure that any `AppIdentifier` objects have been augmented with the correct `desktopAgent` value for the app's host Desktop Agent (e.g. if returning responses to `findIntent`, ensure each `AppIntent.apps[]` entry includes the correct `desktopAgent` value). Further details of any such augmentation are provided in the description of each message exchange.\n\n### Handling of Error Responses\n\nThe FDC3 Desktop Agent API specifies a number of error enumerations that define specific error strings that should be used as the `message` element of a JavaScript `Error` to be returned to the requesting application via a rejected promise. In the event that an Error must be returned by a Desktop Agent to the Desktop Agent Bridge, the message should be selected from the [Error enumeration](../api/ref/Errors) normally used by the corresponding FDC3 function (i.e. `OpenError` for `open` calls, `ResolveError` for `findIntent` and `raiseIntent` etc.). However, Desktop Agent Bridging does NOT require that an `Error` object is returned across the bridge as it cannot be fully recreated from its constituent fields in JavaScript. Rather, return only the specified message string in the `error` field of the `payload`, which should then be used to initialize a JavaScript `Error` on the receiving end. It is also advisable to output additional logging (in the Desktop Agent Bridge) indicating that the error was originally generated by a remote Desktop Agent and to provide the relevant details.\n\nFor example, a `raiseIntent` targeted at an app instance that no longer exists might generate the following response from the Desktop Agent:\n\n```json\n// e.g. agent-B -> DAB in response to a raiseIntent call\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"error\": \"TargetInstanceUnavailable\", //<error string from the relevant error enum\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nFor messages that target a specific agent, the Desktop Agent Bridge will augment the message with source information and return it to the calling agent, which will then respond to the app that made the original request.\n\nIf all agents (or the targeted agent) return errors, then a suitable error string should be forwarded in the `payload.error` field as returned by at least one of the agents. This allows the agent that made the original request to return that error to the app that made the original API call. All agents that returned errors should be listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`).\n\nHowever, API calls that require a collated response from all agents where at least one agent returns a successful response, will result in a successful response from the Desktop Agent Bridge (i.e. no `error` element should be included), with the agents returning errors listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`). This allows for successful exchanges on API calls such as `fdc3.findIntent` where some agents do not have options to return and would normally respond with (for example) `ResolveError.NoAppsFound`.\n\nFinally, to facilitate easier debugging, errors specific to Desktop Agent Bridge are added to the Error enumerations, including:\n\n```typescript\nenum OpenError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n\nenum ResolveError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n```\n\nAnd an error enumeration is created for errors related to bridging that may occur on any request, and are returnable through the FDC3 API.\n\n```typescript\nenum BridgingError {\n  /** Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging,\n   * within the alloted timeout. */\n  ResponseTimedOut = 'ResponseToBridgeTimedOut',\n  /** Returned if a Desktop Agent that has been targeted by a particular request has\n   * been disconnected from the Bridge before a response has been received from it. */\n  AgentDisconnected = 'AgentDisconnected',\n  /** Returned for FDC3 API calls that are specified with arguments indicating that\n   *  a remote Desktop Agent should be targeted (e.g. raiseIntent with an app on a\n   *  remote DesktopAgent targeted), when the local Desktop Agent is not connected to\n   *  a bridge. */\n  NotConnectedToBridge = 'NotConnectedToBridge',\n  /** Returned if a message to a Bridge deviates from the schema for that message\n   * sufficiently that it could not be processed.\n   */\n  MalformedMessage = 'MalformedMessage'\n}\n```\n\n### Handling Malformed Messages\n\nIt is the Bridge's responsibility to validate all messages that flow to and from Desktop Agents. When a request message is malformed the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` error to the sender.  For 'request only' message exchanges, no specific error response schema is provided. Hence, the generic [Bridge Error Response Message schema](#all-responses-are-errors) should be used for such messages (with the type set to match the request message type).\n\nWhere responses to requests from other agents are malformed, the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` to the sender and record `BridgingError.MalformedMessage` as the error response from the responder that sent the malformed message.\n\n### Forwarding of Messages and Collating Responses\n\nWhen handling request messages, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive request messages from connected Desktop Agents.\n- Augment request messages with `meta.source.desktopAgent` information (as described above).\n- Forward request messages onto either a specific Desktop Agent or all other Desktop Agents.\n  - The bridge MUST NOT forward the request to the agent that sent the request, nor expect a reply from it.\n\nFor message exchanges that involve responses, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive and collate response messages (where necessary) according the `meta.requestUuid` (allowing multiple message exchanges to be 'in-flight' at once).\n- Augment response messages with `meta.source.desktopAgent` information (as described above).\n- Apply a timeout to the receipt of response messages for each request.\n- Produce a single collated response message (where necessary) that incorporates the output of each individual response received and has its own unique `meta.responseUuid` value.\n- Deliver the collated and/or augmented response message to the source Desktop Agent that sent the request.\n\nCollated response messages generated by the bridge use the same format as individual response messages.\n\nThe following pseudo-code defines how messages should be forwarded or collated by the bridge:\n\n- **if** the message is a request (`meta.requestUuid` is set, but `meta.responseUuid` is not),\n  - **if** the message includes a `meta.destination` field,\n    - forward it to the specified destination agent,\n    - annotate the request as requiring only a response from the specified agent,\n    - await the response or the specified timeout.\n  - **else**\n    - forward it to all other Desktop Agents (not including the source),\n    - annotate the request as requiring responses from all other connected agents,\n    - await responses or the specified timeout.\n- **else if** the message is a response (both `meta.requestUuid` and `meta.responseUuid` are set)\n  - **if** the `meta.requestUuid` is known,\n    - augment any `AppIdentifier` types in the response message with a `desktopAgent` field matching that of the responding Desktop Agent,\n    - **if** `payload.error` is set in the response add the DesktopAgentIdentifier to the `meta.errorSources` element.\n    - **else**\n      - add the DesktopAgentIdentifier to the `meta.sources` element.\n    - **if** the message exchange requires collation,\n      - add the message to the collated responses for the request,\n      - **if** all expected responses have been received (i.e. all connected agents or the specified agent has responded, as appropriate),\n        - produce the collated response message and return to the requesting Desktop Agent.\n      - **else**\n        - await the configured response timeout or further responses,\n        - **if** the timeout is reached without any responses being received\n          - produce and return an appropriate [error response](../api/ref/Errors), including details of all Desktop Agents in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n        - **else if** the timeout is reached with a partial set of responses,\n          - produce and return, to requesting Desktop Agent, a collated response and include details of Desktop Agents that timed out in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n    - **else**\n      - forward the response message on to requesting Desktop Agent.\n  - **else**\n    - discard the response message (as it is a delayed to a request that has timed out or is otherwise invalid).\n- **else**\n  - the message is invalid and should be discarded.\n\n### Workflows Broken By Disconnects\n\nTargeted request and request/response workflows may be broken when a Desktop Agent disconnects from the bridge, which bridge implementations will need to handle.\n\nThree types of requests:\n\n1. Fire and forget (i.e. `broadcast`).\n2. Requests that require the bridge to collate multiple responses from the bridged Desktop Agents (e.g. `findIntent`).\n3. Requests targeted at a specific Desktop Agent that are forwarded to the target Desktop Agent (e.g. `raiseIntent`).\n\nThe latter two types embody workflows that may be broken by an agent disconnecting from the bridge either before or during the processing of the request.\n\nWhen processing the disconnection of an agent from the bridge, the bridge MUST examine requests currently 'in-flight' and:\n\n- For requests that require the bridge to collate multiple responses:\n  - add the disconnected Desktop Agent's details to the `errorSources` array in the response and the `BridgingError.AgentDisconnected` message to the `errorDetails` array.\n  - complete requests that no longer require further responses (all other agents have responded), or\n  - continue to await the timeout (if other agents are yet to respond), or\n  - return an 'empty' response in the expected format (if no other agents are connected and no data will be received).\n- For requests that target a specific agent:\n  - return the `BridgingError.AgentDisconnected` in the response's `payload.error` field (as the request cannot be completed).\n\nFinally, in the event that either a Desktop Agent or the bridge itself stops responding, but doesn't fully disconnect, the timeouts (specified earlier in this document) will be used to handle the request as if a disconnection had occurred.\n\nIn the event that a Desktop Agent repeatedly times out, the bridge SHOULD disconnect that agent (and update other agents via the `connectedAgentsUpdate` message specified in the connection protocol), to avoid all requests requiring the full timeout to complete.\n\nIn the event that the bridge repeatedly times out, connected Desktop Agents MAY disconnect from the bridge and attempt to reconnect by returning to Step 1 of the connection protocol.\n\n### Individual message exchanges\n\nIndividual message exchanges are defined for each of the Desktop Agent methods that require bridging in the reference section of this Part.\n\nEach section assumes that we have 3 agents connected by a bridge (itself denoted by `DAB` in diagrams):\n\n- agent-A (denoted by `DA A` in diagrams)\n- agent-B (denoted by `DA A` in diagrams)\n- agent-C (denoted by `DA A` in diagrams)\n\nMessage exchanges come in a number of formats, which are known as:\n\n- **Request only**: A request message that does not require a response ('fire and forget'), such as a [`broadcast`](ref/broadcast).\n- **Request Response (single)**: A request message that expects a single response from a single Desktop Agent, such as `open` or `getAppMetadata`.\n- **Request Response (collated)**: A request message that expects responses from all other Desktop Agents that are collated by the bridge and returned as a single response to the requestor, such as `findIntent` or `findInstances`.\n- **Request Multiple Response (single)**: A request message that expects multiple responses from a single Desktop Agent, such as `raiseIntent`.\n\nThe message exchanges defined are:\n\n- [`broadcast`](ref/broadcast)\n- [`findInstances`](ref/findInstances)\n- [`findIntent`](ref/findIntent)\n- [`findIntentsByContext`](ref/findIntentsByContext)\n- [`getAppMetadata`](ref/getAppMetadata)\n- [`open`](ref/open)\n- [`raiseIntent`](ref/raiseIntent)\n- [`PrivateChannel.broadcast`](ref/PrivateChannel.broadcast)\n- [`PrivateChannel.eventListenerAdded`](ref/PrivateChannel.eventListenerAdded)\n- [`PrivateChannel.eventListenerRemoved`](ref/PrivateChannel.eventListenerRemoved)\n- [`PrivateChannel.onAddContextListener`](ref/PrivateChannel.onAddContextListener)\n- [`PrivateChannel.onUnsubscribe`](ref/PrivateChannel.onUnsubscribe)\n- [`PrivateChannel.onDisconnect`](ref/PrivateChannel.onDisconnect)\n\n#### PrivateChannels\n\n`PrivateChannels` are intended to provide a private communication channel for applications. In order to do so, there are differences in how their broadcasts and event messages (used to manage the channel's lifecycle) MUST be handled.\n\nBroadcasts and event messages should be addressed to the Desktop Agent that created the channel, which will route it to the relevant application and any other listeners. If any of those listeners are remote, the message should be repeated back to the bridge, once for each listener with the destination set as a full `AppIdentifier`. Both these messages and broadcast messages MUST NOT be repeated back to the application that generated them. The source information on repeated messages should be unmodified to ensure that the message is attributed to the original source.\n\nTo facilitate the addressing of messages to the relevant Desktop Agent and `AppIdentifier` some additional tracking of private channel metadata is necessary in each Desktop Agent (or Desktop Agent Bridge Client implementation). For applications receiving a private channel as an `IntentResult`, the `AppIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id. This data MUST be retained until the receiving application sends a `disconnect` message, after which it can be discarded. For applications that have created and returned a private channel, and have subsequently received event messages subscriptions (`onAddContextListener`, `onSubscribe`, `onDisconnect`) the `appIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id and listener type, which will facilitate repeating of messages to registered listeners. This data MUST be retained until the remote application sends a `disconnect` message or a message indicating that the listener has been removed.\n\n#### FDC3 API calls that do NOT generate bridge messages\n\nSome FDC3 API calls can be handled locally and do not need to generate request messages to the Desktop Agent Bridge, but are likely to be involved in other exchanges that do generate messages to the bridge (for example adding context or intent handlers). Those calls include:\n\n- `addContextListener` functions (excluding those for `PrivateChannel` instances)\n- `listener.unsubscribe` (excluding those for `PrivateChannel` instances)\n- `addIntentListener`\n- `getOrCreateChannel`\n- `createPrivateChannel`\n- `getUserChannels` and `getSystemChannels`\n- `joinUserChannel` and `joinChannel`\n- `getCurrentChannel`\n- `leaveCurrentChannel`\n- `getInfo`\n\nHowever, `PrivateChannel` instances allow the registration of additional event handlers (for the addition or removal of context listeners) that may be used to manage streaming data sent over them by starting or stopping the stream in response to those events. Hence, the following calls DO generate request messages when used on a PrivateChannel instance:\n\n- `addContextListener`\n- `listener.unsubscribe`\n- `disconnect`\n\n#### Message Schemas and generated sources\n\nJSONSchema definitions are provided for all Desktop Agent Bridging message exchanges (see links in each reference page), which may be used to validate the correct generation of messages to or from a bridge (a separate schema is provided for the agent and bridge versions of each message).\n\nThe JSONSchema definitions are also used to generate TypeScript interfaces for the messages to aid in implementation of a Desktop Agent Bridge or client library. These may be imported from the FDC3 npm module:\n\n```typescript\nimport { BridgingTypes } from \"@finos/fdc3\";\nconst aMessage: BridgingTypes.BroadcastAgentRequest\n```\n\nor\n\n```typescript\nimport { BroadcastAgentRequest } from \"@finos/fdc3/dist/bridging/BridgingTypes\";\nconst aMessage: BroadcastAgentRequest\n```\n\nSources may also be generated from the JSONSchema files for other languages.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/App-Channel-Tests.md",
    "content": "---\nid: App-Channel-Tests\nsidebar_label: App Channel Tests\ntitle: App Channel Tests\nhide_title: true\n---\n\n# App Channel Tests  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n## Basic Broadcast\n\n| App | Step               | Details                                                                    |\n|-----|--------------------|----------------------------------------------------------------------------|\n| A   | 1.Retrieve `Channel`    |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2.Add Context Listener |Add an _untyped_ context listener to the channel, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(null, handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(null, handler)` |\n| B   | 3.Retrieve `Channel`     | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4.Broadcast          | Broadcast an `fdc3.instrument` Context to the channel with: <br/>`testChannel.broadcast(<fdc3.instrument context>)`|\n| A   | 5.Receive Context    | The handler added in step 2 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- `ACBasicUsage1` Perform above test.\n\n## Current Context\n\n| App | Step               | Details                                                                    |\n|-----|--------------------|----------------------------------------------------------------------------|\n| B   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2.Broadcast          | Broadcast an `fdc3.instrument` to the channel using: <br/> `testChannel.broadcast(<fdc3.instrument context>)`|\n| A   | 3.Retrieve `Channel`   |Retrieve a `Channel` object representing the same 'App' channel B did (`test-channel`)|\n| A   | 4.Retrieve Current Context    | A gets the _current context_ of the user channel. via:  `await testChannel.getCurrentContext()` <br />Ensure that the instrument received by A is identical to that sent by B    |\n\n-  `ACBasicUsage2` Perform above test\n\n## Filtered Context\n\n| App | Step               | Details                                                         |\n|-----|--------------------|-----------------------------------------------------------------|\n| A   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2.Add Context Listener |Add a _typed_ context listener for `fdc3.instrument`, using: <br/> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(\"fdc3.instrument\", handler)`\n| B   | 3.Retrieve `Channel`   |Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4.Broadcast          | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument context>)` <br /> `testChannel.broadcast(<fdc3.contact context>)`|\n| A   | 5.Receive Context    | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received.                                                                   |\n\n-  `ACFilteredContext1`: Perform above test \n-  `ACFilteredContext2`: Perform above test, but add listeners for both `fdc3.instrument` and `fdc3.contact` in step2.  Ensure that both context objects are received. \n-  `ACFilteredContext3`: Perform above test, except creating a _different_ channel in app B. Check that you _don't_ receive anything (as the channels don't match).\n-  `ACFilteredContext4`: Perform above test, except that after creating the channel **A** creates another channel with a further _different_ channel id and adds a further context listener to it.  Ensure that **A** is still able to receive context on the first channel (i.e. it is unaffected by the additional channel) and does NOT receive anything on the second channel.\n-  `ACUnsubscribe`: Perform above test, except that after creating the channel **A** then `unsubscribe()`s the listener it added to the channel. Check that **A** does NOT receive anything.\n\n### App Channel History\n\n| App | Step               | Details                                                 |\n|-----|--------------------|---------------------------------------------------------|\n| A   | 1.Retrieve `Channel` |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br/>`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2.Retrieve `Channel` |Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 3.Broadcast          |B broadcasts both the instrument context and a contact context, using: <br /> `testChannel.broadcast(<fdc3.instrument context>)` <br /> `testChannel.broadcast(<fdc3.contact context>)` |\n| A   | 4.Add Context Listener| A adds a context listener to the channel *after* B has completed all its broadcasts, via: <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `testChannel.addContextListener(\"fdc3.instrument\", handler)` <br /> Ensure that A does NOT receive any context via these listeners (past context is only retrieved via a `getCurrentContext()` call on App channels). |\n| A   | 5.Retrieve Current Context    | A is able to retrieve the most recent context of each context type from the `Channel`  via: <br/>`const instrument = await testChannel.getCurrentContext('fdc3.instrument')`<br/>`const instrument = await testChannel.getCurrentContext('fdc3.contact')`<br />Ensure that both contexts retreived by A are identical to those sent by B|\n\n- `ACContextHistoryTyped`: Perform above test.\n- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types.  Ensure that only the last version of each type is received by **A**.\n- `ACContextHistoryLast`: In step 5. **A** retrieves the _untyped_ current context of the channel via `const currentContext = await testChannel.getCurrentContext()`. Ensure that A receives only the very last broadcast context item _of any type_.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/Basic-Tests.md",
    "content": "---\nid: Basic-Tests\nsidebar_label: Basic Tests\ntitle: Basic Tests\nhide_title: true\n---\n\n# Basic Tests ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_These are some basic sanity tests implemented in the FDC3 Conformance Framework.  It is expected that Desktop Agent testers will run these first before commencing the much more thorough tests in section 2 onwards._\n\n- `BasicCL1`: You can create a context listener by calling `fdc3.addContextListener('fdc3.contact',<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicCL2`: You can create an **unfiltered** context listener by calling `fdc3.addContextListener(null,<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicIL1`: You can create an intent listener by calling `fdc3.addIntentListener(<intent name>,<handler>)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicGI1`: An application can retrieve an `ImplementationMetadata` object to find out the version of FDC3 it is using and the provider details by calling:\n    - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getInfo()` \n    - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `await fdc3.getInfo()` \n- `BasicAC1`: An application can retrieve a named 'App' channel via the `fdc3.getOrCreateChannel(<name>)` function. The `Channel` object returned conforms to the defined interface.\n- `BasicUC1`: An application can query the available user/system channels, which are returned as an array of `Channel` Objects conforming to the defined interface.  The API call is:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getSystemChannels()`\n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)`await fdc3.getUserChannels()` \n- `BasicJC1`: The application should be able to join one of the user/system channels with the channel's id.  Having done so, the current channel should NOT be null, and be set for the application _to the channel for the id given_.  After you leave the current channel, it should go back to being `null`.\n  - The channel is joined with:\n    - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.joinChannel(<channelId>)` \n    - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.joinUserChannel(<channelId>)` \n  - A `Channel` object representing the current channel is retrieved with:\n    - `fdc3.getCurrentChannel()` to get the current channel.\n  - The channel is left with: \n    - `fdc3.leaveCurrentChannel()`\n- `BasicRI1`: The application should be able to raise an intent by invoking: \n  - `fdc3.raiseIntent(<intent name>)`\n  - A promise should be returned.\n- `BasicRI2`: The application should be able to raise an intent for some item of context by invoking:\n  - `fdc3.raiseIntentForContext(<context>)`\n  - A promise should be returned.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/Intents-Tests.md",
    "content": "---\nid: Intents-Tests\nsidebar_label: Intents Tests\ntitle: Intents Tests\nhide_title: true\n---\n\n# Intents Tests\n\n## Version 1.2 Intents Tests ![1.2](https://img.shields.io/badge/FDC3-1.2-green)\n\n_NB: Intents received a lot of work in 2.0 version of the specification, so by and large the tests for these are now completely different._\n\n### Setup\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                                                                                                                                    |\n|-----|------------------------------------------------------------------------------------------------------------------------------------------------------|\n| A   | A’s AppD Record contains: `aTestingIntent` (with context type `testContextX`, `testContextZ`) and `sharedTestingIntent1` (with context type `testContextX`)    |\n| B   | B’s AppD Record contains `bTestingIntent` (with context type `testContextY`) and `sharedTestingIntent1` (with context types `testContextX` and `testContextY`) |\n| C   | C’s AppD Record contains `cTestingIntent` (with context type `testContextX`)                                                                             |\n\nAlso we assume a fourth app **D** that is going to discover the intents in the other 3.\n\n### Find Intent From AppD\n\n-  `IntentAppD`: Calls `fdc3.findIntent(‘aTestingIntent’)`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.\n-  `WrongIntentAppD`: Calls `fdc3.findIntent(‘nonExistentIntent’)`. Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror\n-  `IntentAppDRightContext`: Calls `fdc3.findIntent(‘aTestingIntent’, ‘testContextX’)`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.\n-  `IntentAppDWrongContext`: Calls `fdc3.findIntent(‘aTestingIntent’, ‘testContextY’)`.  Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror\n-  `IntentAppDMultiple1`: Calls `fdc3.findIntent(‘sharedTestingIntent1’)`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.\n-  `IntentAppDMultiple2`: Calls `fdc3.findIntent(‘sharedTestingIntent1’, 'testContextX')`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.\n-  `IntentAppDMultiple3`: Calls `fdc3.findIntent(‘sharedTestingIntent1’, 'testContextY')`.  Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **B** app metadata.\n\n### Find Intents By Context\n\n-  `SingleContext`: Call `fdc3.findIntentsByContext(‘testContextX’)`.  Should return `aTestingIntent` (app **A**), `sharedTestingIntent1` (**A**, **B**) and `cTestingIntent` (**C**) AND nothing else.\n-  `NoContext`: Call `fdc3.findIntentsByContext()`. Throws error of `NoAppsFound`\n\n### Raise Intent\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| D   | 1. Raise          | `fdc3.raiseIntent(‘sharedTestingIntent1’, {testContextY})`<br />starts app B.                       |\n| B   | 2. Gather Context | `fdc.addIntentListener(‘sharedTestingIntent1’)`<br />Receives testContextY, matching that sent by D |\n\n-  `SingleResolve1`: Perform above test\n-  `TargetedResolve1`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, <A’s App Name>)` to start app A, otherwise, as above\n-  `TargetedResolve2`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: \"<A's App Name>\"})` to start app A, otherwise, as above\n-  `TargetedResolve3`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: \"<app B Name>\", appId: \"<app B ID>\"})` to start app B, otherwise, as above\n-  `FailedResolve1-3` As with `TargetedResolve1-3`, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextY}, <A’s App Name>)` and variations.  You will receive `NoAppsFound` Error\n-  `FailedResolve4` As above, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, <C’s App Name>)`.  You will receive `NoAppsFound` Error\n\n## Current Intents Tests ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_Please note that API calls (and associated test cases) relating to API calls based on the `name` property of an appD record (used to specify a target application) were deprecated in FDC3 2.0 in favour of those based on `AppIdentifier`. Hence, those API calls have become optional and test cases related to them have been removed._\n\n### Setup\n\nWe assume 6 context types in the below tests (and associated AppD records):\n\n- `testContextX`\n- `testContextY`\n- `testContextZ`\n- `nonExistentContext` (context object with a unique type that does NOT appear in any of the apps (metadata or otherwise).\n- `privateChannelDetails`\n- `privateChannelIsPrivateResult`\n\nThese may be used in a test as a context object `{ \"type\": \"<typeName>\" }` or just the base type name.  Where the base type name is used it is surround with \"quotes\". If not wrapped in quotes assume it is an instance of that context type (generally just an object with a `type` field set to the type name - but occasionally with other data).\n\nYou will need to pre-populate the AppDirectory with the following items (some of which will never be started, but must be configured to confirm correct behavior from various API functions):\n\n| App | Usage                                                 | ListensFor `(pattern: intent([context-types…]) (=> result-type)`)                               | On Startup                                                                   |\n|-----|-------------------------------------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|\n| A   | Raise Intent tests without results                    | `aTestingIntent(testContextX,testContextZ)`<br/>`sharedTestingIntent1(testContextX)` | addIntentListener() for given intents                                       |\n| B   | Raise Intent tests with Context results               | `bTestingIntent(testContextY)`<br/>`sharedTestingIntent1(testContextX, testContextY) => testContextY` | addIntentListener() for given intents                                       |\n| C   | Find Intent tests (never started)                     | `cTestingIntent(testContextX) => testContextZ`                                                  | addIntentListener() for given intents                                       |\n| D   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextX) => testContextZ`                                            | addIntentListener() for given intents                                       |\n| E   | Find Intent & Raise Intent with Channel result        | `sharedTestingIntent2(testContextY) => channel`                                                 | addIntentListener() for given intents                                       |\n| F   | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel<testContextZ>` *                                 | addIntentListener() for given intents                                       |\n| G   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextY)`                                                            | addIntentListener() for given intents                                       |\n| H   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                            | - no action                                                                   |\n| I   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                           | addIntentListener(‘MadeUpIntent’, handler)                          |\n| J   | PrivateChannels are private                           | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult`                   | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |\n| K   | PrivateChannel lifecycle events                       | `kTestingIntent(testContextX) => channel<testContextZ>`                                         | addIntentListener() for given intents                                       |\n\nNB:\n\n- There is no way to indicate in the app directory the difference between a private channel and app channel.\n- We assume a final test app `Test` that will discover the Intent support in the others using the API.\n\nFinally, please note that this is a larger set of apps than were required for 1.2 tests. This is due to an increased number of parameters to API calls and AppD records, which multiplies the number of apps required. The apps are all specified here (rather than broken down over multiple issues) to ensure that clashes between test case sets can be worked out here. For example, adding one additional app that works with a particular intent/context pair might corrupt the results of multiple `findIntent` or `raiseIntent` tests. Hence, please stick to the defined type and report any issues you find so that they can be rectified in these definitions.\n\n### Find Intent basic usage\n\n- `2.0-FindIntentAppD`: Calls `fdc3.findIntent(\"aTestingIntent\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** `AppMetadata`.\n- `2.0-FindNonExistentIntentAppD`: Calls `fdc3.findIntent(\"nonExistentIntent\")`. Rejects with an Error whose `message` is `ResolveError.NoAppsFound` https://fdc3.finos.org/docs/api/ref/Errors#resolveerror\n- `2.0-FindIntentAppDRightContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextX\")`.  Receives promise containing an `AppIntent` with metadata containing `aTestingIntent` and only metadata for app **A**.\n- `2.0-FindIntentAppDWrongContext`: Calls `fdc3.findIntent(\"aTestingIntent\", \"testContextY\")`.  Rejects with an Error whose `message` is `ResolveError.NoAppsFound` https://fdc3.finos.org/docs/api/ref/Errors#resolveerror\n- `2.0-FindIntentAppDMultiple1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and metadata for apps  **D**, **E**, **F**, **G**, **H**  and **I** only.\n- `2.0-FindIntentAppDMultiple2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", \"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and `AppMetadata` for apps  **E**, **F**, **G**, **H**  and **I** only.\n\n### Find Intents By Context\n\n- `2.0-FindIntentByContextSingleContext`: Call `fdc3.findIntentsByContext(testContextX)`.  Should return:\n  - `aTestingIntent` (app **A**),\n  - `sharedTestingIntent1` (**A**, **B**)\n  - `cTestingIntent` (**C**),\n  - `sharedTestingIntent2` (**D**)\n  - `kTestingIntent` (**K**),\n  - AND nothing else.\n- `2.0FindIntentByContextWrongIntentAppD`: Calls `fdc3.findIntentsByContext(nonExistentContext)`. Rejects with an Error whose `message` is `ResolveError.NoAppsFound` https://fdc3.finos.org/docs/api/ref/Errors#resolveerror\n\n### Find Intents By Result Type\n\n- `2.0-FindIntentAppDByResultSingle`: Calls `fdc3.findIntent(\"cTestingIntent\", testContextX, \"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultSingleNullContext`: Calls `fdc3.findIntent(\"cTestingIntent\", null, \"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultMultiple`: Calls `fdc3.findIntent(\"sharedTestingIntent1\", testContextX, \"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **B** app metadata.\n- `2.0-FindIntentAppDByResultChannel1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", testContextY, \"channel\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and only **E** and **F** app metadata.\n- `2.0-FindIntentAppDByResultChannel2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\", testContextY, \"channel<testContextZ>\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **F** app metadata.\n\n### Raise Intent (Ignoring any result)\n\n| App   | Step           | Details                                                                                           |\n|-------|----------------|---------------------------------------------------------------------------------------------------|\n| Test  | 1. Raise        | `fdc3.raiseIntent(\"aTestingIntent\", testContextX)`<br />starts app A.                       |\n| A     | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent1\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test  | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.**                       |\n\n- `2.0-RaiseIntentSingleResolve`: Perform above test\n- `2.0-RaiseIntentTargetedAppResolve`: Repeat the above test, but:\n  - In the first step use `fdc3.raiseIntent(\"sharedTestingIntent1\", testContextX, {\"appID\": \"<B’s appId>\"})` to start app B,\n  - Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveOpen`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId: \"<A's appId>\"})` to start A and retrieve its `AppIdentifier` with instance details.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, appIdentifier)` to target the running instance of app A. \n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveFindInstances`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId: \"<A's appId>\"})` to start A.\n  - Then use `const instances = await fdc3.findInstances({appId: \"<A's appId>\"})` to retrieve a list of instances of app A. Confirm that only one is present and retrieve its `AppIdentifier`, confirming that it contains an `instanceId` field that matches that returned by the `fdc3.open` call.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, appIdentifier)` to target the running instance of app A. \n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentFailedResolve`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextY)`.  Note that no app supports this intent and context combination.**\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve1`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextY, {appId: \"<A's appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, {appId: \"NonExistentApp\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.TargetAppUnavailable`.\n- `2.0-RaiseIntentFailTargetedAppResolve3`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<H's appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but does not add any intent listeners).\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppResolve4`: Perform above test, but: \n  - `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<I's appId>\"})`\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but adds intent listeners of the wrong type.\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve1`: Perform above test, but:\n  - First spawn an instance of App **A** and collect its `AppIdentifier` with `const appIdentifier = await fdc3.open({appId: \"<A's appId>\"})`.\n  - Then use `fdc3.raiseIntent(\"aTestingIntent\", testContextY, appIdentifier)` to target that instance.  \n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound` (since A doesn't support this context type).\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\", testContextX, {appId: \"<A's appId>\", instanceId \"NonExistentInstanceId\"})`.  \n  - You should receive a JavaScript Error with the message `ResolveError.TargetInstanceUnavailable`.\n\n### Raise Intent Result (void result)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"aTestingIntent\", testContextX)`<br />starts app A.                       |\n| A       | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.                     |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.                        |\n| A       | 5. return void          | A should return `void` after a short delay (e.g. 5 seconds).                        |\n| Test   | 6. receive void result          | The promise received by Test from `resolution.getResult()` should resolve to void. Confirm that the promise could be retrieved before the handler function returned and that the result was received *after* the result was returned by A, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited.                      |\n\n- `2.0-RaiseIntentVoidResult5secs`: Perform above test\n- `2.0-RaiseIntentVoidResult0secs`: Perform above test, but A should return its result immediately (no delay). Ignore test step 6 (as there is too little time between the IntentResolution and IntentHandler completing).\n- `2.0-RaiseIntentVoidResult61secs`: Perform above test, but A should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n### Raise Intent Result (Context result)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"sharedTestingIntent1\", testContextY)`<br />starts app **B**. |\n| B      | 2. Receive Intent & Context | After starting up, B runs `fdc3.addIntentListener(\"sharedTestingIntent1\")` to register its listener.<br />It then receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution          | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App B's `appId` and `instanceId` set. |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |\n| B      | 5. return `testContextY`          | B should return a `testContextY` instance after a short delay (e.g. 5 seconds). |\n| Test   | 6. receive context result          | The promise received by Test from `resolution.getResult()` should resolve to the `testContextY` instance. Confirm that the promise could be retrieved before the handler function returned and that the result was received *after* the result was returned by B, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited. |\n\n- `2.0-RaiseIntentContextResult5secs`: Perform the above test.\n- `2.0-RaiseIntentContextResult0secs`: Perform the previous test but B should return its result immediately (no delay).\n- `2.0-RaiseIntentContextResult61secs`: As above, but B should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n### Raise Intent Result (Channel results)\n\n| App   | Step                          | Details                                                                                           |\n|-------|-----------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise Intent          | Test raises an intent with `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY, {appId: \"<E's appId>\"})`<br />starts app E. |\n| E       | 2. Receive Intent & Context     | After starting up, E runs `fdc3.addIntentListener(\"sharedTestingIntent2\")` to register its listener.<br />It them receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution   | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App E's `appId` and `instanceId` set.   |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| E       | 5. return Channel | E should retrieve a Channel object via `fdc3.getOrCreateChannel(\"someChannelName\")` and return it immediately. |\n| Test   | 6. receive Channel result | The promise received by Test from `resolution.getResult()` should resolve to a `Channel` object with the expected id. Confirm that the `type` of the Channel object is \"app\".\n| Test   | 7. addContextListener | Add a context listener to the Channel object via `channelObj.addContextListener(\"testContextZ\", handler)` |\n| E       | 8. broadcast context | After a short delay (of a few seconds) E should broadcast a `testContextZ` context object over the channel, including an `id` field with a unique identifier set (e.g. a uuid). |\n| Test  | 9. receive context | Test should receive the context broadcast by E and confirm that it contains the expected `id` value. |\n\n- `2.0-RaiseIntentChannelResult`: Perform the above test\n- `2.0-RaiseIntentPrivateChannelResult`: Perform the above test, but:\n  - Substitute app F throughout - which returns a PrivateChannel result instead of channel.\n  - At step 5, the PrivateChannel should be created via`fdc3.createPrivateChannel()`.\n  - At step 6 confirm that the type of the channel is \"private\".\n\n### PrivateChannels cannot be accessed as app channels\n\n| App  | Step                | Details                                                                                                                                    |\n|-------|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Create a private channel | Test creates a PrivateChannel with `const privChan = await fdc3.createPrivateChannel()`. Confirm that the Channel has an `id`.\n| Test   | 2. Confirm private channel `id` is unique | Test creates a second PrivateChannel with `const privChan = await fdc3.createPrivateChannel();`. Confirm that the Channel has an `id` and that it is distinct from the first channel created. |\n| Test   | 3. Retrieve as app channel | Attempt to retrieve the channels as App Channels with `const appChan = await fdc3.getOrCreateChannel(privChan.id)` this should fail with `ChannelError.AccessDenied`  |\n| Test   | 4. Raise Intent & await result | Start app J and pass it the id of the second PrivateChannel with `fdc3.raiseIntent(\"privateChannelIsPrivate\", privateChannelDetails)`, where the context object contains the id of the channel to attempt to retrieve. An IntentResolution should be returned and App J should start. Wait for a result to be returned via `await resolution.getResult()`.\n| J | 5. Receive Intent & Context | J should add an Intent Listener and receive the context with `fdc3.addIntentListener(\"privateChannelIsPrivate\", handler)` |\n| J | 6. Retrieve as app channel | J should attempt to retrieve the channel as an App Channel by `id` with `const appChan = await fdc3.getOrCreateChannel(\"<idPassedInContext>\")` this should fail with `ChannelError.AccessDenied`. Return a `privateChannelisPrivateResult` back to Test to complete the test. |\n| Test   | 7. Receive result | Test receives the result back from J and confirms that the test was passed. |\n\n- `2.0-PrivateChannelsAreNotAppChannels`: Perform the above test\n\n### PrivateChannel Lifecycle Events\n\n| App  | Step                 | Details                                                                                                                                    |\n|-------|-----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent(‘\"kTestingIntent\", testContextX, {appId: \"<K's appId>\"})`<br />starts app K. |\n| K       | 2. Receive Intent & Context     | After starting up, K runs `fdc3.addIntentListener(\"kTestingIntent\")` to register its listener.<br />It them receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution   | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set.   |\n| Test   | 4. await results          | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| K       | 5. Create PrivateChannel and setup event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,<br />it should then add listeners for the 3 events offered + a context listener via:<br />- `const listener1 = await privChan.onAddContextListener(handler1);`<br />- `const listener2 = await privChan.onUnsubscribe(handler2);`<br />- `const listener3 = await privChan.onDisconnect(handler3);`<br />- `const listener4 = await privChan.addContextListener(\"testContextX\", handler4)`<br />it should then return the `PrivateChannel`. |\n| Test   | 6. receive PrivateChannel  | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is \"private\".\n| Test   | 7. addContextListener | Test should add a context listener to the PrivateChannel object via `const listener1 = privChan.addContextListener(\"testContextZ\", handler)` |\n| K       | 8. Receive event & broadcast context | The `onAddContextListener` handler (`listener1`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |\n| Test   | 9. Unsubscribe listener | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `listener1.unsubscribe().` |\n| K       | 10. Receive unsubscribe event | The event handler registered by K via `onUnsubscribe` should fire. If it does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|\n| Test   | 11. Broadcast context | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |\n| K       | 12. Receive context | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|\n| Test   | 13. re-run addContextListener  | Test should (again) add a context listener to the PrivateChannel object via `const listener2 = privChan.addContextListener(\"testContextZ\", handler)` |\n| K       | 14. Receive event & broadcast context | The `onAddContextListener` handler added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |\n| Test   | 15. Disconnect | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |\n| K       | 16. Receive events & cleanup | The `onUnsubscribe` handler added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, the `onDisconect` handler also added in step 5 should fire. Once it has, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |\n\n- `2.0-PrivateChannelsLifecycleEvents`: Perform the above test.\n\n### Resolving Ambiguous Intents\n\nFDC3 Desktop Agent MUST provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForContext that return multiple options). This is often accomplished by providing a user interface allowing the user to select the desired target application or intent and application. \n\nAs the methods of resolving ambiguous intents are often user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. These tests are based on the same applications defined for and used in other intent tests - however a separate manual test app should be provided to enable the test.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY)` |\n| User | 2. Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousIntentTarget`: Perform above steps to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 2.  Chooser Interaction | Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousContextTarget`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\", testContextY)` |\n| User | 3. Chooser Interaction | Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousIntentTargetMultiInstance`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App | Step | Details |\n|---|---|---|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 3.  Chooser Interaction | Chooser Interaction | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousContextTargetMultiInstance`: Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/Metadata-Tests.md",
    "content": "---\nid: Metadata-Tests\nsidebar_label: Metadata Tests\ntitle: Metadata Tests\nhide_title: true\n---\n\n# Metadata & Instance Test Cases\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                        |\n|-----|------------------------------------------|\n| A   | Generic AppD Record which contains at least the following fields:<br />- `name`<br />- `version`<br />- `title`<br />- `tooltip`<br />- `description`<br />- `icons` (`Array<Icon>`)<br />- `screenshots` (`Array<Image>`)<br />- `interop.intents.listensFor` (`aTestingIntent` with at least context type `testContextX`)  |\n\n## Retrieve `AppMetadata` ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.getAppMetadata    | Retrieve metadata for the configured app A with <br/> `const metadata1 = await fdc3.getAppMetadata({appId: \"<A's appId>\"})`  |\n| Test   | 2.Confirm    | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set  |\n\n- `GetAppMetadata`: perform the above steps\n\n## Instance Metadata ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.Open1    | Open a first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test   | 2.Open2    |Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test   | 3.getAppMetadata1    | Retrieve metadata for the first instance of the app with<br/> `const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |\n| Test   | 4.Confirm1 | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches.  |\n| Test   | 5.getAppMetadata2    | Retrieve metadata for the second instance of the app with <br/>`const metadata2 = fdc3.getAppMetadata(appIdentifier2)`  |\n| Test   | 6.Confirm2    | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2`  |\n\n- `AppInstanceMetadata`: Perform the above steps\n\n## Finding Instances ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.Open1    | Open the first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test   | 2.Open2    |Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test   | 3.FindInstances    | Retrieve details of open instances of app A with <br/> `let instances = await fdc3.findInstances({appId: \"<A's appId>\"})` <br/> confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array.  |\n| Test   | 4.RaiseIntent   | Use `appIdentifier1` to raise an intent and target that instance, with<br/> `const resolution = fdc3.raiseIntent(\"aTestingIntent\", {\"type\": \"testContextX\"}, appIdentifier1)` |\n| Test   | 5.Confirm1 | Check that `resolution.source` matches `appIdentifier1` |\n| A | 6.ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |\n\n- `FindInstances`: Perform the above steps\n\n## Getting Info For The Agent\n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.getInfo    |Retrieve the `ImplementationMetadata` for the DesktopAgent with <br/> - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `let implMetadata = fdc3.getInfo()`  <br/> - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.getInfo().then((implMetadata) => { subsequent steps }`   <br />**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|\n| Test   | 2.CheckVersion  | Check that the `fdc3Version` variable is present and at or greater than:  <br /> -  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) 1.2 <br /> - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) 2.0  <br />(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):<br />`const isFDC3v2 = versionIsAtLeast(implMetadata, \"2.0\")`  |\n| Test   | 3.CheckProvider  | Check that the `provider` variable is present and not an empty string  |\n| Test   | 4.CheckFeatures  | ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values  |\n\n- ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `GetInfo1`: Perform the above steps \n\n| App | Step           | Details                                                                                           |\n|-----|----------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1.Open1    | Start an instance of App A with <br/>`const appIdentifier1 = await fdc3.open({appId: \"<A's appId>\"})` <br /> retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |\n| A | 2.getInfo     |   Retrieve the `ImplementationMetadata` for the DesktopAgent with: <br  />`fdc3.getInfo().then((implMetadata) => {  ... subsequent steps ...}` <br/> This should include `AppMetadata` for the retrieving app. |\n| A + Test | 3.Confirm  | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |\n\n- ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `GetInfo2`: Perform the above steps. \n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/Open-Tests.md",
    "content": "---\nid: Open-Tests\nsidebar_label: Open Tests\ntitle: Open Tests\nhide_title: true\n---\n\n# Open Tests\n\n## A Opens B  \n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App  | App A calls a function (see below) to open a second app, B |\n| A   | 2. Check Metadata | Ensure that the correct app was opened |\n\n- `AOpensB1`:   ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name’)` \n- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"<app B Name>\"})` \n- `AOpensB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"<app B Name>\", appId: \"<app B ID>\"})` \n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"})`\n- `AOpensB4`:  ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: \"<app B ID>\"})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.\n\n## A Fails To Open Another App\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App  | App A calls a function (see below) to try and open a non-existent app |\n| A   | 2. Check Error Response | ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open` throws an Error with the message \"App Not Found\"<br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open` returns a promise that rejects with an Error with the message \"App Not Found\" |\n\n- `AFailsToOpenB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘non existent app’)` \n- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"non existent app\"})` \n- `AFailsToOpenB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via: \n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"non existent app\", appId: \"non existent app\"})` \n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"})`\n\n## A Opens B With Context\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | 1. Opening App     |App A opens app B with an `fdc3.instrument` Context Object by calling a function (see below) |\n| B   | 2. Receive Context | Add an untyped context listener via: <br/>`fdc3.addContextListener(null, handler)` <br /> B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open() call made by A |\n\n- `AOpensBWithContext1`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name', <fdc3.instrument context>)` \n- `AOpensBWithContext2`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: \"<app B Name>\"}, <fdc3.instrument context>)` \n- `AOpensBWithContext3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: \"<app B Name>\", appId: \"<app B ID>\"}, <fdc3.instrument context>)` \n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  `fdc3.open({appId: \"<app B ID>\"}, <fdc3.instrument context>)`\n- `AOpensBWithSpecificContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener('fdc3.instrument', handler)` \n- `AOpensBMultipleListen`:  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener('fdc3.contact', handler)` prior to the existing `addContextListener` for `fdc3.instrument`.  The correct context listener should receive the context, and the promise completes successfully. \n- `AOpensBWithWrongContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.\n  - Confirm that NO context is received. \n  - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) the `fdc3.open` call throws an Error with message `AppTimeout` \n  - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) The promise returned to **A** by `fdc3.open` rejects with an Error with message `AppTimeout`\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/Overview.md",
    "content": "---\nid: Conformance-Overview\nsidebar_label: Overview\ntitle: FDC3 Conformance Tests\nhide_title: true\n---\n\n# FDC3 Conformance Tests\n\nThis section contains test definitions that are used to test for conformance of a Desktop Agent API implementation with FDC3.\n\n:::info\nAs FDC3 2.1 does not introduce changes to the Desktop Agent API, the conformance test set for FDC3 2.0 remains current for this version. Please see the [FDC3 2.1 Changelog entry](https://github.com/finos/FDC3/blob/main/CHANGELOG.md#fdc3-standard-21---2023-09-13) for more details.\n:::\n\nYou can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.\n\nThere are currently 6 sections to the tests.  Where tests apply to a particular version of FDC3, this is labelled with icons in the header, like so: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n- [Basic Tests](Basic-Tests.md)\n- [Open Tests](Open-Tests.md)\n- [User Channel Tests](User-Channel-Tests.md)\n- [App Channel Tests](App-Channel-Tests.md)\n- [Metadata Tests](Metadata-Tests.md)\n- [Intents Tests](Intents-Tests.md)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/conformance/User-Channel-Tests.md",
    "content": "---\nid: User-Channel-Tests\nsidebar_label: User Channel Tests\ntitle: User Channel Tests\nhide_title: true\n---\n\n# User Channel Tests  ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)\n\n_NB:  User Channels were called System Channels in FDC3 1.2.  The new terminology is used in this specification_\n\n## Basic Broadcast\n\n| App | Step               |Details                                                                           |\n|-----|--------------------|----------------------------------------------------------------------------------|\n| A   | 1.addContextListener |A adds an _unfiltered_ Context Listener using `addContextListener(null, handler)`. <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` method. |\n| A   | 2.joinUserChannel     |A joins the first available (non-global) user channel.  The available Channels are retrieved with: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.getSystemChannels()` _Check channels are returned._ <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.getUserChannels()` <br/> The first channel (that does not have the id 'global') is joined with: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.joinChannel(<channelId>)` _Check channels are returned._ <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.joinUserChannel(<channelId>)`  |\n| B   | 3.joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4.Broadcast          | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast(<the instrument>)`. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  Check a `void` promise is returned. |\n| A   | 5.Receive Context    | A receives the instrument object, matching the one broadcast by B.  |\n\n- `UCBasicUsage1` Perform above test \n- `UCBasicUsage2` Perform steps in order: 2,1,3,4,5 to confirm that the order of `joinUserChannel` and `addContextListener` calls doesn't matter\n- `UCBasicUsage3` Perform steps in order: 3,4,1,2,5 to confirm that the current context is automatically received on joining a channel.\n- `UCBasicUsage4` Perform steps in order: 3,4,2,1,5  to confirm that the current context is automatically received on adding a context listener to an already joined a channel.\n\n## Filtered Broadcast\n\n| App | Step               |Details                                                                           |\n|-----|--------------------|----------------------------------------------------------------------------------|\n| A   | 1.addContextListener |A adds a `fdc3.instrument` _typed_ Context Listener using `addContextListener(\"fdc3.instrument\", handler)`. <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` method.|\n| A   | 2.joinUserChannel     |A joins the first available user channel using: <br/> ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `getSystemChannels()` Check channels are returned. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3.joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4.Broadcast          | B broadcasts: <br/> 1.`fdc3.broadcast(<the instrument>)`. <br/> 2. `fdc3.broadcast(<a contact>)` <br /> ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)  Check a `void` promise is returned. |\n| A   | 5.Receive Context    | A receives the `fdc3.instrument` object, matching the one broadcast by B. <br />Check that the `fdc3.contact` is NOT received. |\n\n- `UCFilteredUsage1` Perform above test \n- `UCFilteredUsage2` Perform steps in order: 2,1,3,4,5\n- `UCFilteredUsage3` Perform steps in order: 3,4,1,2,5\n- `UCFilteredUsage4` Perform steps in order: 3,4,2,1,5\n\n## Broadcast With Multiple Listeners\n\n| App | Step               | Details                                                                                                     |\n|-----|--------------------|-------------------------------------------------------------------------------------------------------------|\n| A   | 1.addContextListeners | A sets up two Context Listeners.  One for `fdc3.instrument` and one for `fdc3.contact` by calling:  `addContextListener (\"fdc3.instrument\", handler)` <br/> `addContextListener (\"fdc3.contact\", handler)` <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) A `Listener` object is returned for each.  <br />![2.0](https://img.shields.io/badge/FDC3-2.0-blue) A promise resolving a `Listener` object is returned for each. <br />Check that this has an `unsubscribe` method for each.  |\n| A   | 2.joinUserChannel     |A joins the first available user channel using: <br/>![1.2](https://img.shields.io/badge/FDC3-1.2-green) `getSystemChannels()` Check channels are returned. <br/>![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3.joinUserChannel     |B joins the same channel as A, via the same process in 2. |\n| B   | 4.Broadcast          | `fdc3.broadcast(<instrument context>)` <br/> `fdc3.broadcast(<contact context>)` . |\n| A   | 5.Receive Context    | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.<br />A's `fdc3.contact` object matches the one broadcast  by B, and arrives on the correct listener.   |\n\n - `UCFilteredUsage5`: Perform above test\n - `UCFilteredUsage6`: Perform above test, except B will join a _different_ channel to A. Check that you _don't_ receive anything.\n - `UCFilteredUsageChange`: Perform above test, except that after joining, **A** changes channel to a _different_ channel via a further call to `fdc3.joinUserChannel`.  Check that **A** does NOT receive anything.\n - `UCFilteredUsageUnsubscribe`: Perform above test, except that after joining, **A** then `unsubscribe()`s from the channel using the `listener.unsubscribe` function. Check that **A** does NOT receive anything. \n - `UCFilteredUsageLeave`: Perform above test, except that immediately after joining, **A** _leaves the channel_, and so receives nothing.\n - `UCFilteredUsageNoJoin`: Perform the above test, but skip step 2 so that **A** does NOT join a channel. Confirm that the _current channel_ for **A** is NOT set before continuing with the rest of the test.  **A** should receive nothing.\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/Channel.md",
    "content": "---\nid: Channel\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\n---\n# `Channel`\n\nRepresents a context channel that applications can join to share context data and provides functions for interacting with it.\n\nA channel can be either a [\"User\" channel](../spec#joining-user-channels) (retrieved with [`getUserChannels`](DesktopAgent#getuserchannels)), a custom [\"App\" channel](../spec#app-channels) (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)) or a [\"Private\" channel](../spec#private-channels) (obtained via an intent result).\n\n:::note\n\nThere are differences in behavior when you interact with a User channel via the Desktop Agent interface and the Channel interface. Specifically, when 'joining' a User channel or adding a context listener when already joined to a channel via the `DesktopAgent` interface, existing context (matching the type of the context listener) on the channel is received by the context listener immediately. Whereas, when add a context listener via the Channel interface, context is not received automatically, but may be retrieved manually via the [`getCurrentContext()`](#getcurrentcontext) function.\n\n:::\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: \"user\" | \"app\" | \"private\";\n  displayMetadata?: DisplayMetadata;\n\n  // functions\n  broadcast(context: Context): Promise<void>;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n  \n  //deprecated functions\n  /**\n   * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n}\n```\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n\n## Properties\n\n### `id`\n\n```ts\npublic readonly id: string;\n```\n\nUniquely identifies the channel. It is either assigned by the desktop agent (User Channel) or defined by an application (App Channel).\n\n### `type`\n\n```ts\npublic readonly type: \"user\" | \"app\" | \"private\";\n```\n\nCan be _user_,  _app_ or _private_.\n\n### `displayMetadata`\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\nDisplayMetadata can be used to provide display hints for User Channels intended to be visualized and selectable by end users.\n\n**See also:**\n\n- [`DisplayMetadata`](Metadata#displaymetadata)\n\n## Functions\n\n### `addContextListener`\n\n```ts\npublic addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\nIf, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the [`getCurrentContext(contextType)`](#getcurrentcontext) function.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**Examples:**\n\nAdd a listener for any context that is broadcast on the channel:\n\n```ts\nconst listener = await channel.addContextListener(null, context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n```ts\nconst contactListener = await channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`ContextHandler`](Types#contexthandler)\n- [`broadcast`](#broadcast)\n- [`getCurrentContext`](#getcurrentcontext)\n\n### `broadcast`\n\n```typescript\npublic broadcast(context: Context): Promise<void>;\n```\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [FDC3 Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n```javascript\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`getCurrentContext`](#getcurrentcontext)\n- [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\nIf getting the current context fails, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Examples:**\n\nWithout specifying a context type:\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\nSpecifying a context type:\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler error\n}\n```\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`broadcast`](#broadcast)\n- [`addContextListener`](#addcontextlistener)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n```ts\n/**\n * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\npublic addContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/DesktopAgent.md",
    "content": "---\nid: DesktopAgent\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\n---\n# `DesktopAgent`\n\nAn FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nIt is expected that the `DesktopAgent` interface is made available via the [`window.fdc3`](Globals#windowfdc3-object) global object, and that the [`fdc3Ready`](Globals#fdc3ready-event) event fires when it is ready to be used.\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n\n  // context\n  broadcast(context: Context): Promise<void>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n\n  // intents\n  findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n  findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n\n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  createPrivateChannel(): Promise<PrivateChannel>;\n  getUserChannels(): Promise<Array<Channel>>;\n\n  // OPTIONAL channel management functions\n  joinUserChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel | null>;\n  leaveCurrentChannel() : Promise<void>;\n\n  //implementation info\n  getInfo(): Promise<ImplementationMetadata>;\n\n  //Deprecated functions\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  open(name: string, context?: Context): Promise<AppIdentifier>;\n  raiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n}\n```\n\n## Functions\n\n### `addContextListener`\n\n```ts\naddContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or [`fdc3.open`](#open) API call). If the consumer is only interested in a context of a particular type, they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.\n\nContext broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from User channels. If this function is called after the app has already joined a channel and the channel already contains context that matches the type of the context listener, then it will be called immediately and the context passed to the handler function. If `null` was passed as the context type for the listener and the channel contains context, then the handler function will be called immediately with the most recent context - regardless of type.\n\nContext may also be received via this listener if the application was launched via a call to  [`fdc3.open`](#open), where context was passed as an argument. In order to receive this, applications SHOULD add their context listener as quickly as possible after launch, or an error MAY be returned to the caller and the context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the Desktop Agent implementation.\n\n**Examples:**\n\n```js\n// any context\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n// listener for a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });\n\n// listener that logs metadata for the message a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', (contact, metadata) => {\n  console.log(`Received context message\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n  //do something else with the context\n});\n```\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`ContextHandler`](Types#contexthandler)\n\n### `addIntentListener`\n\n```ts\naddIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming intents raised by other applications, via calls to [`fdc3.raiseIntent`](#raiseintent) or [`fdc3.raiseIntentForContext`](#raiseintentforcontext). If the application is intended to be launched to resolve raised intents, it SHOULD add its intent listeners as quickly as possible after launch or an error MAY be returned to the caller and the intent and context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nThe handler function may return void or a promise that resolves to a [`IntentResult`](Types#intentresult), which is either a [`Context`](Types#context) object, representing any data that should be returned to the app that raised the intent, or a [`Channel`](Channel), a [`PrivateChannel`](PrivateChannel) over which data responses will be sent, or `void`. The `IntentResult` will be returned to the app that raised the intent via the [`IntentResolution`](Metadata#intentresolution) and retrieved from it using the `getResult()` function.\n\nThe Desktop Agent MUST reject the promise returned by the `getResult()` function of `IntentResolution` if any of the following is true:\n\n1. The intent handling function's returned promise rejects.\n2. The intent handling function returns something other than a promise.\n3. The returned promise resolves to an invalid type.\n\nThe [`PrivateChannel`](PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**Examples:**\n\n```js\n//Handle a raised intent\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n  return;\n});\n\n//Handle a raised intent and log the originating app metadata\nconst listener = fdc3.addIntentListener('StartChat', (contact, metadata) => {\n  console.log(`Received intent StartChat\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n    return;\n});\n\n//Handle a raised intent and return Context data via a promise\nfdc3.addIntentListener(\"CreateOrder\", (context) => {\n  return new Promise<Context>((resolve) => {\n    // go create the order\n    resolve({type: \"fdc3.order\", id: { \"orderId\": 1234}});\n  });\n});\n\n//Handle a raised intent and return a PrivateChannel over which response will be sent\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel: PrivateChannel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // Called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // Stop the feed if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n**See also:**\n\n- [Register an Intent Handler](../spec#register-an-intent-handler)\n- [`PrivateChannel`](PrivateChannel)\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`IntentHandler`](Types#intenthandler)\n\n### `broadcast`\n\n```ts\nbroadcast(context: Context): Promise<void>;\n```\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User Channel_ the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\nDesktopAgent implementations SHOULD ensure that context messages broadcast to a channel by an application joined to it are not delivered back to that same application.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n**See also:**\n\n- [addContextListener](#addcontextlistener)\n\n### `createPrivateChannel`\n\n```ts\ncreatePrivateChannel(): Promise<PrivateChannel>;\n```\n\nReturns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.\n\nIf the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\nThe `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n**Example:**\n\n```js\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // This gets called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  const unsubscribeListener = channel.onUnsubscribe((contextType) => {\n    feed.stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n**See also:**\n\n- [`PrivateChannel`](PrivateChannel)\n- [`raiseIntent`](#raiseintent)\n- [`addIntentListener`](#addintentlistener)\n\n### `findInstances`\n\n```ts\nfindInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n```\n\nFind all the available instances for a particular application.\n\nIf the application is not known to the agent, the returned promise should be rejected with the `ResolverError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array.\n\nIf the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n```js\n// Retrieve a list of instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Target a raised intent at a specific instance\nlet resolution = fdc3.raiseIntent(\"ViewInstrument\", context, instances[0]);\n```\n\n### `findIntent`\n\n```ts\nfindIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n```\n\nFind out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type.\n\n`findIntent` is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to an `AppIntent` which provides details of the intent, its metadata and metadata about the apps and app instances that are registered to handle it. This can be used to raise the intent against a specific app or app instance.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no apps are found that resolve the intent, when the [`ResolveError.NoAppsFound`](Errors#resolveerror) message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nResult types 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.\n\n**Examples:**\n\nI know 'StartChat' exists as a concept, and want to know which apps can resolve it:\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Slack\" }\n//   ]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0]);\n\n//later, we want to raise 'StartChat' intent again\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns an AppIntent, but with multiple options for resolution,\n// which includes an existing instance of an application:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//    { appId: \"Slack\" }\n//   ]\n```\n\nAn optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types.\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\", contact);\n\n// returns only apps that support the type of the specified input context:\n// {\n//     intent: { name: \"StartChat\" },\n//     apps: { name: \"Symphony\" }]\n// }\n\nconst appIntent = await fdc3.findIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     intent: { name: \"ViewContact\" },\n//     apps: { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }\n\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     intent: { name: \"QuoteStream\" },\n//     apps: { appId: \"MyOMS\", resultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n**See also:**\n\n- [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n```ts\nfindIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n```\n\nFind all the available intents for a particular context, and optionally a desired result context type.\n\n`findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.\nA 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.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no intents with associated apps are found, when the `ResolveError.NoAppsFound` message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nThe 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 without a specified context type, 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.\n\n**Example:**\n\nI 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...\n\n```js\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [\n//   {\n//     intent: { name: \"StartCall\" },\n//     apps: [{ appId: \"Skype\" }]\n//   },\n//   {\n//     intent: { name: \"StartChat\" },\n//     apps: [\n//       { appId: \"Skype\" },\n//       { appId: \"Symphony\" },\n//       { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//       { appId: \"Slack\" }\n//     ]\n//   },\n//   {\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n//   }\n// ];\n```\n\nor I look for only intents that are resolved by apps returning a particular result type\n\n```js\nconst appIntentsForType = await fdc3.findIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app or instance\nconst selectedApp = startChat.apps[2];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp);\n```\n\n**See also:**\n\n- [`findIntent()`](#findintent)\n- [`ResolveError`](Errors#resolveerror)\n\n### `getAppMetadata`\n\n```ts\ngetAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n```\n\nRetrieves the [`AppMetadata`](Metadata#appmetadata) for an [`AppIdentifier`](Types#appidentifier), which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes.\n\nIf the app is not found, the promise MUST be rejected with an `Error` Object with the `message` given by [`ResolveError.TargetAppUnavailable`](Errors#resolveerror), or (if connected to a Desktop Agent Bridge) an error from the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n\n**Examples:**\n\n```js\nlet appIdentifier = { appId: \"MyAppId@my.appd.com\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`AppIdentifier`](Types#appidentifier)\n\n### `getCurrentChannel`\n\n```ts\ngetCurrentChannel() : Promise<Channel | null>;\n```\n\nOPTIONAL function that returns the `Channel` object for the current User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nReturns `null` if the app is not joined to a channel.\n\n**Examples:**\n\n```js\n// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getInfo`\n\n```ts\ngetInfo(): Promise<ImplementationMetadata>;\n```\n\nRetrieves information about the FDC3 Desktop Agent implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent.\n\nReturns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.  This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes.\n\n**Example:**\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\nThe `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n```\n\n**See also:**\n\n- [`ImplementationMetadata`](Metadata#implementationmetadata)\n- [`AppMetadata`](Metadata#appmetadata)\n\n### `getOrCreateChannel`\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\nReturns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist.\n\nIf the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n\n**Example:**\n\n```js\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  myChannel.addContextListener(null, context => { /* do something with context */});\n}\ncatch (err){\n  //app could not register the channel\n}\n```\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getUserChannels`\n\n```ts\ngetUserChannels() : Promise<Array<Channel>>;\n```\n\nRetrieves a list of the User Channels available for the app to join.\n\n**Example:**\n\n```js\nconst userChannels = await fdc3.getUserChannels();\nconst redChannel = userChannels.find(c => c.id === 'red');\n```\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `joinUserChannel`\n\n```ts\njoinUserChannel(channelId: string) : Promise<void>;\n```\n\nOPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nIf an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.\n\nIf the channel already contains context that would be passed to context listeners added via `fdc3.addContextListener` then those listeners will be called immediately with that context.\n\nAn app can only be joined to one channel at a time.\n\nIf an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Examples:**\n\n```js\n// get all user channels\nconst channels = await fdc3.getUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\nfdc3.joinUserChannel(selectedChannel.id);\n\n```\n\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `leaveCurrentChannel`\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\nOPTIONAL function that removes the app from any User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nContext broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel.\n\n**Examples:**\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(null, context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(null, channelListener);\n\n```\n\n### `open`\n\n```ts\nopen(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n```\n\nLaunches an app, specified via an [`AppIdentifier`](Types#appidentifier) object.\n\nThe `open` method differs in use from [`raiseIntent`](#raiseintent).  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying an App Directory, `open` would be used to open an app returned in the search results.\n\n**Note**, if the intent, context and target app name are all known, it is recommended to instead use [`raiseIntent`](#raiseintent) with the `target` argument.\n\nIf a [`Context`](Types#context) object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n\nReturns an [`AppIdentifier`](Types#appidentifier) object with the `instanceId` field set to identify the instance of the application opened by this call.\n\nIf an error occurs while opening the app, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`OpenError`](Errors#openerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n ```js\n// Open an app without context, using an AppIdentifier object to specify the target\nlet appIdentifier = { appId: 'myApp-v1.0.1' };\nlet instanceIdentifier = await fdc3.open(appIdentifier);\n\n// Open an app with context\nlet instanceIdentifier = await fdc3.open(appIdentifier, context);\n```\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppMetadata`](Metadata#appmetadata)\n- [`OpenError`](Errors#openerror)\n\n### `raiseIntent`\n\n```ts\nraiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\nRaises a specific intent for resolution against apps registered with the desktop agent.\n\nThe 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.\nAlternatively, 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).\n\nIf 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, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\nIf 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.\n\nReturns an [`IntentResolution`](Metadata#intentresolution) object with details of the app instance that was selected (or started) to respond to the intent.\n\nIssuing 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, Channel object or void 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 valid response (a promise or void), or (3) the returned promise resolves to an invalid type.\n\n**Example:**\n\n```js\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait fdc3.raiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Raise an intent without a context by using the null context type\nawait fdc3.raiseIntent(\"StartChat\", {type: \"fdc3.nothing\"});\n\n//Raise an intent and retrieve a result from the IntentResolution\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  if (result && result.broadcast) { //detect whether the result is Context or a Channel\n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n```\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResult`](Types#intentresult)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n- [`ResultError`](Errors#resulterror)\n\n### `raiseIntentForContext`\n\n```ts\nraiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\nFinds and raises an intent against apps registered with the desktop agent based purely on the type of the context data.\n\nThe desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context.\nAlternatively, the specific app or app instance to target can also be provided, in which case any method of resolution SHOULD only consider intents supported by the specified application.\n\nUsing `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app.\n\nReturns an `IntentResolution` object, see [`raiseIntent()`](#raiseintent) for details.\n\nIf a target intent and app cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\n**Example:**\n\n```js\n// Display a resolver UI for the user to select an intent and application to resolve it\nconst intentResolution = await fdc3.raiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait fdc3.raiseIntentForContext(context, targetAppIdentifier);\n```\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`raiseIntent()`](#raiseintent)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n```ts\naddContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\nAdds a listener for incoming context broadcasts from the Desktop Agent. Provided for backwards compatibility with versions FDC3 standard &lt;2.0.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n\n### `getSystemChannels` (deprecated)\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\nAlias to the [`getUserChannels`](#getuserchannels) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `joinChannel` (deprecated)\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\nAlias to the [`joinUserChannel`](#joinuserchannel) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n\n**See also:**\n\n- [`joinUserChannel`](#joinuserchannel)\n\n### `open` (deprecated)\n\n```ts\nopen(name: string, context?: Context): Promise<AppIdentifier>;\n```\n\nVersion of `open` that launches an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`open`](#open)\n\n### `raiseIntent` (deprecated)\n\n```ts\nraiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n```\n\nVersion of `raiseIntent` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntent`](#raiseintent)\n\n### `raiseIntentForContext` (deprecated)\n\n```ts\nraiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;;\n```\n\nVersion of `raiseIntentForContext` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntentForContext`](#raiseintentforcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/Errors.md",
    "content": "---\ntitle: Errors\n---\n\nFDC3 API operations may sometimes result in an error, which must be returned to the caller. Errors should be returned by rejecting the promise returned by the API with a JavaScript `Error` object (or equivalent for the language of the implementation). The `Error` Object's message should be chosen from the appropriate Error enumeration below.\n\n## `ChannelError`\n\n```typescript\nenum ChannelError {\n  /** Returned if the specified channel is not found when attempting to join a\n   *  channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).\n   */\n  NoChannelFound = 'NoChannelFound',\n\n  /** SHOULD be returned when a request to join a user channel or to a retrieve\n   *  a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods\n   *  of the DesktopAgent (`fdc3`) object is denied. \n   */\n  AccessDenied = 'AccessDenied',\n  \n  /** SHOULD be returned when a channel cannot be created or retrieved via the\n   *  `getOrCreateChannel` method of the DesktopAgent (`fdc3`).\n   */\n  CreationFailed = 'CreationFailed',\n\n  /** Returned if a call to the `broadcast` functions is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = 'MalformedContext',\n}\n```\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n**See also:**\n\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n\n## `OpenError`\n\n```typescript\nenum OpenError {\n  /** Returned if the specified application is not found.*/\n  AppNotFound = 'AppNotFound',\n\n  /** Returned if the specified application fails to launch correctly.*/\n  ErrorOnLaunch = 'ErrorOnLaunch',\n\n  /** Returned if the specified application launches but fails to add a context\n   *  listener in order to receive the context passed to the `fdc3.open` call.\n   */\n  AppTimeout = 'AppTimeout',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = 'ResolverUnavailable',\n\n  /** Returned if a call to the `open` function is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = 'MalformedContext',\n\n    /** @experimental Returned if the specified Desktop Agent is not found, via a connected \n   *  Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n**See also:**\n\n- [`DesktopAgent.open`](DesktopAgent#open)\n\n## `ResolveError`\n\n```typescript\nexport enum ResolveError {\n  /** SHOULD be returned if no apps are available that can resolve the intent\n   *  and context combination.\n   */\n  NoAppsFound = 'NoAppsFound',\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = 'ResolverUnavailable',\n\n  /** Returned if the user cancelled the resolution request, for example by\n   *  closing or cancelling a resolver UI.\n   */\n  UserCancelled = 'UserCancelledResolution',\n\n  /** SHOULD be returned if a timeout cancels an intent resolution that\n   *  required user interaction. Please use `ResolverUnavailable` instead for\n   *  situations where a resolver UI or similar fails.\n   */\n  ResolverTimeout = 'ResolverTimeout',\n\n  /** Returned if a specified target application is not available or a new\n   *  instance of it cannot be opened. \n   */\n  TargetAppUnavailable = 'TargetAppUnavailable',\n\n  /** Returned if a specified target application instance is not available,\n   *  for example because it has been closed. \n   */\n  TargetInstanceUnavailable = 'TargetInstanceUnavailable',\n\n  /** Returned if the intent and context could not be delivered to the selected\n   *  application or instance, for example because it has not added an intent\n   *  handler within a timeout.\n   */\n  IntentDeliveryFailed = 'IntentDeliveryFailed',\n\n  /** Returned if a call to one of the `raiseIntent` functions is made with an \n   *  invalid context argument. Contexts should be Objects with at least a `type`\n   *  field that has a `string` value.\n   */\n  MalformedContext = 'MalformedContext',\n\n    /** @experimental Returned if the specified Desktop Agent is not found, via a connected \n   *  Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent), [`findIntentsByContext`](DesktopAgent#findintentsbycontext), [`raiseIntent`](DesktopAgent#raiseintent) or [`raiseIntentForContext`](DesktopAgent#raiseintentforcontext) methods on the [DesktopAgent](DesktopAgent).\n\n**See also:**\n\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n\n## `ResultError`\n\n```typescript\nenum ResultError {\n  /** Returned if the intent handler exited without returning a valid result \n   * (a promise resolving to a Context, Channel object or void).\n   */\n  NoResultReturned = 'NoResultReturned',\n\n  /** Returned if the `IntentHandler` function processing the raised intent\n   *  throws an error or rejects the Promise it returned. \n   */\n  IntentHandlerRejected = 'IntentHandlerRejected',\n}\n```\n\nContains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object.\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `BridgingError`\n\n`@experimental`\n\n```typescript\nenum BridgingError {\n  /** @experimental Returned if a Desktop Agent did not return a response, via \n   *  Desktop Agent Bridging, within the alloted timeout. */\n  ResponseTimedOut = 'ResponseToBridgeTimedOut',\n  /** @experimental Returned if a Desktop Agent that has been targeted by a \n   *  particular request has been disconnected from the Bridge before a \n   *  response has been received from it. */\n  AgentDisconnected = 'AgentDisconnected',\n  /** @experimental Returned for FDC3 API calls that are specified with\n   *  arguments indicating that a remote Desktop agent should be targeted\n   *  (e.g. raiseIntent with an app on a remote DesktopAgent targeted), \n   *  when the local Desktop Agent is not connected to a bridge. */\n  NotConnectedToBridge = 'NotConnectedToBridge',\n  /** @experimental Returned if a message to a Bridge deviates from the schema\n   *  for that message sufficiently that it could not be processed.\n   */\n  MalformedMessage = 'MalformedMessage'\n}\n```\n\nContains constants representing the errors that can be encountered when queries are forwarded to a Desktop Agent Bridge, but one or more remote Desktop Agents connected to it disconnects, times-out or a malformed message is encountered while a particular request is in flight. These errors may be returned via the FDC3 API when a Desktop Agent is (or was) connected to a Desktop Agent Bridge.\n\n**See also:**\n\n- [Agent Bridging - Workflows broken by disconnects](../../agent-bridging/spec#workflows-broken-by-disconnects)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/Globals.md",
    "content": "---\ntitle: Globals\n---\n\nSince FDC3 is typically available to the whole web application, desktop agents are expected to make the [`DesktopAgent`](DesktopAgent) interface available at a global level.\n\n## `window.fdc3` Object\n\nThe global `fdc3` object can be used to access FDC3 API operations, if the current desktop agent supports FDC3.\n\n**Example:**\n\n```ts\n// check if fdc3 is available\nif (window.fdc3) {\n  // raise an intent\n  await window.fdc3.raiseIntent('StartChat', {\n    type: 'fdc3.contact',\n    id: { email: 'johndoe@mail.com' }\n  })\n}\n```\n\n## `fdc3Ready` Event\n\nThe global `window.fdc3` should only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors should provide an `fdc3Ready` event.\n\n**Example:**\n\n```ts\nfunction fdc3Action() {\n  // Make some fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Action();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Action);\n}\n```\n\n## `fdc3Ready()` Function\n\nIf you are using the `@finos/fdc3` NPM package, it includes a handy wrapper function that will check for the existence of `window.fdc3` and wait on the `fdc3Ready` event for you.\n\nIt returns a promise that will resolve immediately if the `window.fdc3` global is already defined, or reject with an error if the `fdc3Ready` event doesn't fire after a specified timeout period (default: 5 seconds).\n\n**Example:**\n\n```ts\nimport { fdc3Ready, broadcast } from '@finos/fdc3'\n\nasync function fdc3Action() {\n  try {\n    await fdc3Ready(1000); // wait for (at most) 1 second\n    broadcast({\n      type: 'fdc3.instrument',\n      id: { ticker: 'AAPL' }\n    })\n  } catch (error) {\n    // handle error\n  }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/Metadata.md",
    "content": "---\ntitle: Metadata\n---\n\nFDC3 API operations return various types of metadata.\n\n## `AppIntent`\n\n```ts\ninterface AppIntent {\n  /** Details of the intent whose relationship to resolving applications is\n   *  being described.\n   */\n  readonly intent: IntentMetadata;\n\n  /** Details of applications that can resolve the intent. */\n  readonly apps: Array<AppMetadata>;\n}\n```\n\nAn interface that represents the binding of an intent to apps, returned as part of intent discovery.\nFor each intent, it reference the applications that support that intent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`IntentMetadata`](#intentmetadata)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `AppMetadata`\n\n```ts\ninterface AppMetadata extends AppIdentifier {\n  /**\n   *  The 'friendly' app name. This field was used with the `open` and\n   *  `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier`\n   *  with `appId` set. \n   * \n   *  Note that for display purposes the `title` field should be used, if set,\n   *  in preference to this field.\n   */\n  readonly name?: string;\n\n  /** The version of the application. */\n  readonly version?: string;\n\n  /** An optional set of, implementation specific, metadata fields that can be\n   *  used to disambiguate instances, such as a window title or screen position.\n   *  Must only be set if `instanceId` is set. \n   */\n  readonly instanceMetadata?: Record<string, any>;\n\n  /** A more user-friendly application title that can be used to render UI\n   *  elements.\n   */\n  readonly title?: string;\n\n  /** A tooltip for the application that can be used to render UI elements. */\n  readonly tooltip?: string;\n\n  /** A longer, multi-paragraph description for the application that could\n   *  include mark-up.\n   */\n  readonly description?: string;\n\n  /** A list of icon URLs for the application that can be used to render UI \n   *  elements.\n   */\n  readonly icons?: Array<Icon>;\n\n  /** Images representing the app in common usage scenarios that can be used to render UI elements */\n  readonly screenshots?: Array<Image>;\n  \n  /** The type of result returned for any intent specified during resolution. \n   *  May express a particular context type (e.g. \"fdc3.instrument\"), channel \n   *  (e.g. \"channel\") or a channel that will receive a specified type \n   *  (e.g. \"channel<fdc3.instrument>\").\n   */\n  readonly resultType?: string | null;\n}\n```\n\nExtends an AppIdentifier, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\n\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\n\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc..\n\n**See also:**\n\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppIntent.apps`](#appintent)\n- [`Icon`](#icon)\n- [`Image`](#image)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## `ContextMetadata`\n\n```ts\ninterface ContextMetadata {\n  /** Identifier for the app instance that sent the context and/or intent. \n   *  @experimental \n   */\n  readonly source: AppIdentifier;\n}\n```\n\nMetadata relating to a context or intent & context received through the `addContextListener` and `addIntentListener` functions. Currently identifies the app that originated the context or intent message.\n\n[`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`ContextHandler`](Types#contexthandler)\n- [`IntentHandler`](Types#intenthandler)\n- [`addIntentListener`](DesktopAgent#addintentlistener)\n- [`addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DisplayMetadata`\n\n```ts\ninterface DisplayMetadata {\n  /**\n   *  A user-readable name for this channel, e.g: `\"Red\"`. */\n  readonly name?: string;\n\n  /**\n   *  The color that should be associated within this channel when displaying\n   *  this channel in a UI, e.g: `#FF0000`. May be any color value supported by\n   *  CSS, e.g. name, hex, rgba, etc.. */\n  readonly color?: string;\n\n  /**\n   *  A URL of an image that can be used to display this channel. */\n  readonly glyph?: string;\n}\n```\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n\n## `Icon`\n\n```typescript\ninterface Icon {\n  src: string;\n  size?: string;\n  type?: string;\n}\n```\n\nMetadata relating to a single icon image at a remote URL, used to represent an application in a user interface.\n\nAppMetadata includes an icons property allowing multiple icon types to be specified. Various properties may be used by the Desktop Agent to decide which icon is the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n```js\n\"icons\": [\n  {\n    \"src\": \"https://app.foo.icon/app_icons/lowres.webp\",\n    \"size\": \"48x48\",\n    \"type\": \"image/webp\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_icons/hd_hi.svg\",\n    \"size\": \"72x72\",\n    \"type\": \"image/svg+xml\"\n  }\n]\n```\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the icon.\n- **`size`:** The dimensions of the Icon formatted as `<height>x<width>`.\n- **`type`:** The media type of the icon. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `Image`\n\n```typescript\ninterface Image {\n  src: string;\n  size?: string;\n  type?: string;\n  label?: string;\n}\n```\n\nMetadata relating to a single image at a remote URL, used to represent screenshot images.\n\nAppMetadata includes a screenshots property allowing multiple images to be specified. Various properties may be used by the Desktop Agent to decide which image(s) are the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n```js\n\"screenshots\": [\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/dashboard.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Example app dashboard\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/notifications.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Order notifications view\"\n  }\n]\n```\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the image.\n- **`size`:** The dimensions of the image formatted as `<height>x<width>`.\n- **`type`:** The media type of the image. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `ImplementationMetadata`\n\n```ts\ninterface ImplementationMetadata {\n  /** The version number of the FDC3 specification that the implementation\n   *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  readonly fdc3Version: string;\n\n  /** The name of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. io.Connect, OpenFin etc.).\n   */\n  readonly provider: string;\n\n  /** The version of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. 5.3.0).\n   */\n  readonly providerVersion?: string;\n\n  /** Metadata indicating whether the Desktop Agent implements optional features of\n   *  the Desktop Agent API.\n   */\n  readonly optionalFeatures: {\n    /** Used to indicate whether the exposure of 'originating app metadata' for\n     *  context and intent messages is supported by the Desktop Agent.*/\n    readonly OriginatingAppMetadata: boolean;\n    /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n     *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n     *  the Desktop Agent.*/\n    readonly UserChannelMembershipAPIs: boolean;\n    /** Used to indicate whether the experimental Desktop Agent Bridging\n     *  feature is implemented by the Desktop Agent.*/\n    readonly DesktopAgentBridging: boolean;\n  };\n\n  /** The calling application instance's own metadata, according to the \n   *  Desktop Agent (MUST include at least the `appId` and `instanceId`).\n   */\n  readonly appMetadata: AppMetadata;\n}\n```\n\nMetadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number and the metadata of the calling application according to the desktop agent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`DesktopAgent.getInfo`](DesktopAgent#getinfo)\n\n## `IntentMetadata`\n\n```ts\ninterface IntentMetadata {\n  /** The unique name of the intent that can be invoked by the raiseIntent call. */\n  readonly name: string;\n\n  /** Display name for the intent.\n   * @deprecated Use the intent name for display as display name may vary for\n   * each application as it is defined in the app's AppD record.\n   */\n  readonly displayName: string;\n}\n```\n\nThe interface used to describe an intent within the platform.\n\n**See also:**\n\n- [`AppIntent.intent`](#appintent)\n\n## `IntentResolution`\n\n```ts\ninterface IntentResolution {\n\n  /** Identifier for the app instance that was selected (or started) to resolve\n   *  the intent. `source.instanceId` MUST be set, indicating the specific app \n   *  instance that received the intent.\n   */\n  readonly source: AppIdentifier;\n\n  /** The intent that was raised. May be used to determine which intent the user\n   *  chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  readonly intent: string;\n\n  /** The version number of the Intents schema being used.\n   */\n  readonly version?: string;\n  \n  /** Retrieves a promise that will resolve to `Context` data returned \n   *  by the application that resolves the raised intent, a `Channel` \n   *  established and returned by the app resolving the intent or void. \n   * \n   *  A `Channel` returned MAY be of the `PrivateChannel` type. The \n   *  client can then `addContextListener()` on that channel to, for example, \n   *  receive a stream of data.\n   * \n   *  If an error occurs (i.e. an error is thrown by the handler function,\n   *  the promise it returns is rejected, or the promise resolved to an invalid \n   *  type) then the Desktop Agent MUST reject the promise returned by the \n   *  `getResult()` function of the `IntentResolution` with a string from\n   *  the `ResultError` enumeration.\n   */\n   getResult(): Promise<IntentResult>;\n}\n```\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n\n**Examples:**\n\n```js\n// Resolve a \"Chain\" type intent\nlet resolution = await agent.raiseIntent(\"intentName\", context);\n\n// Use metadata about the resolving app instance to target a further intent\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //Some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err) { ... }                                    \n                                               \n//Resolve a \"Client-Service\" type intent with a data or channel response\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n    const result = await resolution.getResult();\n    if (result && result.broadcast) { //detect whether the result is Context or a Channel\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\n    } else if (result){\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n    } else {\n        console.error(`${resolution.source} didn't return anything`);\n    }\n} catch(error) {\n    console.error(`${resolution.source} returned an error: ${error}`);\n}\n```\n\n**See also:**\n\n- [`IntentResult`](Types#intentresult)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`AppIdentifier`](Types#appidentifier)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/PrivateChannel.md",
    "content": "---\nid: PrivateChannel\nsidebar_label: PrivateChannel\ntitle: PrivateChannel\nhide_title: true\n---\n# `PrivateChannel`\n\nObject representing a private context channel, which is intended to support secure communication between applications, and extends the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n```ts\ninterface  PrivateChannel extends Channel {\n  // methods\n  onAddContextListener(handler: (contextType?: string) => void): Listener;\n  onUnsubscribe(handler: (contextType?: string) => void): Listener;\n  onDisconnect(handler: () => void): Listener;\n  disconnect(): void;\n}\n```\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## Examples\n\n### 'Server-side' example\n\nThe intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextlistener()` on that channel, the intent app receives notice via the handler added with `onAddContextListener()` and knows that the client is ready to start receiving quotes.\n\nThe Desktop Agent knows that a channel is being returned by inspecting the object returned from the handler (e.g. check constructor or look for private member).\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses.\n\n```typescript\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const channel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = channel.onAddContextListener((contextType) => {\n        // broadcast price quotes as they come in from our quote feed\n        feed.onQuote(symbol, (price) => {\n            channel.broadcast({ type: \"price\", price});\n        });\n    });\n\n    // This gets called when the remote side calls Listener.unsubscribe()\n    const unsubscribeListener = channel.onUnsubscribe((contextType) => {\n        feed.stop(symbol);\n    });\n\n    // This gets called if the remote side closes\n    const disconnectListener = channel.onDisconnect(() => {\n        feed.stop(symbol);\n    });\n\n    return channel;\n});\n```\n\n### 'Client-side' example\n\nThe 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. A listener may also be to clear up if the 'server-side' disconnects from the stream.\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses.\n\n```javascript\ntry {\n    const resolution3 = await fdc3.raiseIntent(\"QuoteStream\", { type: \"fdc3.instrument\", id : { ticker: \"AAPL\" } });\n    try {\n           const result = await resolution3.getResult();\n         //check that we got a result and that it's a channel\n         if (result && result.addContextListener) {\n             const listener = result.addContextListener(\"price\", (quote) => console.log(quote));\n               \n               //if it's a PrivateChannel\n               if (result.onDisconnect) {\n                   result.onDisconnect(() => {\n                         console.warn(\"Quote feed went down\");\n                   });\n\n                   // Sometime later...\n                   listener.unsubscribe();\n               }\n        } else {\n            console.warn(`${resolution3.source} did not return a channel`);\n        }\n    } catch(channelError) {\n          console.log(`Error: ${resolution3.source} returned an error: ${channelError}`);\n    }\n} catch (resolverError) {\n    console.error(`Error: Intent was not resolved: ${resolverError}`);\n}\n```\n\n## Methods\n\n### `onAddContextListener`\n\n```ts\nonAddContextListener(handler: (contextType?: string) => void): Listener;\n```\n\nAdds a listener that will be called each time that the remote app invokes addContextListener on this channel.\n\nDesktop Agents MUST call this for each invocation of addContextListener on this channel, including those that occurred before this handler was registered (to prevent race conditions).\n\n**See also:**\n\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n### `onUnsubscribe`\n\n```ts\nonUnsubscribe(handler: (contextType?: string) => void): Listener;\n```\n\nAdds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added.\n\nDesktop Agents MUST call this when disconnect() is called by the other party, for each listener that they had added.\n\n**See also:**\n\n- [`Listener`](Types#listener)\n\n### `onDisconnect`\n\n```ts\nonDisconnect(handler: () => void): Listener;\n```\n\nAdds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called. This is in addition to calls that will be made to onUnsubscribe listeners.\n\n**See also:**\n\n- [`disconnect`](#disconnect)\n\n### `disconnect`\n\n```ts\ndisconnect(): void;\n```\n\nMay be called to indicate that a participant will no longer interact with this channel.\n\nAfter this function has been called, Desktop Agents SHOULD prevent apps from broadcasting on this channel and MUST automatically call Listener.unsubscribe() for each listener that they've added (causing any `onUnsubscribe` handler added by the other party to be called) before triggering any onDisconnect handler added by the other party.\n\n**See also:**\n\n- [`onUnsubscribe`](#onunsubscribe)\n- [`Listener`](Types#listener)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/ref/Types.md",
    "content": "---\ntitle: Types\n---\n\nFDC3 API operations make use of several type declarations.\n\n## `AppIdentifier`\n\nIdentifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.\nWill always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc..\nIf the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id.\n\n```ts\ninterface AppIdentifier {\n  /** The unique application identifier located within a specific application\n   *  directory instance. An example of an appId might be 'app@sub.root'.\n   */\n  readonly appId: string;\n  \n  /** An optional instance identifier, indicating that this object represents a\n   *  specific instance of the application described.\n   */\n  readonly instanceId?: string;\n\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Context`\n\n```typescript\ninterface Context {\n  id?: { [key: string]: string };\n  name?: string;\n  type: string;\n}\n```\n\nThe base interface that all contexts should extend: a context data object adhering to the [FDC3 Context Data specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n**See also:**\n\n- [`ContextHandler`](#contexthandler)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `ContextHandler`\n\n```typescript\ntype ContextHandler = (context: Context, metadata?: ContextMetadata) => void;\n```\n\nDescribes a callback that handles a context event. Optional metadata about the context message, including the app that originated the message, may be provided.\n\nUsed when attaching listeners for context broadcasts.\n\nOptional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DesktopAgentIdentifier`\n\n```typescript\n/** @experimental */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent.**/\n  readonly desktopAgent: string;\n}\n```\n\n(Experimental) Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no app details are available or are appropriate.\n\n**See also:**\n\n* [Agent Bridging - Identifying Desktop Agents Identity and Message Sources](../../agent-bridging/spec#identifying-desktop-agents-identity-and-message-sources)\n\n## `IntentHandler`\n\n```typescript\ntype IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise<IntentResult> | void;\n```\n\nDescribes a callback that handles a context event and may return a promise of a Context, Channel object or `void` to be returned to the application that raised the intent.\n\nUsed when attaching listeners for raised intents.\n\nOptional metadata about the intent & context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`PrivateChannel`](PrivateChannel)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `IntentResult`\n\n```typescript\ntype IntentResult = Context | Channel | void;\n```\n\nDescribes results that an Intent handler may return that should be communicated back to the app that raised the intent, via the [`IntentResolution`](Metadata#intentresolution).\n\nRepresented as a union type in TypeScript, however, this type may be rendered as an interface in other languages that both the `Context` and `Channel` types implement, allowing either to be returned by an `IntentHandler`.\n\n**See also:**\n\n- [`Context`](#context)\n- [`Channel`](Channel)\n- [`PrivateChannel`](PrivateChannel)\n- [`IntentHandler`](#intenthandler)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Listener`\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object.\n\n```typescript\ninterface Listener {\n  unsubscribe(): void;\n}\n```\n\n### `unsubscribe`\n\n```ts\nunsubscribe(): void;\n```\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`ContextHandler`](Types#contexthandler)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/api/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: API Overview (2.1)\n---\n\nThe role of FDC3 API is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications, standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe following sections examine the API's use-cases and core concepts. The APIs a fully defined in both subsequent pages of this Part and a full set of TypeScript definitions in the [src](https://github.com/finos/FDC3/tree/main/src/api) directory of the [FDC3 GitHub repository](https://github.com/finos/FDC3/).\n\n## Components\n\n### Desktop Agent\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- io.Connect\n- OpenFin\n- Refinitiv Eikon\n\nAn FDC3-compliant Desktop Agent exposes an FDC3 Standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n### Application\n\nAn application is any endpoint on the desktop that is:\n\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of endpoints include:\n\n- Native Applications\n- Web Applications\n- Headless “services” running on the desktop\n\n## Desktop Agent Implementation\n\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A Desktop Agent MUST provide implementations for the following interfaces:\n\n- [`DesktopAgent`](ref/DesktopAgent)\n- [`Channel`](ref/Channel)\n- [`PrivateChannel`](ref/PrivateChannel)\n- [`Listener`](ref/Types#listener)\n\nOther interfaces defined in the spec are not critical to define as concrete types.  Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.\n\n### API Access\n\nThe FDC3 API can be made available to an application through a number of different methods.  In the case of web applications, a Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means.\n\nThe global `window.fdc3` must only be available after the API is ready to use. To enable applications to avoid using the API before it is ready, implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use. Implementations should first check for the existence of the FDC3 API and add a listener for this event if it is not found:\n\n```js\nfunction fdc3Stuff() {\n  // Make fdc3 API calls here\n}\n\nif (window.fdc3) {\n  fdc3Stuff();\n} else {\n  window.addEventListener('fdc3Ready', fdc3Stuff);\n}\n```\n\n### Standards vs. Implementation\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n\n- workspace management\n- user identity and SSO\n- entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n### Inter-Agent Communication\n\nA goal of the FDC3 Standard is that applications running in different Desktop Agent contexts on the same desktop, or operated by the same user, would be able to interoperate and that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context. As Desktop Agent interop is supported by common standards for APIs an app in one Desktop Agent context would not need to know a different syntax to launch or interact with an app in another Desktop Agent context.\n\nInter-agent communication at the API layer may be achieved via the [Desktop Agent Bridging Part of the FDC3 Standard](../agent-bridging/spec) ([@experimental](../fdc3-compliance#experimental-features)), which defines an independent service that Desktop Agents may connect to, and a protocol for the exchange of messages relating to FDC3 API calls. Hence, by implementing support for Desktop Agent Bridging, a platform may extend interop across applications running in multiple Desktop Agent contexts.\n\nDesktop Agent Bridging provides message exchanges and a workflow for performing intent resolution across multiple agents. Hence, app discovery is supported across the agents connected to the bridge for intent-based workflows. Further, as channels are also supported by bridging, context sharing also works across multiple agents.\n\nThere is currently no method of discovering all the apps supported by a Desktop Agent in the FDC3 API nor bridging. Hence, to support launching, via `fdc3.open` across the connected Desktop Agents, application details must be known in advance. This may be achieved by connecting Desktop Agents to the same App Directories.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\n### Desktop Agent API Standard Compliance\n\nAn FDC3 Standard compliant Desktop Agent implementation **MUST**:\n\n- Provide the FDC3 API to web applications via a global accessible as [`window.fdc3`](#api-access).\n- Provide a global [`fdc3Ready`](#api-access) event that is fired when the API is ready for use.\n- Provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to `raiseIntentForContext` that return multiple options), such as a resolver UI.\n  - Intent resolution MUST take into account any specified input or return context types\n  - Requests for resolution to apps returning a channel MUST include any apps that are registered as returning a channel with a specific type.\n- Return (JavaScript or platform appropriate) Error Objects with messages from the [`ChannelError`](ref/Errors#channelerror), [`OpenError`](ref/Errors#openerror), [`ResolveError`](ref/Errors#resolveerror) and [`ResultError`](ref/Errors#resulterror) enumerations as appropriate.\n- Accept as input and return as output data structures that are compatible with the interfaces defined in this Standard.\n- Include implementations of the following [Desktop Agent](ref/DesktopAgent) API functions, as defined in this Standard:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener)\n  - [`addIntentListener`](ref/DesktopAgent#addintentlistener)\n  - [`broadcast`](ref/DesktopAgent#broadcast)\n  - [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel)\n  - [`findInstances`](ref/DesktopAgent#findinstances)\n  - [`findIntent`](ref/DesktopAgent#findintent)\n  - [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n  - [`getInfo`](ref/DesktopAgent#getinfo)\n  - [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel)\n  - [`getUserChannels`](ref/DesktopAgent#getuserchannels)\n  - [`open`](ref/DesktopAgent#open)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext)\n- Provide an ID for each [`PrivateChannel`](ref/PrivateChannel) created via [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel) and prevent them from being retrieved via [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) by ID.\n- Only require app directories that they connect to to have implemented only the minimum requirements specified in the [App Directory API Part](../app-directory/spec) of this Standard.\n- Provide details of whether they implement optional features of the Desktop Agent API in the `optionalFeatures` property of the [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned by the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function.\n- Allow, by default, at least a 15 second timeout for an application, launched via [`fdc3.open`](../api/ref/DesktopAgent#open), [`fdc3.raiseIntent`](../api/ref/DesktopAgent#raiseintent) or [`fdc3.raiseIntentForContext`](../api/ref/DesktopAgent#raiseintentforcontext) to add any context listener (via [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener)) or intent listener (via [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener)) necessary to deliver context or intent and context to it on launch. This timeout only applies to listeners needed to receive context on launch; further intent and context listeners not required on launch MAY be added later.\n\nAn FDC3 Standard compliant Desktop Agent implementation **SHOULD**:\n\n- Support connection to one or more App Directories meeting the [FDC3 App Directory Standard](../app-directory/overview).\n- Qualify `appId` values received from an app directory with the hostname of the app directory server (e.g. `myAppId@name.domain.com`) [as defined in the app directory standard](../app-directory/overview#application-identifiers).\n- Allow applications to register an [`IntentHandler`](ref/Types#intenthandler) for particular Intent and Context type pairs by providing `interop.intents.listensFor` metadata in their AppD record.\n- Adopt the [recommended set of User channel definitions](#recommended-user-channel-set).\n- Ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.\n- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.\n- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.\n\nAn FDC3 Standard compliant Desktop Agent implementation **MAY**:\n\n- Make the Desktop Agent API available through modules, imports, or other means.\n- Support multiple routes for registration of an [`IntentHandler`](ref/Types#intenthandler) by an app to be considered during Intent resolution, including dynamic registration of apps at runtime.\n- Implement the following OPTIONAL [Desktop Agent](ref/DesktopAgent) API functions:\n  - [`joinUserChannel`](ref/DesktopAgent#joinuserchannel)\n  - [`leaveCurrentChannel`](ref/DesktopAgent#leavecurrentchannel)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n- Implement the following deprecated API functions:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener-deprecated) (without a contextType argument)\n  - [`getSystemChannels`](ref/DesktopAgent#getsystemchannels-deprecated) (renamed getUserChannels)\n  - [`joinChannel`](ref/DesktopAgent#joinchannel-deprecated) (renamed joinUserChannel)\n  - [`open`](ref/DesktopAgent#open-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext-deprecated) (deprecated version that addresses apps via `name` field)\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Functional Use Cases\n\n### Open an Application\n\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Requesting Functionality From Another App\n\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3 and is implemented via the raising of [intents](../intents/spec), which represent a desired action, to be performed with a [context](../context/spec) supplied as input.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).  Currently, this is the primary focus in FDC3.\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client. Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n### Send/broadcast Context\n\nOn the financial desktop, applications often want to broadcast [context](../context/spec) to any number of applications.  Context sharing needs to support different groupings of applications, which is supported via the concept of 'channels', over which context is broadcast and received by other applications listening to the channel.  \n\nIn some cases, an application may want to communicate with a single application or service and to prevent other applications from participating in the communication. For single transactions, this can instead be implemented via a raised intent, which will be delivered to a single application that can, optionally, respond with data. Alternatively, it may instead respond with a [`Channel`](ref/Channel) or [`PrivateChannel`](ref/PrivateChannel) over which a stream of responses or a dialog can be supported.\n\n### Retrieve Metadata about the Desktop Agent implementation\n\nAn application may wish to retrieve information about the version of the FDC3 Standard supported by a Desktop Agent implementation and the name of the implementation provider.\n\nSince version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.:\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent('ViewChart', context);\n}\n```\n\nThe [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n\n```\n\n### Reference apps or app instance(s) and retrieve their metadata\n\nTo construct workflows between applications, you need to be able to reference specific applications and instances of those applications.\n\nFrom version 2.0 of the FDC3 Standard, Desktop Agent functions that reference or return information about other applications do so via an [`AppIdentifier`](ref/Types#appidentifier) type. [`AppIdentifier`](ref/Types#appidentifier) references specific applications via an `appId` from an [App Directory](../app-directory/overview) record and instances of that application via an `instanceId` assigned by the Desktop Agent.\n\nAdditional metadata for an application can be retrieved via the [`fdc3.getAppMetadata(appIdentifier)`](ref/DesktopAgent#getappmetadata) function, which returns an [`AppMetadata`](ref/Metadata#appmetadata) object. The additional metadata may include a title, description, icons, etc., which may be used for display purposes.\n\nIdentifiers for instances of an application may be retrieved via the [`fdc3.findInstances(appIdentifier)`](ref/DesktopAgent#findinstances) function.\n\n## Raising Intents\n\nRaising an Intent is a method for an application to request functionality from another application and, if desired, defer the discovery and launching of the destination app to the Desktop Agent.\n\n### Intents and Context\n\nWhen raising an intent a specific context is provided as input. The type of the provided context may determine which applications can resolve the intent.\n\nA context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents.\n\nTo raise an intent without a context, use the [`fdc3.nothing`](../context/ref/Nothing) context type. This type exists so that applications can explicitly declare that they support raising an intent without a context (when registering an `IntentHandler` or in an App Directory).\n\nAs an alternative to raising a specific intent, you may also raise an unspecified intent with a known context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent and then to raise it with the specified context for resolution.\n\n### Intent Results\n\nAn optional [`IntentResult`](ref/Types#intentresult) may also be returned as output by an application handling an intent. Results may be a single `Context` object, a `Channel` that may be used to send a stream of responses, or `void` (no result). The [`PrivateChannel`](ref/PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via [raising an intent](ref/DesktopAgent#raiseintent).\n\nFor example, an application handling a `CreateOrder` intent might return a context representing the order and including an ID, allowing the application that raised the intent to make further calls using that ID.\n\nAn optional result type is also supported when programmatically resolving an intent via [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentByContext`](ref/DesktopAgent#findintentsbycontext).\n\n### Resolvers\n\nSuccessful delivery of an intent depends first upon the Desktop Agent's ability to \"resolve the intent\" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentByContext`](ref/DesktopAgent#findintentsbycontext) and then raise the intent with a specific target application, e.g.:\n\n```js\n// Find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Find apps to resolve an intent and return a specified context type\nconst appIntent = await fdc3.findIntent(\"ViewContact\", context, \"fdc3.contact\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  const result = await resolution.getResult();\n  console.log(`${resolution.source} returned ${JSON.stringify(result)}`);\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n\n//Find apps to resolve an intent and return a channel\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", context, \"channel\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  const result = await resolution.getResult();\n  if (result && result.addContextListener) {\n    result.addContextListener(null, (context) => { \n      console.log(`received context: ${JSON.stringify(context)}`); \n    });\n  } else {\n    console.log(`${resolution.source} didn't return a channel! Result: ${JSON.stringify(result)}`);\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n\n//Find apps that can perform any intent with the specified context\nconst appIntents = await fdc3.findIntentByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]);\n```\n\nResult context types requested are represented by their type name. A channel may be requested by passing the string `\"channel\"` or a channel that returns a specific type via the syntax `\"channel<contextType>\"`, e.g. `\"channel<fdc3.instrument>\"`. Requesting intent resolution to an app returning a channel MUST include apps that are registered as returning a channel with a specific type.\n\n### Intent Resolution\n\nRaising an intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n#### Resolve\n\n- Intent was resolved unambiguously and the receiving app was launched successfully (if necessary).\n- Intent was ambiguous, a resolution was chosen by the end user, and the chosen application was launched successfully.\n\n#### Reject\n\n- No app matching the intent and context (if specified) was found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n#### Resolution Object\n\nIf the raising of the intent resolves (or rejects), a standard [`IntentResolution`](ref/Metadata#intentresolution) object will be passed into the resolver function with details of the application that resolved the intent and the means to access any results subsequently returned.\n\nFor example, to raise a specific intent:\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n}\ncatch (err){ ... }\n```\n\nor to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog:\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntentForContext(context);\n  if (resolution.data) {\n    const orderId = resolution.data.id;\n  }\n}\ncatch (err){ ... }\n```\n\nUse metadata about the resolving app instance to target a further intent\n\n```js\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err) { ... }\n```\n\nRaise an intent and retrieve either data or a channel from the IntentResolution:\n\n```js\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  /* Detect whether the result is Context or a Channel by checking for properties unique to Channels. */\n  if (result && result.broadcast) { \n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`);\n  }\n} catch(error) {\n  console.error(`${resolution.source} returned a data error: ${error}`);\n}\n```\n\n### Register an Intent Handler\n\nApplications need to let the system know the intents they can support.  Typically, this SHOULD be done via registration with an [App Directory](../app-directory/spec) by providing `interop.intents.listensFor` metadata. However, Desktop Agent implementations MAY support dynamic registration of an [`IntentHandler`](ref/Types#intenthandler) by an app at runtime (for example, when they add an `IntentListener` via the API) to allow for ad-hoc registration which may be helpful at development time.  Although dynamic registration is not part of this specification, a Desktop Agent agent MAY choose to support any number of registration paths.\n\nWhen an instance of an application is launched, it is expected to add an [`IntentHandler`](ref/Types#intenthandler) function to the Desktop Agent for each intent it has registered by calling the [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) function of the Desktop Agent. Doing so allows the Desktop Agent to pass incoming intents and contexts to that instance of the application. Hence, if the application instance was spawned in response to the raised intent, then the Desktop Agent must wait for the relevant intent listener to be added by that instance before it can deliver the intent and context to it. In order to facilitate accurate error responses, calls to `fdc3.raiseIntent` should not return an `IntentResolution` until the intent handler has been added and the intent delivered to the target app.\n\nIntent handlers SHOULD be registered via [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations. Individual Desktop Agent implementations MAY support longer timeouts or configuration to control or extend timeouts.\n\n### Originating App Metadata\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered intent handlers. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n\n### Compliance with Intent Standards\n\nIntents 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.\n\nIt is expected that App Directories SHOULD also curate listed apps and ensure that they are complying with declared intents.\n\n## Context Channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\n### Types of Channel\n\nThere are three types of channels, which have different visibility and discoverability semantics:\n\n1. ***User channels***, which:\n\n    - facilitate the creation of user-controlled context links between applications (often via the selection of a color channel),\n    - are created and named by the desktop agent,\n    - are discoverable (via the [`getUserChannels()`](ref/DesktopAgent#getuserchannels) API call),\n    - can be 'joined' (via the [`joinUserChannel()`](ref/DesktopAgent#joinuserchannel) API call).\n\n    :::note\n\n    Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels).\n\n    :::\n\n    :::note\n\n    Earlier versions of FDC3 included the concept of a 'global' system channel\n    which was deprecated in FDC3 1.2 and removed in FDC3 2.0.\n\n    :::\n\n2. ***App channels***, which:\n\n    - facilitate developer controlled messaging between applications,\n    - are created and named by applications (via the [`getOrCreateChannel()`](ref/DesktopAgent#getorcreatechannel) API call),\n    - are not discoverable,\n    - are interacted with via the [Channel API](ref/Channel) (accessed via the desktop agent [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API call)\n\n3. ***Private*** channels, which:\n\n    - facilitate private communication between two parties,\n    - have an auto-generated identity and can only be retrieved via a raised intent.\n\nChannels are interacted with via `broadcast` and `addContextListener` functions, allowing an application to send and receive Context objects via the channel. For User channels, these functions are provided on the Desktop Agent, e.g. [`fdc3.broadcast(context)`](ref/DesktopAgent#broadcast), and apply to channels joined via [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel). For App channels, a channel object must be retrieved, via [`fdc3.getOrCreateChannel(channelName)`](ref/DesktopAgent#getorcreatechannel), which provides the functions, i.e. [`myChannel.broadcast(context)`](ref/Channel#broadcast) and [`myChannel.addContextListener(context)`](ref/Channel#addcontextlistener). For `PrivateChannels`, a channel object must also be retrieved, but via an intent raised with [`fdc3.raiseIntent(intent, context)`](ref/DesktopAgent#raiseintent) and returned as an [`IntentResult`](ref/Types#intentresult).\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are also listening on the channel.\n\n### Joining User Channels\n\nApps can join *User channels*.  An app can only be joined to one User channel at a time.  \n\nWhen an app is joined to a User channel, calls to [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be routed to that channel and listeners added through [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will receive context broadcasts from other apps also joined to that channel. If an app is not joined to a User channel [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be a no-op and handler functions added with  [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will not receive any broadcasts. However, apps can still choose to listen and broadcast to specific channels (both User and App channels) via the methods on the [`Channel`](ref/Channel) class.\n\nWhen an app joins a User channel, or adds a context listener when already joined to a channel, it will automatically receive the current context for that channel.\n\nIt is possible that a call to join a User channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinChannel()`](ref/DesktopAgent#joinuserchannel), [`fdc3.getCurrentChannel()`](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).\n\nThere SHOULD always be a clear UX indicator of what channel an app is joined to.\n\n#### Examples\n\nTo find a User channel, one calls:\n\n```js\n// returns an array of channels\nconst allChannels = await fdc3.getUserChannels();\nconst redChannel = allChannels.find(c => c.id === 'red');\n```\n\nTo join a User channel, one calls:\n\n```js\nfdc3.joinUserChannel(redChannel.id);\n```\n\nCalling `fdc3.broadcast` will now route context to the joined channel.\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n\n  > Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels). The `joinChannel` function was also renamed to `joinUserChannel` to clarify that it is only intended to be used to join 'user', rather than 'app', channels.\n\n### Recommended User Channel Set\n\nDesktop Agent implementations SHOULD use the following set of channels, to enable a consistent user experience across different implementations. Desktop Agent implementation MAY support configuration of the user channels.\n\n:::note\nFuture versions of the FDC3 Standard may support connections between desktop agents, where differing user channel sets may cause user experience issues.\n:::\n\n```javascript\nconst recommendedChannels = [\n  {\n    id: 'fdc3.channel.1',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 1',\n      color: 'red',\n      glyph: '1',\n    },\n  },\n  {\n    id: 'fdc3.channel.2',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 2',\n      color: 'orange',\n      glyph: '2',\n    },\n  },\n  {\n    id: 'fdc3.channel.3',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 3',\n      color: 'yellow',\n      glyph: '3',\n    },\n  },\n  {\n    id: 'fdc3.channel.4',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 4',\n      color: 'green',\n      glyph: '4',\n    },\n  },\n  {\n    id: 'fdc3.channel.5',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 5',\n      color: 'cyan',\n      glyph: '5',\n    },\n  },\n  {\n    id: 'fdc3.channel.6',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 6',\n      color: 'blue',\n      glyph: '6',\n    },\n  },\n  {\n    id: 'fdc3.channel.7',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 7',\n      color: 'magenta',\n      glyph: '7',\n    },\n  },\n  {\n    id: 'fdc3.channel.8',\n    type: 'user',\n    displayMetadata: {\n      name: 'Channel 8',\n      color: 'purple',\n      glyph: '8',\n    },\n  },\n];\n```\n\n### Direct Listening and Broadcast on Channels\n\nWhile joining User channels (using [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel)) automates a lot of the channel behavior for an app, it has the limitation that an app can only be 'joined' to one channel at a time.  However, an app may instead retrieve an App [`Channel`](ref/Channel) Object via the [`fdc3.getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API, create a [`PrivateChannel`](ref/PrivateChannel) via the [`fdc3.createPrivateChannel`](ref/DesktopAgent#createprivatechannel) API, or by raising an intent that returns a channel created by another app. The `Channel` object may then be used to listen to and broadcast on that channel directly using the [`Channel.addContextListener`](ref/Channel#addcontextlistener) and the [`Channel.broadcast`](ref/Channel#broadcast) APIs. FDC3 imposes no restriction on adding context listeners or broadcasting to multiple channels.\n\n### App Channels\n\nApp Channels are topics dynamically created by applications connected via FDC3. For example, an app may create a named App Channel to broadcast data or status that is specific to that app to other apps that know to connect to the channel with that name.\n\nTo get (or create) a [`Channel`](ref/Channel) reference, then interact with it:\n\n```js\nconst appChannel = await fdc3.getOrCreateChannel('my_custom_channel');\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nawait appChannel.addContextListener(null, context => {...});\n// broadcast to the channel\nawait appChannel.broadcast(context);\n```\n\nAn app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to.\n\n```js\n// check for current fdc3 channel\nlet joinedChannel = await fdc3.getCurrentChannel()\n//current channel is null, as the app is not currently joined to a channel\n\n//add a context listener for channels we join\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n//retrieve an App channel and add a listener that is specific to that channel\nconst myChannel = await fdc3.getOrCreateChannel('my_custom_channel');\nconst myChannelListener = await myChannel.addContextListener(null, context => { ... });\n\nfdc3.joinChannel('blue')\njoinedChannel = await fdc3.getCurrentChannel()\n//current channel is now the 'blue' channel\n```\n\nif another application broadcasts to \"my_custom_channel\" (by retrieving it and broadcasting to it via `myChannel.broadcast()`) then the broadcast will be received by the specific listener (`myChannelListener`) but NOT by the listener for joined channels (`listener`).\n\n### Private Channels\n\nA [`PrivateChannel`](ref/PrivateChannel) is created to support the return of a stream of responses from a raised intent, or private dialog between two applications.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\nThe `PrivateChannel` type also supports synchronization of data transmitted over returned channels. They do so by extending the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\n### Broadcasting and listening for multiple context types\n\nThe [Context specification](../context/spec#assumptions) recommends that complex context objects are defined using simpler context types for particular fields. For example, a `Position` is composed of an `Instrument` and a holding amount. This leads to situations where an application may be able to receive or respond to context objects that are embedded in a more complex type, but not the more complex type itself. For example, a pricing chart might respond to an `Instrument` but doesn't know how to handle a `Position`.\n\nTo facilitate context linking in such situations it is recommended that applications `broadcast` each context type that other apps (listening on a User Channel or App Channel) may wish to process, starting with the simpler types, followed by the complex type. Doing so allows applications to filter the context types they receive by adding listeners for specific context types - but requires that the application broadcasting context make multiple broadcast calls in quick succession when sharing its context.\n\n### Originating App Metadata\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered context handlers on all types of channel. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/app-directory/overview.md",
    "content": "---\nid: overview\nsidebar_label: Overview\ntitle: App Directory Overview (2.1)\n---\n\nAn application directory (appD) is a structured repository of information about apps that can be used in an FDC3-enabled desktop. In other words, it’s a convenient way of storing and managing metadata about apps in your ecosystem.\n\nThe application metadata stored in appD records may include: the app name, type, details about how to run the application, its icons, publisher, support contact details and so on. It may also include links to or embed manifest formats defined elsewhere, such as proprietary manifests for launching the app in a container product or a Web Application Manifest (as [defined by the W3C](https://www.w3.org/TR/appmanifest/)).\n\nAll this information is readily available in one place and can be used both to populate a launcher or app catalog UI for your users, and by the Desktop Agent managing the apps on your desktop. In fact, if your desktop platform supports the FDC3 standard, appD is the primary way that the FDC3 Desktop Agent implementation should receive the details about apps available to run on your desktop. Conversely, if an app is not listed in appD, the Desktop Agent can’t ensure its participation in context sharing or use it to resolve intents.\n\n## Advantages\n\nUsing appD offers many advantages both for financial institutions running an FDC3-enabled desktop container and for vendors that provide FDC3-compliant apps:\n\n### For the user\n\n#### Easier to Find App Info\n\nYour appD is the one place to collect all the information about apps. The more apps you have, the more you’ll appreciate the convenience of not having to chase down details about each. This is particularly important for large institutions with multiple desks.\n\n#### Human Readable\n\nAppD has two types of users. One is the Desktop Agent, but the other is humans administrating and using the smart desktop at your organization. Hence, an appD contains information about apps in both machine- and human-readable forms. For example, it includes both unique identifiers for apps that are used to refer to them in code and human-friendly app names, icons, descriptions and tooltips necessary to populate a launcher menu or app catalog user interface for your users.\n\n#### Apps are Discoverable\n\nFor large institutions, it can be difficult to keep track of all the apps (developed both in-house and by vendors), since a typical desktop could have many. Users can search appD to discover the apps they need. An app might already reside on their system or be available to them over the internet, but if they don’t have a way to search the apps available to them, they won’t be able to find it. An appD provides a way for users to discover the apps they need.\n\nAn appD makes it possible to discover info about apps that reside on various domains, not just the one domain the appD itself is hosted on. In addition, you can find details about how to launch the apps in multiple, diverse environments. This is a different use-case to, for example, the [W3C's Web App Manifest](https://www.w3.org/TR/appmanifest/), which is hosted on the same domain as the app, is limited to web apps, and is generally used to 'install' an app that the user has already accessed.\n\n#### Updating Apps\n\nTypically, software evolves over time. The app versions you are running today will not be the same ones you need tomorrow. Therefore, you will need to upgrade apps periodically. Very few people look forward to upgrading, but appD and web deployment can make it easier for you. To roll out a new version of your app, either update the existing entry for it in appD or add a new entry for that version (allowing users to select the version they will use).\n\n#### Agent-agnostic\n\nAs a part of the FDC3 standard, appD isn't tied to any specific vendor. This is important, as it allows you more flexibility in that you are not tied to any specific container or Desktop Agent implementation. If at any point you want to switch to a different Desktop Agent, the process won’t be prohibitively difficult. The existing appD will work without any additional effort from you, as long as your new Desktop Agent is also FDC3-compliant. This is in contrast with proprietary solutions, where you would have to produce a new configuration and integration for every application.\n\nAppD reduces fragmentation in the market and allows end-users more flexibility in what applications can be included in their desktop.\n\n#### Intent Resolution\n\nAppD provides information to the Desktop Agent on which applications can handle particular [intents](../intents/spec) and the context types they support as input to them. This allows the Desktop Agent to implement an [intent resolver](../api/spec#resolvers) that can launch applications and pass the intent and context to them to operate on, supporting workflows between applications that didn't require prior bilateral agreements between the application providers.\n\n### For an Application Provider\n\nUntil now, we've looked at appD from the perspective of a desktop owner and user. But appD also offers advantages to vendors who develop apps for the financial services desktop.\n\n#### Apps Work Well Together Out-of-the-box\n\nWhen your customers add your FDC3-compliant app to their desktop via an appD record accurately describing it, you can be sure that your app will interoperate with other apps that follow the FDC3 standard. You don’t have to do anything special, or arrange a bilateral agreement with anyone else. The benefit of the open standard is that any app that follows it will work well with any other compliant app.\n\n#### Easy Updates\n\nAs a vendor, you prefer for all your customers to run your latest software. However, many customers will postpone upgrades, sometimes for a long time, because upgrading can be a pain. An advantage of a vendor-hosted appD is that the configuration of an app can be updated at any time and, if your customers need to choose when to upgrade, multiple versions of it can be made available, each with their own configuration. By making it easier for customers to update, you can drive better adoption.\n\n### For the Industry\n\nBy hosting our own appD we can easily combine applications from various providers into one cohesive directory. Alternatively, we can connect to directories from multiple providers (in standardized format) and provide a single view over them. This reduces fragmentation in the market, allows end-users more flexibility in what apps to include in their smart desktop, and obviates the need for vendors to provide application details in diverse formats or for their customers to work out these details for themselves.\n\n## Relationship to Other Standards\n\nThe App Directory's application record is similar to application manifests defined in other standards, in particular the W3C's [Web Application Manifest](https://www.w3.org/TR/appmanifest/). However, the App Directory, and by extension the application record, serve a different set of use-cases specific to application interoperability on financial services desktops, which other standards do not fully address.\n\nWherever possible, FDC3 seeks to draw inspiration from, align itself with and reference other standards - ensuring that conventions and best practices developed by those standards are reused, along with the standard itself (e.g. data formats in ISO standard formats, external links to technology-specific manifest file formats etc.). For a list of standards that FDC3 references, see the [References](../references) page.\n\n## Use Cases\n\nAn application directory provides information about an application's identifiers, publisher details, intents that it supports, and metadata necessary to launch and integrate the application in a Desktop Agent.\n\nThe following provides a summary of use cases.\n\n### Launcher\n\nA Desktop Agent will usually include a user interface allowing the user to select from a set of launchable applications and then allow them to manually launch one. It is also responsible for launching applications necessary to resolve a raised intent. However, it must first retrieve the necessary metadata about the available applications. An app directory provides an endpoint to retrieve a list of the available applications along with their metadata, which may include or link to additional information necessary to launch the application in a specific Desktop Agent.\n\nA launcher will usually be configured with the locations of one or more AppD servers (which is necessary to implement intent resolution), however, as described in the [Service Discovery](#service-discovery) section, a fully qualified application identifier (e.g. `app1@host.appd.com`) may also be used to both locate the appD service and to retrieve the specific application data.\n\n![img](/assets/appd_launcher_embedded.png)\n\n### Aggregated View\n\nThere could be many different appD service instances in the world providing application data zoned to the provider or enterprise deployment. The appD specification allows for unique instances of the service with no requirement to aggregate data or define a structured hierarchy. With this said, a launcher might want to construct an aggregated view of applications from one or more appD instances. In this case, the launcher would be required to retrieve multiple application definitions from one or more appD instances providing a consolidated view of all applications required.\n\nToday, there is no intention to create a single registry of known AppD instances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location.\n\n![img](/assets/appd_launcher_aggregated.png)\n\n### Authentication and Entitlements\n\nThe AppD API specification defines the optional use of an access token to identify the requesting user/launcher and implement authorizations which may affect appD API responses. For example, different subsets of the full list of applications may be returned for different users depending on their role in an organization.\n\nThe specification does not define or make mandatory any authorizations or roles that a provider or enterprise can define.\n\n## Application Identifiers\n\nApplication Records served by an app directory are each labelled with an identifier, `appId`, which should be unique within the app directory instance and may be used to refer to or retrieve the application's record via the [app directory API](spec). This identifier may be made globally unique through a nested namespace approach and email address construction (`appId@fqdn`) where `@` followed by the app directory instance's host name is appended to it. The resulting globally unique identifier is known as a 'fully qualified application identifier'.\n\nFully qualified appIds may be used to locate the appD instance hosting the application's record. See the [Service Discovery](#service-discovery) section for details.\n\n### Shrinking the URI\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID `app1@appd.foo.com` is represented as `app1` within the application directory.  As a result a launcher can use a shortened URI construct `https://appd.foo.com/api/appd/v2/apps/app1` to resolve the application data vs `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`.\n\n## Service Discovery\n\nIn order to support the discovery of applications that can be used with a Desktop Agent, it is necessary to access data stored in one or more app directory instances.\n\n![img](/assets/appd_service_distribution.png)\n\nHowever, in order to do so, you must first discover the location of an app directory service, which you may then use to generate URIs  (e.g. `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`) to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required.\n\nThree methods for discovering app directory services are defined in this Standard:\n\n  1. **Static configuration:** Statically defined URI records for use within client applications (typically a Desktop Agent implementation) directly.\n  2. **Fully-qualified appID namespace syntax host resolution:** Discovery of the appD location using a fully qualified application ID (appId) domain name.\n  3. **DNS lookup by domain name:** Discovery of the appD location using a domain name to lookup DNS SRV records identifying the host server location and TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782))\n\nApp directory service host discovery implementations SHOULD support each of these methods and MUST support at least static configuration.\n\n### Static configuration\n\nAs the name implies, a static configuration for an appD service location is defined within a Desktop Agent or launcher application. This is the simplest and most common approach to app directory and application data discovery.\n\n![img](/assets/appd_static_config.png)\n\n### Fully-qualified appID namespace syntax host resolution\n\nAn app directory URI can be constructed using a [fully qualified application ID](overview#application-identifiers) (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application id `app1` with a fully qualified identifier of `app1@appd.foo.com` an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" MUST resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by:\n\n1. URI protocol is defaulted to `https`, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default `https/443`, but can be overridden by the launcher\n4. URI url is by default `/api/appd/(version)/apps` . Calls that are made without version MUST automatically default to latest, i.e. `/api/appd/apps/app1` should return the same result as `/api/appd/v2/apps/app1\".\n\nThe resulting URI to retrieve application data for `app1` would be [https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com)\n\n### DNS/SRV Records\n\nAnother approach to support app directory service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an appD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well-known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```text\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *`service`*: the symbolic name of the desired service.  For AppD service, this must be identified as **`_appd`**\n- *`proto`*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *`name`*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *`TTL`*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *`class`*: standard DNS class field (this is always *IN*).\n- *`priority`*: the priority of the target host, lower value means more preferred.\n- *`weight`*: A relative weight for records with the same priority, higher value means more preferred.\n- *`port`*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *`target`*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record MUST use the following definitions:\n\n- `service` = **`_appd`**\n- `proto` = **`_tcp`**\n- `name` = must map to the domain of the application identifier . Example:  the `name` for application identifier `app1@appd.foo.com` would be `appd.foo.com`\n\n*AppD service through DNS / SRV records:*\n\n![img](/assets/appd_dns.png)\n\n#### Known domains\n\nAlthough SRV records provide the means of resolving the location of an app directory service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/app-directory/spec.md",
    "content": "---\nid: spec\nsidebar_label: API\ntitle: App Directory API (2.1)\n---\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/2.1/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/2.1/appd.schema.json\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v2/apps`         | GET    | Retrieve all application definitions\n `/v2/apps/{appId}` | GET    | Retrieve an application definition\n `/v1/apps`         | POST   | (deprecated v1 API version) Create a new application definition\n `/v1/apps/{appId}` | GET    | (deprecated v1 API version) Retrieve an application definition\n `/v1/apps/search`  | GET    | (deprecated v1 API version) Retrieve a list of applications\n\nApp Directory implementations MAY extend the list of endpoints to provide other necessary functionality. However, FDC3 Desktop Agent implementations that connect to app directories MUST support connection to app directories that only provide the minimum endpoints listed here.\n\n## App Directory Standard Compliance\n\nAn FDC3 Standard compliant App Directory implementation **MUST**:\n\n- Implement the specified `/v2` endpoints for retrieving app definitions as defined in the [app directory OpenAPI specification](pathname:///schemas/2.1/app-directory.html#tag/Application):\n  - `/v2/apps` (GET)\n  - `/v2/apps/{appId}` (GET)\n- Ensure that `appId` field values assigned to applications are unique within the directory.\n- Ensure that app directory records served meet the minimum requirements specified in the [app directory OpenAPI specification](pathname:///schemas/2.1/app-directory.html#tag/Application)\n- Support retrieval of app directory records via either the raw `appId` (e.g. `myAppId`) or fully-qualified appId (e.g. `myAppId@host.domain.com`) as defined in the [app directory overview](overview#shrinking-the-uri).\n\nAn FDC3 Standard compliant App Directory implementation **SHOULD**:\n\n- Support authentication (where required) via the HTTP Authorization header and Bearer authentication schema (implemented via JWT tokens)\n- Select any `categories` field values from the recommended list.\n- Encourage the use of the `lang` and `localizedVersions` fields in appD records to support localization and accessibility.\n\nAn FDC3 Standard compliant App Directory implementation **MAY**:\n\n- Support filtering of application records returned by user entitlement, where authentication is enabled.\n- Implement the deprecated `/v1` endpoints provided for backwards compatibility with prior version of the standard:\n  - `/v1/apps` (POST)\n  - `/v1/apps/{appId}` (GET)\n  - `/v1/apps/search` (GET)\n- Extend the implementation with additional endpoints.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Action.md",
    "content": "---\nid: Action\nsidebar_label: Action\ntitle: Action\nhide_title: true\n---\n# `Action`\n\nA representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\n\nThe action may be completed by calling `fdc3.raiseIntent()` with the specified Intent and Context, or, if only a context is specified, by calling `fdc3.raiseIntentForContext()` (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\n\nAccepts an optional `app` parameter in order to specify a specific app.\n\n## Type\n\n`fdc3.action`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/action.schema.json](pathname:///schemas/2.1/context/action.schema.json)\n\n## Details\n\n| Property          | Type                                      | Required | Example Value           |\n|-------------------|-------------------------------------------|----------|-------------------------|\n| `type`            | string                                    | Yes      | `'fdc3.action'`         |\n| `title`           | string                                    | Yes      | `'Click to view Chart'` |\n| `intent`          | string                                    | No       | `'ViewChart'`           |\n| `context`         | string                                    | Yes      | See Below               |\n| `app`             | object                                    | No       | `'myApp'`               |\n| `app.appId`       | string                                    | Yes      | `'app1'`                |\n| `app.instanceId`  | string                                    | No       | `'instance1'`           |\n\n## Example\n\n```js\nconst action = {\n    type: 'fdc3.action',\n    title: 'Click to view Chart',\n    intent: 'ViewChart',\n    context {\n        type: 'fdc3.chart',\n        instruments: [\n            {\n                type: 'fdc3.instrument',\n                id: {\n                    ticker: 'EURUSD'\n                }\n            }\n        ],\n        range: {\n            type: 'fdc3.dateRange',\n            starttime: '2020-09-01T08:00:00.000Z',\n            endtime: '2020-10-31T08:00:00.000Z'\n        },\n        style: 'candle'\n    },\n    app {\n        appId: 'MyChartViewingApp',\n        instanceId: 'instance1'\n    }\n}\n```\n\n## See Also\n\nOther Types\n\n- [Message](Message)\n\nIntents\n\n- [StartChat](../../intents/ref/StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Chart.md",
    "content": "---\nid: Chart\nsidebar_label: Chart\ntitle: Chart\nhide_title: true\n---\n# `Chart`\n\nA context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\n\n- A list of instruments for comparison\n- The time period to plot the chart over\n- The style of chart (line, bar, mountain, candle etc.)\n- Other settings such as indicators to calculate, or data representing drawings and annotations\n\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\n\n## Type\n\n`fdc3.chart`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/chart.schema.json](pathname:///schemas/2.1/context/chart.schema.json)\n\n## Details\n\n| Property         | Type            | Required | Example Value        |\n|------------------|-----------------|----------|----------------------|\n| `type`           | string          | Yes      | `'fdc3.chart'`     |\n| `instruments`    | Instrument[]  | Yes      | <pre>[<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.instrument\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"ticker\": \"AAPL\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\},<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.instrument\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"ticker\": \"MSFT\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\}<br/>]</pre> |\n| `range` | TimeRange  | No       | <pre>\\{<br/>&emsp;&emsp;\"type\": \"fdc3.timeRange\",<br/>&emsp;&emsp;\"startTime\": \"2022-03-30T15:44:44+00:00\",<br/>&emsp;&emsp;\"endTime\": \"2022-04-30T23:59:59+00:00\"<br/>\\}</pre>            |\n| `style`    | string  | No       | one of: `'line'`, `'bar'`, `'stacked-bar'`, `'mountain'`, `'candle'`, `'pie'`, `'scatter'`, `'histogram'`, `'heatmap'`, `'custom'`      |\n| `otherConfig`* | array  | No |  `[ \\{/* additional config context objects */\\} ]`  |\n\n::: info\n\nIt is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\n\n:::\n\n## Example\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: [\n        {\n            type: \"somevendor.someproduct.indicator\",\n            name: \"stddev\",\n            parameters: {\n                period: 10,\n                matype: \"exponential\"\n            }\n        },\n        {\n            type: \"someothervendor.someotherproduct.formula\",\n            formula: \"standard-deviation\",\n            fields: {\n                lookback: 10,\n                type: \"ema\"\n            }\n        }\n    ]\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n- [TimeRange](TimeRange)\n\nIntents\n\n- [ViewChart](../../intents/ref/ViewChart)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/ChatInitSettings.md",
    "content": "---\nid: ChatInitSettings\nsidebar_label: ChatInitSettings\ntitle: ChatInitSettings\nhide_title: true\n---\n\n# `ChatInitSettings`\n\nA collection of settings to start a new chat conversation\n\n## Type\n\n`fdc3.chat.initSettings`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/chatInitSettings.schema.json](pathname:///schemas/2.1/context/chatInitSettings.schema.json)\n\n## Details\n\n| Property                       | Type        | Required | Example Value                                                        |\n| ------------------------------ | ----------- | -------- | -------------------------------------------------------------------- |\n| `type`                         | string      | Yes      | `'fdc3.chat.initSettings'`                                           |\n| `chatName`                     | string      | No       | `'Instrument XYZ'`                                                   |\n| `members`                      | ContactList | No       | ContactList - cf. below                                              |\n| `message`                      | Message     | No       | Message - cf. below                                                  |\n| `options.groupRecipients`      | boolean     | No       | `true`: if false a separate chat will be created for each member     |\n| `options.isPublic`             | boolean     | No       | `true`: the room will be visible to everyone in the chat application |\n| `options.allowHistoryBrowsing` | boolean     | No       | `true`: members will be allowed to browse past messages              |\n| `options.allowMessageCopy`     | boolean     | No       | `true`: members will be allowed to copy/paste messages               |\n| `options.allowAddUser`         | boolean     | No       | `true`: members will be allowed to add other members to the chat     |\n\nIf _members_ or _chatName_ are not provided, the application executing this\nintent is expected to provide a means to enter such information.\n\n## Example\n\n```js\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Chat ABCD',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane@mail.com'\n            }\n        },{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true\n    },\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nconst res = fdc3.raiseIntent('StartChat', initSettings);\n\n// Return a reference to the room\nconst chatRoom = await res.getResult();\n```\n\n## See Also\n\nOther Types\n\n- [ChatRoom](ChatRoom)\n- [ContactList](ContactList)\n- [Message](Message)\n\nIntents\n\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [SendChatMessage](../../intents/ref/StartChat)\n- [ViewContact](../../intents/ref/ViewContact)\n\nFINOS Financial Objects\n\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/ChatMessage.md",
    "content": "---\nid: ChatMessage\nsidebar_label: ChatMessage\ntitle: ChatMessage\nhide_title: true\n---\n# `ChatMessage`\n\nA context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\n\n## Type\n\n`fdc3.chat.message`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/chatMessage.schema.json](pathname:///schemas/2.1/context/chatMessage.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.chat.message'`  |\n| `chatRoom`      | ChatRoom  | Yes       | `{ type: 'fdc3.chat.room', providerName: 'Symphony', id:{ streamId: 'j75xqXy25NBOdacUI3FNBH'} }`      |\n| `message`  | [Message](pathname:///schemas/2.1/message.schema.json)  | Yes       | `'A message to send'` |\n\n## Example\n\n```js\nconst chatMessage = {\n    type: \"fdc3.chat.message\",\n    chatRoom: {\n        type: 'fdc3.chat.room',\n        providerName: \"Symphony\",\n        id: {\n            streamId: \"j75xqXy25NBOdacUI3FNBH\"\n        }\n    },\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n```\n\n## See Also\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [SendChatMessage](../../intents/ref/SendChatMessage)\n\nFINOS Financial Objects\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/ChatRoom.md",
    "content": "---\nid: ChatRoom\nsidebar_label: ChatRoom\ntitle: ChatRoom\nhide_title: true\n---\n# `ChatRoom`\n\nReference to the chat room, which could be used later to send a message to the room.\n\n## Type\n\n`fdc3.chat.room`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/chatRoom.schema.json](pathname:///schemas/2.1/context/chatRoom.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.chat.room'`  |\n| `providerName`      | string  | Yes       | `'Symphony'`      |\n| `id`  | object  | Yes       | `{ streamId: 'j75xqXy25NBOdacUI3FNBH', anyOtherKey: 'abcdef'}` |\n| `url` | string  | No       | `'http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA'`      |\n| `name` | string  | No       | `'My new room'`      |\n\nThe `url` is a universal url to access to the room. It could be opened from a browser, a mobile app, etc...\n\n## Example\n\n```js\nconst chatRoom = {\n  type: \"fdc3.chat.room\",\n  providerName: \"Symphony\",\n  id: {\n      streamId: \"j75xqXy25NBOdacUI3FNBH\"\n  }\n  url: \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n  name: 'My new room'\n};\n\n//Chat rooms are returned by the StartChat intent as a result\nconst intentResolution = await fdc3.raiseIntent(\"StartChat\", context);\n\ntry {\n    const chatRooms = await intentResolution.getResult():\n} catch (error) {\n   //chat room were not created...\n}\n```\n\n## See Also\n\nOther Types\n* [ChatInitSettings](ChatInitSettings)\n\nIntents\n- [StartChat](../../intents/ref/StartChat)\n- [SendChatMessage](../../intents/ref/SendChatMessage)\n\nFINOS Financial Objects\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/ChatSearchCriteria.md",
    "content": "---\nid: ChatSearchCriteria\nsidebar_label: ChatSearchCriteria\ntitle: ChatSearchCriteria\nhide_title: true\n---\n# `ChatSearchCriteria`\n\nA context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\n\n## Type\n\n`fdc3.chat.searchCriteria`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/chatSearchCriteria.schema.json](pathname:///schemas/2.1/context/chatSearchCriteria.schema.json)\n\n## Details\n\n| Property         | Type            | Required | Example Value        |\n|------------------|-----------------|----------|----------------------|\n| `type`           | string          | Yes      | `'fdc3.chat.searchCriteria'`     |\n| `criteria` | (Instrument &#124;<br/>Contact &#124;<br/>Organization &#124;<br/>string)[] | Yes | <pre>[<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.instrument\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"ticker\": \"AAPL\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\},<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.contact\",<br/>&emsp;&emsp;&emsp;&emsp;\"name\":\"Jane Doe\",<br/>&emsp;&emsp;&emsp;&emsp;\"id\": \\{<br/>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\"email\": \"jane.doe@mail.com\"<br/>&emsp;&emsp;&emsp;&emsp;\\}<br/>&emsp;&emsp;\\},<br/>&emsp;&emsp;\\{<br/>&emsp;&emsp;&emsp;&emsp;\"type\": \"fdc3.organization\",<br/>&emsp;&emsp;&emsp;&emsp;\"name\":\"Symphony\",<br/>&emsp;&emsp;\\},<br/>&emsp;&emsp;\"#OrderID45788422\",<br/>]</pre> |\n\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\n\nEmpty search criteria can be supported to allow resetting of filters.\n\n## Example\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        },\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\n## See Also\n\nIntents\n\n* [ViewMessages](../../intents/ref/ViewMessages)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Contact.md",
    "content": "---\nid: Contact\nsidebar_label: Contact\ntitle: Contact\nhide_title: true\n---\n# `Contact`\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Type\n\n`fdc3.contact`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/contact.schema.json](pathname:///schemas/2.1/context/contact.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value     |\n|-------------|---------|----------|-------------------|\n| `type`      | string  | Yes      | `'fdc3.contact'`  |\n| `name`      | string  | No       | `'Jane Doe'`      |\n| `id.email`  | string  | No       | `'jane@mail.com'` |\n| `id.FDS_ID` | string  | No       | `'ABC123-E'`      |\n\n## Example\n\n```js\nconst contact = {\n    type: \"fdc3.contact\",\n    name: \"Jane Doe\",\n    id: {\n        email: \"jane.doe@mail.com\"\n    }\n}\n\n\nfdc3.broadcast(contact)\n```\n\n## See Also\n\nOther Types\n\n- [ContactList](ContactList)\n\nIntents\n\n- [CreateInteraction](../../intents/ref/CreateInteraction)\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n\n- [Contact](https://fo.finos.org/docs/objects/contact)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/ContactList.md",
    "content": "---\nid: ContactList\nsidebar_label: ContactList\ntitle: ContactList\nhide_title: true\n---\n# `ContactList`\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nNotes:\n\n- The contact list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.contactList`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/contactList.schema.json](pathname:///schemas/2.1/context/contactList.schema.json)\n\n## Details\n\n| Property    | Type      | Required | Example Value          |\n|-------------|-----------|----------|------------------------|\n| `type`      | string    | Yes      | `'fdc3.contactList'`   |\n| `id`        | object    | No       | `{ customId: '5576' }` |\n| `name`      | string    | No       | `'My address book'`    |\n| `contacts`  | Contact[] | Yes      | `[contact1, contact2]` |\n\n## Example\n\n```js\nconst contacts = {\n    type: \"fdc3.contactList\",\n    contacts: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.contact\",\n            name: \"John Doe\",\n            id: {\n                email: \"john.doe@mail.com\"\n            }\n        },\n    ]\n}\nfdc3.raiseIntent(\"StartChat\", contacts)\n```\n\n## See Also\n\nOther Types\n\n- [Contact](Contact)\n\nIntents\n\n- [CreateInteraction](../../intents/ref/CreateInteraction)\n- [StartChat](../../intents/ref/StartChat)\n- [StartCall](../../intents/ref/StartCall)\n\nFINOS Financial Objects\n\n- [ContactList](https://fo.finos.org/docs/objects/contactlist)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Context.md",
    "content": "---\nid: Context\nsidebar_label: Context\ntitle: Context\nhide_title: true\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not\nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/context.schema.json](pathname:///schemas/2.1/context/context.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema.\nThe FDC3 [API](../../api/spec) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/spec) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`.\nFor non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications\nidentify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\n## See Also\n\nFDC3 Specifications\n\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Country.md",
    "content": "---\nid: Country\nsidebar_label: Country\ntitle: Country\nhide_title: true\n---\n# `Country`\n\nA country entity.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement\nis for at least one standardized identifier to be provided\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n## Type\n\n`fdc3.country`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/country.schema.json](pathname:///schemas/2.1/context/country.schema.json)\n\n\n## Details\n\n| Property                 | Type    | Required | Example Value        |\n|--------------------------|---------|----------|----------------------|\n| `type`                   | string  | Yes      | `'fdc3.country'`     |\n| `name`                   | string  | No       | `'Sweden'`           |\n| `id.COUNTRY_ISOALPHA2`   | string  | Yes      | `'SE'`               |\n| `id.COUNTRY_ISOALPHA3`   | string  | No       | `'SWE'`              |\n| `id.ISOALPHA2` *         | string  | No       | `'SE'`               |\n| `id.ISOALPHA3` *         | string  | No       | `'SWE'`              |\n\n\\* Field names deprecated in FDC3 2.0 in favour of the versions prefixed with `COUNTRY_`.\n\n**Example:**\n\n```js\nconst country = {\n    type: \"fdc3.country\",\n    name: \"Sweden\",\n    id: {\n        COUNTRY_ISOALPHA2: \"SE\"\n    }\n}\n\nfdc3.broadcast(country)\n```\n\n## See Also\n\nIntents\n\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n\nFINOS Financial Objects\n\n- [Country](https://fo.finos.org/docs/objects/country)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Currency.md",
    "content": "---\nid: Currency\nsidebar_label: Currency\ntitle: Currency\nhide_title: true\n---\n\n# `Currency`\n\nA context representing an individual Currency.\n\n## Type\n\n`fdc3.currency`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/currency.schema.json](pathname:///schemas/2.1/context/currency.schema.json)\n\n## Details\n\n| Property                | Type    | Required | Example Value     |\n|-------------------------|---------|----------|-------------------|\n| `type`                  | string  | Yes      | `'fdc3.currency'` |\n| `name`                  | string  | No       | `'US Dollar'`     |\n| `id.CURRENCY_ISOCODE` * | string  | Yes      | `'USD'`           |\n\n\\* The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html).\n\n## Example\n\n```js\nconst currency = {\n    type: 'fdc3.currency',\n    name: 'US Dollar',\n    id: {\n        CURRENCY_ISOCODE: \"USD\"\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Email.md",
    "content": "---\nid: Email\nsidebar_label: Email\ntitle: Email\nhide_title: true\n---\n# `Email`\n\nA collection of information to be used to initiate an email with a Contact or ContactList\n\n## Type\n\n`fdc3.email`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/email.schema.json](pathname:///schemas/2.1/context/email.schema.json)\n\n## Details\n\n| Property          | Type                                  | Required | Example Value       |\n|-------------------|---------------------------------------|----------|---------------------|\n| `type`            | string                                | Yes      | `'fdc3.email'` |\n| `recipients`      | fdc3.contact or fdc3.contactList      | Yes      | `{ type: \"fdc3.contact\", name: \"John Doe\", id: { \"email\": \"john@sample.com\" } }` |\n| `subject`         | string                                | No       | `'The information you requested'`            |\n| `textBody`        | string                                | No       | `'Blah, blah, bah`         |\n\n## Example\n\n```js\nconst email = {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n}\n\n\nfdc3.raiseIntent(\"StartEmail\", email)\n```\n\n## See Also\n\nOther Types\n\n- [Contact](Contact)\n- [ContactList](ContactList)\n\nIntents\n\n- [StartEmail](../../intents/ref/StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Instrument.md",
    "content": "---\nid: Instrument\nsidebar_label: Instrument\ntitle: Instrument\nhide_title: true\n---\n# `Instrument`\n\nA financial instrument from any asset class.\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match.\n\nNotes:\n\n- Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified.\nIn general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\n- The `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\n\n- It is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement\nis for at least one instrument identifier to be provided.\n\n- Try to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define\na property that makes it clear what value represents. Doing so will make interpretation easier for the developers of target applications.\n\n## Type\n\n`fdc3.instrument`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/instrument.schema.json](pathname:///schemas/2.1/context/instrument.schema.json)\n\n## Details\n\n| Property                    | Type    | Required | Example Value            | More Info                                              |\n|-----------------------------|---------|----------|--------------------------|--------------------------------------------------------|\n| `type`                      | string  | Yes      | `\"fdc3.instrument\"`      |                                                        |\n| `name`                      | string  | No       | `\"Microsoft\"`            |                                                        |\n| `id.ticker`                 | string  | No       | `\"MSFT\"`                 |                                                        |\n| `id.BBG`                    | string  | No       | `\"MSFT:US\"`              | [https://www.bloomberg.com/](https://www.bloomberg.com/)                           |\n| `id.CUSIP`                  | string  | No       | `\"594918104\"`            | [https://www.cusip.com/](https://www.cusip.com/)                               |\n| `id.FDS_ID`                 | string  | No       | `\"P8R3C2-R\"`             | [https://www.factset.com/](https://www.factset.com/)                             |\n| `id.FIGI`                   | string  | No       | `\"BBG000BPH459\"`         | [https://www.openfigi.com/](https://www.openfigi.com/)                            |\n| `id.ISIN`                   | string  | No       | `\"US5949181045\"`         | [https://www.isin.org/](https://www.isin.org/)                                |\n| `id.PERMID`                 | string  | No       | `\"4295907168\"`           | [https://permid.org/](https://permid.org/)                                  |\n| `id.RIC`                    | string  | No       | `\"MSFT.OQ\"`              | [https://www.refinitiv.com/](https://www.refinitiv.com/)                           |\n| `id.SEDOL`                  | string  | No       | `\"2588173\"`              | [https://www.lseg.com/sedol](https://www.lseg.com/sedol)                           |\n| `market.MIC`                | string  | No       | `\"XNAS\"`                 | [https://en.wikipedia.org/wiki/Market_Identifier_Code](https://en.wikipedia.org/wiki/Market_Identifier_Code) |\n| `market.name`               | string  | No       | `\"NASDAQ - All Markets\"` |                                                        |\n| `market.COUNTRY_ISOALPHA2`  | string  | No       | `\"US\"`                   |                                                        |\n| `market.BBG`                | string  | No       | `\"US\"`                   | [https://www.bloomberg.com/](https://www.bloomberg.com/)                           |\n\n## Example\n\n```js\nconst instrument = {\n    type: \"fdc3.instrument\",\n    name: \"Microsoft\",\n    id: {\n        ticker: \"MSFT\",\n        RIC: \"MSFT.OQ\",\n        ISIN: \"US5949181045\"\n    },\n    market: {\n        MIC: \"XNAS\"\n    }\n}\n\nfdc3.joinUserChannel('Channel 1')\nfdc3.broadcast(instrument)\n```\n\n## See Also\n\nOther Types\n\n- [InstrumentList](InstrumentList)\n- [Chart](Chart)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n\n- [Instrument](https://fo.finos.org/docs/objects/instrument)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/InstrumentList.md",
    "content": "---\nid: InstrumentList\nsidebar_label: InstrumentList\ntitle: InstrumentList\nhide_title: true\n---\n# `InstrumentList`\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist).\n\nWhen holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type, though.\n\nNotes:\n\n- The instrument list schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.instrumentList`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/instrumentList.schema.json](pathname:///schemas/2.1/context/instrumentList.schema.json)\n\n## Details\n\n| Property      | Type         | Required | Example Value                  |\n|---------------|--------------|----------|--------------------------------|\n| `type`        | string       | Yes      | `'fdc3.instrumentList'`        |\n| `name`        | string       | No       | `'Interesting instruments...'` |\n| `id`          | object       | No       | `{ customId: '5464' }`         |\n| `instruments` | Instrument[] | Yes      | `[instrument1, instrument2]`   |\n\n## Example\n\n```js\nconst instruments = {\n    type: \"fdc3.instrumentList\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            },\n            market: {\n                MIC: \"XNAS\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ISIN: \"US5949181045\"\n            }\n        },\n    ]\n}\n\nfdc3.joinUserChannel('Channel 1')\nfdc3.broadcast(instruments)\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n- [Position](Position)\n- [Portfolio](Portfolio)\n\nIntents\n\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewInstrument](../../intents/ref/ViewInstrument)\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewQuote](../../intents/ref/ViewQuote)\n\nFINOS Financial Objects\n\n- [InstrumentList](https://fo.finos.org/docs/objects/instrumentlist)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Interaction.md",
    "content": "---\nid: Interaction\nsidebar_label: Interaction\ntitle: Interaction\nhide_title: true\n---\n# `Interaction`\n\nAn `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\n\nNotes:\n\n- `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\n- `origin` is used to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\n- `id` does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\n- `id` can be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted.\n- `id.URI` can be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\n\n## Type\n\n`fdc3.interaction`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/interaction.schema.json](pathname:///schemas/2.1/context/interaction.schema.json)\n\n## Details\n\n| Property           | Type             | Required  | Example Value                                   |\n|--------------------|------------------|-----------|-------------------------------------------------|\n| `type`             | string           | Yes       | `fdc3.interaction`                              |\n| `participants`     | fdc3.contactList | Yes       | See below                                       |\n| `timeRange`        | fdc3.timeRange   | Yes       | See below                                       |\n| `interactionType`  | string           | Yes       | `Instant Message`                               |\n| `description`      | string           | Yes       | `Blah, blah, blah`                              |\n| `initiator`        | fdc3.contact     | No        | See below                                       |\n| `origin`           | string           | No        | `Outlook`                                       |\n| `id.SINGLETRACK`   | string           | No        | `a0S8d000000uO05EAE`                            |\n| `id.SALESFORCE`    | string           | No        | `a0S8d000000uO05EAE`                            |\n| `id.URI`           | string           | No        | `https://example.com/record/a0S8d000000uO05EAE` |\n\n\n## Example\n\n```js\nconst interaction = {\n    type: 'fdc3.interaction',\n    participants: {\n        type: 'fdc3.contactList',\n        contacts: [\n            {\n                type: 'fdc3.contact',\n                name: 'Jane Doe',\n                id: {\n                    email: 'jane.doe@mail.com'\n                }\n             },\n            {\n                type: 'fdc3.contact',\n                name: 'John Doe',\n                id: {\n                    email: 'john.doe@mail.com'\n                }\n            },\n        ]\n    },\n    interactionType: 'Instant Message',\n    timeRange: {\n        type: 'fdc3.timeRange',\n        startTime: '2022-02-10T15:12:00Z'\n    },\n    description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n    initiator:  {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n            email: 'jane.doe@mail.com'\n        }\n    },\n    origin: 'Outlook'\n}\n\nfdc3.raiseIntent('CreateInteraction', interaction)\n```\n\n## See Also\n\nOther Types\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [TimeRange](TimeRange)\n- [TransactionResult](TransactionResult)\n\nIntents\n- [CreateInteraction](../../intents/ref/CreateInteraction)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Message.md",
    "content": "---\nid: Message\nsidebar_label: Message\ntitle: Message\nhide_title: true\n---\n# `Message`\n\nA chat message to be sent through an instant messaging application. Can contain one or several text bodies (organised by mime-type, plaintext or markdown),\nas well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\n\n## Type\n\n`fdc3.message`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/message.schema.json](pathname:///schemas/2.1/context/message.schema.json)\n\n## Details\n\n| Property          | Type                                      | Required | Example Value           |\n|-------------------|-------------------------------------------|----------|-------------------------|\n| `type`            | string                                    | Yes      | `'fdc3.message'`        |\n| `text`            | map of string mime-type to string content | No       | \\{ text/plain: 'Hello' \\} |\n| `entities`        | map of json entity to string id           | No       | See Below               |\n\n## Example\n\n```js\nconst message = {\n  type: 'fdc3.message',\n  text: {\n    'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate'\n  },\n  entities: {\n      'picture1': {\n          type: 'fdc3.fileAttachment',\n          data: {\n          name: 'myImage.png',\n                dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n          }\n      },\n      'eurusd_action': {\n        type: 'fdc3.action',\n        title: 'Click to view Chart',\n        intent: 'ViewChart',\n        context: {\n            type: 'fdc3.chart',\n            instruments: [\n                {\n                    type: 'fdc3.instrument',\n                    id: {\n                        ticker: 'EURUSD'\n                    }\n                }\n            ],\n            range: {\n                type: 'fdc3.dateRange',\n                starttime: '2020-09-01T08:00:00.000Z',\n                endtime: '2020-10-31T08:00:00.000Z'\n            },\n            style: 'candle'\n        }\n    }\n  }\n}\n```\n\n## See Also\n\nOther Types\n* [ChatInitSettings](ChatInitSettings)\n* [Action](Action)\n\nIntents\n* [StartChat](../../intents/ref/StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Nothing.md",
    "content": "---\nid: Nothing\nsidebar_label: Nothing\ntitle: Nothing\nhide_title: true\n---\n# `Nothing`\n\nA type that explicitly represents a lack of context.\n\nNotes:\n\n- Intended to be used in situations where no context is desired.\n- For example:\n  - Raising an intent without context (e.g. opening a blank order form, or chat\n    interface without a contact selected).\n  - Resetting context on a channel (e.g. when context is used to set a filter in\n    other applications a null context might release the filter).\n- An explicit representation of a Null or empty context allows apps to declare support for\n  a lack of context, for example in their intent metadata in an app directory.\n\n## Type\n\n`fdc3.nothing`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/nothing.schema.json](pathname:///schemas/2.1/context/nothing.schema.json)\n\n## Example\n\n```js\nconst nullContext = {\n    type: 'fdc3.nothing'\n}\n\nfdc3.joinUserChannel('groupA')\nfdc3.broadcast(nullContext)\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Order.md",
    "content": "---\nid: Order\nsidebar_label: Order\ntitle: Order\nhide_title: true\n---\n# `Order`\n\n[`@experimental`](/docs/fdc3-compliance#experimental-features) context type representing an order. To be used with OMS and EMS systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human-readable `name` field to be used to summarize the order, and an optional `details` field that may be used to provide additional detail about the order, including a Context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as an unspecified Context type, but both `details` and `details.product` are expected to be standardized in the future.\n\n## Type\n\n`fdc3.order`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/order.schema.json](pathname:///schemas/2.1/context/order.schema.json)\n\n## Details\n\n| Property          | Type       | Required | Details                   |\n|-------------------|------------|----------|---------------------------|\n| `type`            | string     | Yes      | `'fdc3.order'`            |\n| `id`              | object     | Yes      | One or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future. E.g.:`{ myOMS: '12345' }` |\n| `name`            | string     | No       | An optional human-readable summary of the order.    |\n| `details`         | object     | No       | Optional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context  |\n| `details.product` | Product    | No       | The product that the order relates to  |\n\n## Examples\n\n```js\nconst order1 = {\n    \"type\": \"fdc3.order\",\n    \"name\": \"...\",\n    \"id\": {\n        \"myOMS\": \"12345\"\n    },\n    \"details\": {\n        \"product\": {\n            \"type\": \"fdc3.product\",\n            \"id\": {\n              \"productId\": \"ABC123\"\n            },\n            \"instrument\": {\n                \"type\": \"fdc3.instrument\",\n                \"id\": {\n                    \"ticker\": \"MSFT\"\n                }\n            }\n        }\n    }\n};\n```\n\n```js\nconst order2 = {\n    \"type\": \"fdc3.order\",\n    \"id\": {\n        \"myOMS\": \"ABC123\"\n    }\n};\n```\n\n## See Also\n\nOther Types\n\n- [OrderList](OrderList)\n- [Product](Product)\n- [Trade](Trade)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/OrderList.md",
    "content": "---\nid: OrderList\nsidebar_label: OrderList\ntitle: OrderList\nhide_title: true\n---\n# `OrderList`\n\n[`@experimental`](/docs/fdc3-compliance#experimental-features) A list of orders. Use this type for use cases that require not just a single order, but multiple.\n\nNotes:\n\n- The OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.orderList`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/orderList.schema.json](pathname:///schemas/2.1/context/orderList.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.orderList'`        |\n| `id`         | object     | No       | `{ listId: '1234' }` |\n| `name`       | string     | No       | `'Today's orders'`    |\n| `orders`     | Trade[]    | Yes      | `[order1, order2]`  |\n\n## Example\n\n```js\nconst orderList = {\n    type: \"fdc3.orderList\",\n    orders: [\n        {\n            \"type\": \"fdc3.order\",\n            \"id\": {\n                \"myOMS\": \"ABC123\"\n            }\n        },\n        {\n            \"type\": \"fdc3.order\",\n            \"id\": {\n                \"myOMS\": \"DEF456\"\n            }\n        }\n    ]\n};\n```\n\n## See Also\n\nOther Types\n\n- [Order](Order)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Organization.md",
    "content": "---\nid: Organization\nsidebar_label: Organization\ntitle: Organization\nhide_title: true\n---\n# `Organization`\n\nAn entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement\nis for at least one specified identifier to be provided.\n\n## Type\n\n`fdc3.organization`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/organization.schema.json](pathname:///schemas/2.1/context/organization.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value             |\n|-------------|---------|----------|---------------------------|\n| `type`      | string  | Yes      | `'fdc3.organization'`     |\n| `name`      | string  | No       | `'Cargill, Incorporated'` |\n| `id.LEI`    | string  | No       | `'QXZYQNMR4JZ5RIRN4T31'`  |\n| `id.PERMID` | string  | No       | `'4296555324'`            |\n| `id.FDS_ID` | string  | No       | `'00161G-E'`              |\n\n## Example\n\n```js\nconst organization = {\n    type: \"fdc3.organization\",\n    name: \"Cargill, Incorporated\",\n    id: {\n        LEI: \"QXZYQNMR4JZ5RIRN4T31\",\n        FDS_ID: \"00161G-E\"\n    }\n}\n\nfdc3.broadcast(organization)\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n\nIntents\n\n- [ViewNews](../../intents/ref/ViewNews)\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [ViewResearch](../../intents/ref/ViewResearch)\n- [ViewInteractions](../../intents/ref/ViewInteractions)\n- [ViewOrders](../../intents/ref/ViewOrders)\n\nFINOS Financial Objects\n\n- [Organization](https://fo.finos.org/docs/objects/organization)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Portfolio.md",
    "content": "---\nid: Portfolio\nsidebar_label: Portfolio\ntitle: Portfolio\nhide_title: true\n---\n# `Portfolio`\n\nA financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this\nwith e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe [Portfolio](Portfolio) type consists of an array of [Position](Position) types, each of which\nrefers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the portfolio can be added, the schema just\nspecifies the minimum contract.\n\n- The portfolio schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.portfolio`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/portfolio.schema.json](pathname:///schemas/2.1/context/portfolio.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.portfolio'`        |\n| `id`         | object     | No       | `{ portfolioId: '7381' }` |\n| `name`       | string     | No       | `'My share portfolio'`    |\n| `positions`  | Position[] | Yes      | `[position1, position2]`  |\n\n## Example\n\n```js\nconst portfolio = {\n    type: \"fdc3.portfolio\",\n    positions: [\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"AAPL\"\n                }\n            },\n            holding: 2000000\n        },\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"MSFT\"\n                }\n            },\n            holding: 1500000\n        },\n        {\n            type: \"fdc3.position\",\n            instrument: {\n                type: \"fdc3.instrument\",\n                id: {\n                    ticker: \"IBM\"\n                }\n            },\n            holding: 3000000\n        }\n    ]\n}\nfdc3.raiseIntent(\"ViewAnalysis\", portfolio)\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Position](Position)\n\nIntents\n\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n\n- [Position](https://fo.finos.org/docs/objects/portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Position.md",
    "content": "---\nid: Position\nsidebar_label: Position\ntitle: Position\nhide_title: true\n---\n# `Position`\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good\nexample of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents\nmultiple holdings in a combination of instruments.\n\nNotes:\n\n- Like all other FDC3 context types, extra properties for the position can be added, the schema just\nspecifies the minimum contract.\n\n- The position schema does not explicitly include identifiers in the `id` section, as there\nis not a common standard for such identifiers. Applications can, however, populate\nthis part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.position`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/position.schema.json](pathname:///schemas/2.1/context/position.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Example Value                      |\n|--------------|------------|----------|------------------------------------|\n| `type`       | string     | Yes      | `'fdc3.position'`                  |\n| `id`         | object     | No       | `{ positionId: '6475' }`           |\n| `name`       | string     | No       | `'My Apple shares'`                |\n| `holding`    | number     | Yes      | `2000000`                          |\n| `instrument` | Instrument | Yes      | `{ type: 'fdc3.instrument', ... }` |\n\n## Example\n\n```js\nconst position = {\n    type: \"fdc3.position\",\n    instrument: {\n        type: \"fdc3.instrument\",\n        id: {\n            ticker: \"AAPL\"\n        }\n    },\n    holding: 2000000\n}\n\nfdc3.raiseIntent(\"ViewChart\", position)\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n- [Portfolio](Portfolio)\n\nIntents\n\n- [ViewAnalysis](../../intents/ref/ViewAnalysis)\n- [ViewChart](../../intents/ref/ViewChart)\n- [ViewNews](../../intents/ref/ViewNews)\n\nFINOS Financial Objects\n\n- [Position](https://fo.finos.org/docs/objects/position)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Product.md",
    "content": "---\nid: Product\nsidebar_label: Product\ntitle: Product\nhide_title: true\n---\n# `Product`\n\n[`@experimental`](/docs/fdc3-compliance#experimental-features) context type representing a tradable product. To be used with OMS and EMS systems. This type is currently only loosely defined as an extensible context object, with an optional instrument field.\n\nNotes:\n\n- The Product schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.product`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/product.schema.json](pathname:///schemas/2.1/context/product.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.product'`        |\n| `id`         | object     | Yes      | One or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future. |\n| `name`       | string     | No       | A human-readable summary of the product. |\n| `instrument` | Instrument | No       | A financial instrument that relates to the definition of this product. |\n\n## Example\n\n```js\nconst product = {\n    \"type\": \"fdc3.product\",\n    \"id\": {\n      \"productId\": \"ABC123\"\n    },\n    \"instrument\": {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"MSFT\"\n      }\n    }\n};\n```\n\n## See Also\n\nOther Types\n\n- [Instrument](Instrument)\n- [Order](Order)\n- [Trade](Trade)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/TimeRange.md",
    "content": "---\nid: TimeRange\nsidebar_label: TimeRange\ntitle: TimeRange\nhide_title: true\n---\n# `TimeRange`\n\nA context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\n\n- A pricing chart\n- A trade blotter\n- A record of client contact/activity in a CRM\n\nExample use cases:\n\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\n\nNotes:\n\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\n\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\n\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n  - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or `\"2022-05-12T16:18:03+01:00\"`\n  - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n\n## Type\n\n`fdc3.timeRange`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/timeRange.schema.json](pathname:///schemas/2.1/context/timeRange.schema.json)\n\n## Details\n\n| Property    | Type      | Required | Example Value                 |\n|-------------|-----------|----------|-------------------------------|\n| `type`      | string    | Yes      | `\"fdc3.timeRange\"`            |\n| `startTime` | string *  | No **    | `\"2022-03-30T15:44:44Z\"`      |\n| `endTime`   | string *  | No **    | `\"2022-04-30T23:59:59+00:00\"` |\n\n\\* Fields representing time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n\\*\\* One of `startTime` or `endTime` MUST be specified.\n\n## Example\n\nA closed range:\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    startTime: \"2022-03-30T15:44:44Z\",\n    endTime: \"2022-04-30T23:59:59ZS\"\n}\n```\n\nOpen ranges:\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    startTime: \"2022-03-30T15:44:44+00:00\"\n}\n```\n\n```js\nconst timeRange = {\n    type: \"fdc3.timeRange\",\n    endTime: \"2022-03-30T16:44:44.123Z\"\n}\n```\n\n## See Also\n\nOther Types\n\n- [Chart](Chart)\n\nIntents\n- [CreateInteraction](../../intents/ref/CreateInteraction)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Trade.md",
    "content": "---\nid: Trade\nsidebar_label: Trade\ntitle: Trade\nhide_title: true\n---\n# `Trade`\n\n[`@experimental`](/docs/fdc3-compliance#experimental-features) context type representing a trade. To be used with execution systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as an unspecified Context type, but `product` is expected to be standardized in future.\n\nNotes:\n\n- The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.trade`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/trade.schema.json](pathname:///schemas/2.1/context/trade.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Details             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.trade'`        |\n| `id`         | object     | Yes      | One or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future. |\n| `name`       | string     | No       | A human-readable summary of the trade, e.g. `'100 TSLA @ 290.85 USD'`    |\n| `product`    | Product    | Yes      | A tradeable product  |\n\n## Example\n\n```js\nconst trade = {\n    \"type\": \"fdc3.trade\",\n    \"name\": \"...\",\n    \"id\": {\n        \"myEMS\": \"12345\"\n    },\n    \"product\": {\n        \"type\": \"fdc3.product\",\n        \"id\": {\n          \"productId\": \"ABC123\"\n        },\n \"instrument\": {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n                \"ticker\": \"MSFT\"\n            }\n        }\n    }\n};\n```\n\n## See Also\n\nOther Types\n\n- [Product](Product)\n- [TradeList](TradeList)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/TradeList.md",
    "content": "---\nid: TradeList\nsidebar_label: TradeList\ntitle: TradeList\nhide_title: true\n---\n# `TradeList`\n\n[`@experimental`](/docs/fdc3-compliance#experimental-features) A list of trades. Use this type for use cases that require not just a single trade, but multiple.\n\nNotes:\n\n- The TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Type\n\n`fdc3.tradeList`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/tradeList.schema.json](pathname:///schemas/2.1/context/tradeList.schema.json)\n\n## Details\n\n| Property     | Type       | Required | Example Value             |\n|--------------|------------|----------|---------------------------|\n| `type`       | string     | Yes      | `'fdc3.tradeList'`        |\n| `id`         | object     | No       | `{ listId: '1234' }` |\n| `name`       | string     | No       | `'Today's trades'`    |\n| `trades`     | Trade[]    | Yes      | `[trade1, trade2]`  |\n\n## Example\n\n```js\nconst tradeList = {\n    type: \"fdc3.tradeList\",\n    trades: [\n        {\n            \"type\": \"fdc3.trade\",\n            \"name\": \"...\",\n            \"id\": {\n                \"myEMS\": \"12345\"\n            },\n            \"product\": {\n                \"type\": \"fdc3.product\",\n                \"id\": {\n                    \"productId\": \"ABC123\"\n                },\n                \"instrument\": {\n                    \"type\": \"fdc3.instrument\",\n                    \"id\": {\n                        \"ticker\": \"MSFT\"\n                    }\n                }\n            }\n        },\n        {\n            \"type\": \"fdc3.trade\",\n            \"id\": {\n                \"myEMS\": \"67890\"\n            },\n            \"product\": {\n                \"type\": \"fdc3.product\",\n                \"id\": {\n                    \"productId\": \"DEF456\"\n                },\n                \"instrument\": {\n                    \"type\": \"fdc3.instrument\",\n                    \"id\": {\n                        \"ticker\": \"TSLA\"\n                    }\n                }\n            }\n        }\n    ]\n};\n```\n\n## See Also\n\nOther Types\n\n- [Trade](Trade)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/TransactionResult.md",
    "content": "---\nid: TransactionResult\nsidebar_label: TransactionResult\ntitle: TransactionResult\nhide_title: true\n---\n# `TransactionResult`\n\nA context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an [`IntentResult`](../../api/ref/Types#intentresult) by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\n\n## Type\n\n`fdc3.transactionResult`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/transactionresult.schema.json](pathname:///schemas/2.1/context/transactionresult.schema.json)\n\n## Details\n\n| Property   | Type    | Required | Example Value     |\n|------------|---------|----------|-------------------|\n| `type`     | string  | Yes      | 'fdc3.transactionResult' |\n| `status`   | string  | Yes      | `\"Created\" \\| \"Deleted\" \\| \"Updated\" \\| \"Failed\"` |\n| `context`  | Context | No       | See Below |\n| `message`  | string  | No       | See Below |\n\n## Example\n\n```js\nconst contact = {\n    type: \"fdc3.contact\",\n    name: \"Jane Doe\",\n    id: {\n        email: \"jane.doe@mail.com\"\n    }\n}\n\nconst resolution = await window.fdc3.raiseIntent('CreateOrUpdateProfile', contact);\nconst result = await resolution.getResult();\nconsole.log(JSON.stringify(result));\n```\n\nConsole log will display:\n\n```json\n{\n    \"type\": \"fdc3.transactionResult\",\n    \"status\": \"Updated\",\n    \"context\": {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n            \"email\": \"jane.doe@mail.com\"\n        }\n    },\n    \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/ref/Valuation.md",
    "content": "---\nid: Valuation\nsidebar_label: Valuation\ntitle: Valuation\nhide_title: true\n---\n# `Valuation`\n\nA context type representing the price and value of a holding.\n\n## Type\n\n`fdc3.valuation`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.1/context/valuation.schema.json](pathname:///schemas/2.1/context/valuation.schema.json)\n\n## Details\n\n| Property             | Type    | Required | Example Value                 |\n|----------------------|---------|----------|-------------------------------|\n| `type`               | string  | Yes      | `'fdc3.valuation'`            |\n| `value`              | number  | Yes      | `500.0`                       |\n| `price`              | number  | No       | `5.0`                         |\n| `CURRENCY_ISOCODE` * | string  | Yes      | `GBP`                         |\n| `valuationTime` **   | string  | No       | `\"2022-05-12T16:16:24.815Z\"`  |\n| `expiryTime` **      | string  | No       | `\"2022-05-13T16:16:24+01:00\"` |\n\n\\* The `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html).\n\n\\*\\* Time fields SHOULD conform to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n## Example\n\n```js\nconst valuation = {\n    type: 'fdc3.valuation',\n    value: 500.0,\n    price: 5.0,\n    CURRENCY_ISOCODE: 'USD',\n    expiryTime: \"2022-05-13T16:16:24+01:00\"\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/context/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Context Data (2.1)\n---\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems. FDC3 Context Data defines a standard for passing common identifiers and data, encoded in JSON, between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard JSON payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [intents](../intents/spec) and when broadcasting context to other applications.\n\nThere are two main use cases for exchanging context data:\n\n- **Transmitting reference data between applications.**\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n- **Transferring information between applications.**\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there aren't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n### Context Schemas\n\nFDC3 Context data is primarily encoded in JSON, but may also be encoded in language specific formats for use with FDC3 API implementations in those languages, although it is advisable to ensure that they can be converted to and from JSON.\n\nEach Standardized context type defined by the FDC3 Standard has an associated [JSON Schema](https://json-schema.org/) definition that should be considered the 'source of truth' for the context definition, although examples in documentation may also be given in TypeScript or JavaScript. The TypeScript definitions distributed in the FDC3 NPM module are generated from the JSON Schema files using [quicktype](https://quicktype.io/). Both documentation for fields defined (in the form of a `title` and `description` entry for each field defined) and examples SHOULD be included in JSON Schema definitions for Context types to ensure that the schema file can serve as a single source of truth, and that code generated from the schema files can also include that documentation.\n\n## The Context Interface\n\nContext can be summarized as:\n\n- Having a unique _type_ identifier, used for routing.\n- Optionally providing a name.\n- Optionally providing a map of equivalent identifiers.\n- Any other properties or metadata.\n\nHence, the Context Interface can be represented in TypeScript as:\n\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n\nor in JSON Schema as:\n\n```JSON\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/2.1/context/context.schema.json\",\n    \"type\": \"object\",\n    \"title\": \"Context\",\n    \"description\": \"The `fdc3.context` type defines the basic contract or \\\"shape\\\" for all data exchanged by FDC3 operations. As such, it is not really meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\\n\\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the object represents, and what shape it has.\\n\\nThe FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\",\n    \"properties\": {\n        \"type\": {\n            \"type\": \"string\"\n        },\n        \"name\": {\n            \"type\": \"string\"\n        },\n        \"id\": {\n            \"type\": \"object\",\n            \"unevaluatedProperties\": {\n                \"type\": \"string\"\n            }\n        }\n    },\n    \"additionalProperties\": true,\n    \"required\": [\n        \"type\"\n    ]\n}\n```\n\n### Namespacing\n\nAll well-known types at FDC3 level should be prefixed with `fdc3`. For private type definitions, or type definitions issued by other organizations, different namespaces can be used, e.g. `blackrock.fund`, etc.\n\n### Versioning\n\nThe specification recognizes that evolving context data definitions over time, and helping applications to deal with changes to types, are very important.\n\nIt may be as simple as adding an optional `$version` property to types, but it could also be a set of guidelines for adding new properties, without removing or changing existing ones. For example, web technologies like REST or GraphQL do not take a particular opinion about versioning.\n\n### Field Type Conventions\n\nThis Standard defines a number of conventions for the fields of context types that all context objects SHOULD adhere to in order to reduce or prevent competing conventions from being established in both standardized types and proprietary types created by app developers.\n\n#### Identifiers\n\nAn `id` field with type `object` is defined in the base [fdc3.context](ref/Context) type, from which all other context objects are derived, and SHOULD be used to encapsulate identifiers. Specific context types may define subfields for specific identifiers as needed.\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\n\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n#### Times\n\nFields representing a point in time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included, e.g.:\n\n- Time in UTC: `\"2022-03-30T15:44:44Z\"`\n- Also time in UTC: `\"2022-03-30T15:44:44+00:00\"`\n- Same time in EDT: `\"2022-03-30T11:44:44-04:00\"`\n\nTimes MAY be expressed with millisecond precision, e.g.:\n\n- `\"2022-03-30T11:44:44.123-04:00\"`\n- `\"2022-03-30T11:44:44.123Z\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30T11:44:44.123-04:00\")\n```\n\n#### Dates\n\nFields representing a point in time SHOULD be string encoded using the `YYYY-MM-DD` date format from [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n\nE.g. `\"2022-03-30\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30\")\n```\n\n#### Country codes\n\nFields representing a country SHOULD be string encoded using the Alpha-2-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) and field name `COUNTRY_ISOALPHA2`. The Alpha-3-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) MAY be used in addition to the Alpha-2-code with the field name `COUNTRY_ISOALPHA3`.\n\nE.g. `\"COUNTRY_ISOALPHA2\": \"GB\"`\n\n#### Currency codes\n\nFields representing a currency SHOULD be string encoded using the Alphabetic code from [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) with the field name `CURRENCY_ISOCODE`.\n\nE.g. `\"CURRENCY_ISOCODE\": \"GBP\"`\n\n:::note\nISO 4217 only includes major currency codes, conversions to minor currencies is the responsibility of the consuming system (where required).\n:::\n\n## Context Data Standard Compliance\n\nAn FDC3 Standard compliant application that supports the use of context data **MUST**:\n\n- Ensure that any FDC3-defined standard context types used meet the interface defined for that type of context data.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers.\n- Where App or Private channels are supported, use the [`Channel.addContextListener`](../api/ref/Channel#addcontextlistener) API call to set up appropriate handlers.\n\nAn FDC3 Standard compliant application that supports the use of context data **SHOULD**:\n\n- Prefer FDC3-defined standard context types over proprietary contexts, where a suitable FDC3-defined standard context type is available.\n- Ensure that any proprietary context data types defined follow any the recommended [namespacing](#namespacing) and [field type conventions](#field-type-conventions) in the specification.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n\nAn FDC3 Standard compliant application that supports the use of context data **MAY**:\n\n- Define proprietary context data types to support use cases not currently supported via FDC3-defined standard context types.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Context Types\n\nThe following are standard FDC3 context types:\n\n- [`fdc3.action`](ref/Action) ([schema](pathname:///schemas/2.1/context/action.schema.json))\n- [`fdc3.chart`](ref/Chart) ([schema](pathname:///schemas/2.1/context/chart.schema.json))\n- [`fdc3.chat.initSettings`](ref/ChatInitSettings) ([schema](pathname:///schemas/2.1/context/chatInitSettings.schema.json))\n- [`fdc3.chat.message`](ref/ChatMessage) ([schema](pathname:///schemas/2.1/context/chatMessage.schema.json))\n- [`fdc3.chat.room`](ref/ChatRoom) ([schema](pathname:///schemas/2.1/context/chatRoom.schema.json))\n- [`fdc3.chat.searchCriteria`](ref/ChatSearchCriteria) ([schema](pathname:///schemas/2.1/context/chatSearchCriteria.schema.json))\n- [`fdc3.contact`](ref/Contact) ([schema](pathname:///schemas/2.1/context/contact.schema.json))\n- [`fdc3.contactList`](ref/ContactList) ([schema](pathname:///schemas/2.1/context/contactList.schema.json))\n- [`fdc3.country`](ref/Country) ([schema](pathname:///schemas/2.1/context/country.schema.json))\n- [`fdc3.currency`](ref/Currency) ([schema](pathname:///schemas/2.1/context/currency.schema.json))\n- [`fdc3.email`](ref/Email) ([schema](pathname:///schemas/2.1/context/email.schema.json))\n- [`fdc3.instrument`](ref/Instrument) ([schema](pathname:///schemas/2.1/context/instrument.schema.json))\n- [`fdc3.instrumentList`](ref/InstrumentList) ([schema](pathname:///schemas/2.1/context/instrumentList.schema.json))\n- [`fdc3.interaction`](ref/Interaction) ([schema](pathname:///schemas/2.1/context/interaction.schema.json))\n- [`fdc3.message`](ref/Message) ([schema](pathname:///schemas/2.1/context/message.schema.json))\n- [`fdc3.organization`](ref/Organization) ([schema](pathname:///schemas/2.1/context/organization.schema.json))\n- [`fdc3.portfolio`](ref/Portfolio) ([schema](pathname:///schemas/2.1/context/portfolio.schema.json))\n- [`fdc3.position`](ref/Position) ([schema](pathname:///schemas/2.1/context/position.schema.json))\n- [`fdc3.nothing`](ref/Nothing) ([schema](pathname:///schemas/2.1/context/nothing.schema.json))\n- [`fdc3.timeRange`](ref/TimeRange) ([schema](pathname:///schemas/2.1/context/timeRange.schema.json))\n- [`fdc3.transactionResult`](ref/TransactionResult) ([schema](pathname:///schemas/2.1/context/transactionresult.schema.json))\n- [`fdc3.valuation`](ref/Valuation) ([schema](pathname:///schemas/2.1/context/valuation.schema.json))\n\nThe following are [`@experimental`](/docs/fdc3-compliance#experimental-features) types, which are in the process of being defined:\n\n- [`fdc3.order`](ref/Order) ([schema](pathname:///schemas/2.1/context/order.schema.json))\n- [`fdc3.orderList`](ref/OrderList) ([schema](pathname:///schemas/2.1/context/orderList.schema.json))\n- [`fdc3.product`](ref/Product) ([schema](pathname:///schemas/2.1/context/product.schema.json))\n- [`fdc3.trade`](ref/Trade) ([schema](pathname:///schemas/2.1/context/trade.schema.json))\n- [`fdc3.tradeList`](ref/TradeList) ([schema](pathname:///schemas/2.1/context/tradeList.schema.json))\n\n### Examples\n\nThe below examples show how the base context data interface can be used to define specific context data objects.\n\n#### Contact\n\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### Email\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n#### Instrument\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### TypeScript definition\n\nThe `Instrument` type is derived from the `Context` type (note that the name becomes a required field, the type is fixed and optional `id` subfields are defined):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" : \n    {  \n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/fdc3-charter.md",
    "content": "---\nid: fdc3-charter\ntitle: FDC3 Charter\n---\n\n## Scope\n\nThe FDC3 Standard specifies protocols and taxonomies to enable applications in financial services workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements between app developers.\n\nFinancial applications include any type of application used in common financial workflows, including:\n\n- Containerized Web applications - Interoperability platforms extending Chromium (e.g. Electron, OpenFin, interop.io's io.Connect)\n- PWAs & Web applications running in a commercial browser\n- Traditional native applications implemented in C++, .NET, Java, Python, etc.\n- Hybrid web/native applications - stand alone native apps embedding a WebView (e.g. Electron, CEF, WebView2, NW.js etc.)\n- Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, Slack, etc.\n\nThis standards group is focused specifically on establishing and promoting standards for the interoperability of front-end applications, hence, its activities are focused on:\n\n- The discovery, configuration, identity and use of financial services applications (e.g. the FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview)),\n- APIs for communication and interaction between applications (e.g. the [Desktop Agent API](https://fdc3.finos.org/docs/api/spec) and [Agent Bridging API](https://fdc3.finos.org/docs/agent-bridging/spec)),\n- Message formats used for communication (e.g. [Context Data](https://fdc3.finos.org/docs/context/spec))\n- Names for requested functionality and workflow steps (e.g. [Intents](https://fdc3.finos.org/docs/intents/spec))\n- Creating and promoting tests for conformance to these standards (e.g. the FDC3 Conformance Framework) and training & certification programs that relate to them (e.g. [Introduction to FDC3](https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/))\n\nThe group's activities do not include:\n\n- Interoperability or communication between back-end platforms.\n- Defining financial objects - where existing standards are well established and can be reused.\n\n## Licensing\n\n- Version 1.0 of the FDC3 specification is licensed under the [FDC3 1.0 Final Specification License](https://github.com/finos/FDC3/blob/17892008c26a73ff1fd9f6e40ceb8c8bfd58c610/PATENTS-FDC3-1.0.md).\n\n- Versions 1.1 - 2.1 of the FDC3 specification are subject to the [FINOS IP Policy](https://github.com/finos/community/blob/fdd059c93b6ceefadd8cf60c4bef995366695337/website/static/governance-docs/IP-Policy.pdf), which authorizes implementation of FDC3 specifications without charge, on a RAND basis, subject to the terms of the policy. For details of the IP commitments made by contributors to FDC3, please refer to the policy.\n\n- Versions of the FDC3 specification following 2.1 and subsequent draft specifications are licensed under the [Community Specification License 1.0](https://github.com/finos/FDC3/blob/4ce90d45ca8e0c4f8f2c5bd73f51304278783d87/LICENSE.md)\n\n- All code in the FDC3 specification (including JSON Schema) are licensed under [Apache 2.0](https://github.com/finos/FDC3/blob/main/LICENSE)\n\n### Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/fdc3-compliance.md",
    "content": "---\nid: fdc3-compliance\ntitle: Compliance\n---\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>    Imperatives of the type defined in this memo must be used with care\n>    and sparingly.  In particular, they MUST only be used where it is\n>    actually required for interoperation or to limit behavior which has\n>    potential for causing harm (e.g., limiting retransmissions)  For\n>    example, they must not be used to try to impose a particular method\n>    on implementors where the method is not required for\n>    interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers the API, App Directory, Context Data, and Intents specifications.\n\n## Personas\n\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation(s) of the FDC3 APIs (The Desktop Agent API and Application Directory) for applications to use.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.\n\nDepending on persona, implementation compliance with FDC3 will mean different things.\n\n### Platform Provider\n\nFor platform providers FDC3 compliance requires that they meet the requirements of the APIs that they implement:\n\n- [Desktop Agent API compliance requirements](api/spec#desktop-agent-api-standard-compliance).\n- [App Directory compliance requirements](app-directory/spec#app-directory-standard-compliance).\n\n### Application Provider\n\nFor application providers FDC3 compliance requires that they interact with the FDC3 APIs as intended and meet the requirements of the Intents and Context Data Standards. Specifically:\n\n- [Intents Standard compliance requirements](intents/spec#intents-standard-compliance)\n- [Context Data Standard compliance requirements](context/spec#context-data-standard-compliance)\n\n## Versioning\n\nTypically, a Standard that has marketplace relevance is revised from time to time, to correct errors and/or to add functionality to support new use cases. Hence, there exist multiple versions of the standard. As FDC3 is a standards project, we don't follow semver, which is meant for libraries. We use the versioning scheme `<major>.<minor>`, e.g. `1.1` or `2.3`.\n\n## Deprecation Policy\n\nOver time, it is not uncommon for certain things in a standard to be marked for removal in a future version, possibly being replaced by an alternative. That is, they are deprecated. Often, they are retained in the standard because of their widespread use, but their use in new projects is discouraged.\n\nFDC3 adopts the following deprecation policy:\n\n1. A feature can be deprecated by any major or minor version. Newly deprecated features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n2. A feature shall only be removed by a major version. Newly removed features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n3. Deprecated features are clearly marked with an `@deprecated` tag and comment in both the documentation and jsDocs applied to the TypeScript sources.\n4. Where possible, changes to the behavior of an existing feature should be avoided; consider deprecating it and replacing it with something with a different name/syntax.\n5. Breaking change should only be made in a major version of the Standard.\n\n## Experimental Features\n\nOccasionally, a change to FDC3 may be proposed where the design is tentative, and because of this, we need feedback from the community to finalize its inclusion in the Standard. In such cases, a feature may be designated as _experimental_ to indicate that its design may change in future and that it is exempted from the normal versioning and deprecation polices in order to facilitate that change.  However, designating a feature as experimental is likely to reduce its uptake by the community, hence, this designation should be used sparingly.\n\nFDC3 adopts the following experimental features policy:\n\n1. A feature may be designated as experimental where feedback is needed to confirm the final design of that feature, with the goal of including it as a full part of the Standard without the experimental label.\n2. A feature should only be designated as experimental where there is a reasonable chance that breaking changes to its design may be applied, based on feedback received; non-breaking changes (refinements) may already be applied to features defined in the Standard without the experimental designation.\n3. Experimental features are clearly marked with an `@experimental` tag and comment in both the documentation and docs applied to the TypeScript sources.\n4. Unless otherwise stated, experimental features should be considered optional for compliance purposes, but recommended for implementation (i.e. the SHOULD keyword is implied).\n5. Experimental features are exempted from the normal versioning and deprecation policies that govern changes to FDC3. I.e. breaking changes may be made to experimental features between versions of the Standard without a major version release.\n6. The experimental designation may be removed from a feature in a minor version release (as this will be considered an additive change).\n\n## Conformance testing\n\nThe FDC3 Standards include a set of [definitions for conformance tests](api/conformance/Conformance-Overview) that may be used to determine if a Desktop Agent API implementation conforms to a particular Standard version, to help disambiguate complex parts of the FDC3 Standard and to enable test-driven development of a Desktop Agent implementation.\n\nThe current set of tests focus on the Desktop Agent API and the interface to it. Tests are not yet defined for the App Directory API or Bridging API Parts of the FDC3 Standard, hence, conformance to those parts of the Standard must be determined manually.\n\n:::info\nAs FDC3 2.1 does not introduce changes to the Desktop Agent API, the conformance test set for FDC3 2.0 remains current for this version. Please see the [FDC3 2.1 Changelog entry](https://github.com/finos/FDC3/blob/main/CHANGELOG.md#fdc3-standard-21---2023-09-13) for more details.\n:::\n\nThe FDC3 Conformance tests are implemented for JavaScript/TypeScript web applications by the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework). Desktop Agent implementors working with web interfaces (Desktop Agent Preload or Desktop Agent Proxy) can clone the conformance framework and run the tests locally to determine if their agent is compliant with the Standard.\n\nOnce a Desktop Agent has passed the conformance tests locally, its authors can [apply for a formal certification of compliance with the Standard from FINOS](https://github.com/finos/FDC3-conformance-framework/blob/main/instructions.md). Please note the [Terms and Conditions](https://github.com/finos/FDC3-conformance-framework/blob/main/terms-conditions/FDC3-Certified-Terms.md) of the Conformance Program.\n\nimport badge_12 from '/img/community/certified-1.2.png';\nimport badge_20 from '/img/community/certified-2.0.png';\n\n<img src={badge_12} alt=\"Certified conformant with FDC3 1.2 badge\" style={{width: 200}} />\n<img src={badge_20} alt=\"Certified conformant with FDC3 2.0 badge\" style={{width: 200}} />\n\n## Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/fdc3-glossary.md",
    "content": "---\nid: fdc3-glossary\ntitle: Glossary of Terms\nsidebar_label: Glossary\n---\n\nFor the purposes of this Standard, the following definitions apply. Other terms are defined when first used, at which place they appear in bold and italic type. Terms explicitly defined in this Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined are assumed to be well-known in the financial services or software industries.\n\n- **Agent Bridge**: Shorthand for Desktop Agent Bridge.\n- **app**: Shorthand for application.\n- **app directory**: A repository of application metadata supporting discovery, for example via name or intent, and retrieval of metadata necessary to launch an application.\n- **app directory record**: Metadata relating to a single application, encoded in JSON.\n- **appD**: Shorthand for app directory.\n- **appD record**: Shorthand for app directory record.\n- **application**: Any endpoint on the desktop that is registered with/known by a Desktop Agent, launchable by a Desktop Agent, addressable by a Desktop Agent or otherwise able to interact with the Desktop Agent.\n- **application, hybrid**: Any web application running within the context of a standalone native application that embeds a web view, typically based on Chromium.\n- **application, native**: A non-web-based application; i.e., one that runs outside the context of web browser, web view or web container. A user-written program, typically implemented in a language such as C++, C#, Java, or Python, rather than JavaScript or TypeScript.\n- **application, web**: An application written in TypeScript or JavaScript, HTML and CSS, which runs within the context of a web browser or a web container.\n- **Application Provider**: A downstream consumer of FDC3 Standards that can understand and use the FDC3 API (supplied by a Platform Provider), context data, and/or intents.\n- **application-specific intent**: A custom intent defined by an application or applications, independent of the Standard.\n- **Bridge**: Shorthand for Desktop Agent Bridge.\n- **bridging**: Shorthand for the exchange of messages across a Desktop Agent Bridge for the purposes of extending interop between apps managed by different Desktop Agents.\n- **Channel**: A grouping of apps for the purposes of sharing stateful pieces of data. A secondary interface of the FDC3 API.\n- **context channels**: A mechanism to allow sets of apps to share stateful pieces of data among themselves, and to be alerted when that data changes.\n- **context**: Shorthand for context data.\n- **context data**: Objects encoding common identifiers and data in a standardized format that can be passed between apps via context channels or used in conjunction with intents to invoke actions creating a seamless cross-application workflow. Diverse context data types are created to encode different types of data, each having their own _type_ field and unique set of data fields.\n- **DAB**: Acronym of Desktop Agent Bridge.\n- **Desktop Agent**: A desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain. The primary interface of the FDC3 API.\n- **Desktop Agent Bridge**: An independent service that Desktop Agents connect to which allows them to relay requests to other Desktop Agents also connected to the bridge, allowing FDC3-based interop to extend across multiple Desktop Agents and machines.\n- **FDC3 API**: A baseline, consistent developer interface for interoperability between applications.\n- **GUID**: Globally Unique IDentifier, synonymous with UUID. Defined by [IETF RFC4122](references).\n- **interop**: Shorthand for interoperability.\n- **interoperability**: the ability of software applications to exchange and make use of information and invoke specified actions.\n- **intent**: A verb, with a pre-agreed meaning (expected behavior), used to invoke an action between applications. A set of such verbs can, in conjunction with Context Data acting as nouns, be used to put together common cross-application workflows on the financial desktop.\n- **Listener**: API interface which allows unsubscribing from Intents or Context Channels.\n- **Originating App**: The application that sent a particular context message or raised an intent.\n- **Platform Provider**: An environment that provides an implementation of the FDC3 API that applications can use.\n- **raising an intent**: The act of requesting, via the FDC3 API/Desktop Agent that a specified action be performed by another application, using specified context data as input.\n- **resolver**: A facility of a Desktop Agent used to map a raised intent and associated context object to an application that will perform the action represented by the intent, using the context object as input. Where multiple applications can resolve the intent, a resolver will often display a user-interface allowing a user to pick from the available applications that support the intent and type of context supplied.\n- **resolving an intent**: The act of mapping a specified intent and context object to an application.\n- **standard intent**: An intent defined by this Standard.\n- **UUID**: Universally Unique IDentifier, synonymous with GUID. Defined by [IETF RFC4122](references).\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/fdc3-intro.md",
    "content": "---\nid: fdc3-intro\ntitle: Welcome to FDC3 2.1\nsidebar_label: Introduction\n---\n\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\nFDC3 provides an **open standard for interoperability** between applications on the financial desktop.\n\nThis includes standardized verbs to invoke actions between applications (**intents**), a standardized **context data** format, a REST-based **App Directory** standard, and standardized API operations for a **Desktop Agent**.\n\n## Motivation\n\nFDC3 codifies standard patterns that application developers have been using for cross-application workflows between web and native applications in the financial industry.\n\nFor more information, see [Why FDC3?](why-fdc3)\n\n## Parts of the Standard\n\nThe [Standard](fdc3-standard) currently consists of five complementary parts:\n\n- [API](api/spec)\n- [Intents](intents/spec)\n- [Context Data](context/spec)\n- [App Directory](app-directory/spec)\n- [Agent Bridging](agent-bridging/spec)\n\n## Use Cases\n\nFrom its inception, the standards have been informed by real-world [business use cases](use-cases/overview), which you can view on this website, and form an important part of FDC3.\n\n## Who is using FDC3?\n\nThe Financial Desktop Connectivity and Collaboration Consortium (FDC3) standards are created and used by [leading organizations across the financial industry](/users). For more detail on who's using FDC3, developer tools, training and examples, see the [community page](/community).\n\n## How is FDC3 governed?\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services.\n\n- See the [FDC3 Governance document](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md) for details of how FDC3 is governed.\n- See the [FDC3 Contribution Guide](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for details of how to contribute to FDC3.\n- See the [FDC3 Charter](fdc3-charter#licensing) for details of how deliverables are licensed.\n\n## Where should I go next?\n\n- Have a look at the [supported platforms](supported-platforms) or [common use cases](use-cases/overview).\n- Visit FDC3 [on GitHub](https://github.com/finos/FDC3).\n- Download and install our [npm package](https://www.npmjs.com/package/@finos/fdc3).\n- Try out an FDC3-compliant implementation, e.g. this [browser extension](https://github.com/finos/fdc3-desktop-agent).\n- Join us in the [mailing list](mailto:fdc3+subscribe@finos.org) or on [Slack](https://app.slack.com/client/T01E7QRQH97/C01R0P7H5LH).\n- [Participate](https://github.com/finos/FDC3#getting-involved) in the evolution of the standard.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/fdc3-standard.md",
    "content": "---\nid: fdc3-standard\ntitle: FDC3 2.1\nsidebar_label: Abstract\n--- \n\n**Status:** Superseded  \n_**adopted:** 31st August 2023_  \n_**released:** 14th September 2023_  \n_**superseded:** 1st April 2025_  \n\n## Abstract\n\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of five complementary parts:\n\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain.\n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n- **[Agent Bridging](agent-bridging/spec)**: An [@experimental](fdc3-compliance#experimental-features) API interface for the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can interoperate.\n\n## Versioning\n\nThis Standard defines FDC3 Version 2.1. The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n\nFor more details on FDC3's versioning, deprecation and experimental features policies see the [Compliance page](./fdc3-compliance#versioning).\n\n## Table of Contents\n\n- [Compliance information](fdc3-compliance)\n- [Glossary](fdc3-glossary)\n- [References](references)\n- [Supported Platforms](supported-platforms)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part](app-directory/spec)\n- [Agent Bridging Part](agent-bridging/spec)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/guides/submit-new-intent.md",
    "content": "---\nid: SubmitNewIntent\nsidebar_label: How To Submit New Intent\ntitle: How to Submit a New Intent PR\n---\n\n## Getting Started\n\nPrepare to submit a patch as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch) in CONTRIBUTING.md. Use the issue number and issue title as the branch name, e.g.\n\n```git checkout -b 587-intent-proposal-view-research```\n\nTo install all the necessary packages to run the website locally, change to the website directory and run yarn\n\n```bash\ncd website\nyarn\n```\n\nTo run the website locally\n\n```yarn start```\n\nThis will open the home page or browse to [https://localhost:3000](https://localhost:3000)\n\nNote that the page opens on the current release version of the docs and you will be changing the latest version. Click the version selector in the top left hand corner\n\n![Version Selector](/assets/version_selector.png)\n\nand then select 'Documentation' under 'Latest Version'\n\n![Latest Version Selector](/assets/latest_version_selector.png)\n\nThe 'next' version will be indicated in the header:\n\n![Next Version](/assets/next_version.png)\n\n## Create Intent File\n\nAdd the new intent markdown file to docs/intents/ref. Use one of the existing intent markdown files as a template. E.g. the [ViewResearch](../intents/ref/ViewResearch) intent was created using [ViewProfile](../intents/ref/ViewProfile) as an example:\n\n![View Research](/assets/view_research.png)\n\n## Link to Intent File\n\nAdd links to your Intent File to the following:\n\n- [src/intents/Intents.ts](https://github.com/finos/FDC3/blob/main/src/intents/Intents.ts)\n- [src/intents/standard intents.json](https://github.com/finos/FDC3/blob/main/src/intents/standard%20intents.json)\n- [website/sidebars.json](https://github.com/finos/FDC3/blob/main/website/sidebars.json) (look for the 'Intents' property and the 'ids' property within it)\n\nAt this point your new Intent should appear on the sidebar (you may need to restart yarn to get this).\n\nAlso add to:\n\n- [docs/intents/spec.md](https://github.com/finos/FDC3/blob/main/docs/intents/spec.md) in the 'Standard Intents' section (also add the summary from your Intent page)\n- Any of the Context documents in [docs/context/ref](https://github.com/finos/FDC3/blob/main/docs/context/ref) that are utilized by the Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent, each of the [Contact](../context/ref/Contact), [Instrument](../context/ref/Instrument) and [Organization](../context/ref/Organization) Contexts are valid and so links were added to their Context pages)\n- Any of the Intents documents in [docs/intents/ref](https://github.com/finos/FDC3/blob/main/docs/intents/ref) that are related or relevant to the new Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent a link was added to the [ViewAnalysis](../intents/ref/ViewAnalysis) document)\n\n## Finishing Off\n\nCommit your changes and push as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch). Then submit the branch as a Pull Request (in github, go to the Branches tab and click 'New Pull Request')\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/CreateInteraction.md",
    "content": "---\nid: CreateInteraction\nsidebar_label: CreateInteraction\ntitle: CreateInteraction\nhide_title: true\n---\n# `CreateInteraction`\n\nCreate a record documenting an interaction (calls, meetings, etc.) between a list of contacts.\n\n## Intent Name\n\n`CreateInteraction`\n\n## Display Name\n\n`Create Interaction`\n\n## Possible Contexts\n\n* [ContactList](../../context/ref/ContactList)\n* [Interaction](../../context/ref/Interaction)\n\nSHOULD return context as a result:\n\n* [TransactionResult](../../context/ref/TransactionResult)\n\n## Example\n\n```js\nconst interaction = {\n    type: 'fdc3.interaction',\n    participants: {\n        type: 'fdc3.contactList',\n        contacts: [\n            {\n                type: 'fdc3.contact',\n                name: 'Jane Doe',\n                id: {\n                    email: 'jane.doe@mail.com'\n                }\n             },\n            {\n                type: 'fdc3.contact',\n                name: 'John Doe',\n                id: {\n                    email: 'john.doe@mail.com'\n                }\n            },\n        ]\n    },\n    interactionType: 'Instant Message',\n    timeRange: {\n        type: 'fdc3.timeRange',\n        startTime: '2022-02-10T15:12:00Z'\n    },\n    description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n    initiator:  {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n            email: 'jane.doe@mail.com'\n        }\n    },\n    origin: 'Outlook'\n}\n\nconst intentResolution = await fdc3.raiseIntent('CreateInteraction', interaction);\nconst result = await intentResolution.getResult();\nconsole.log(result);\n```\n\nConsole log will display:\n\n```js\n{\n    type: 'fdc3.transactionResult',\n    status: 'Created',\n    context: {\n        type: 'fdc3.interaction',\n        participants: {\n            type: 'fdc3.contactList',\n            contacts: [\n                {\n                    type: 'fdc3.contact',\n                    name: 'Jane Doe',\n                    id: {\n                        email: 'jane.doe@mail.com'\n                    }\n                 },\n                {\n                    type: 'fdc3.contact',\n                    name: 'John Doe',\n                    id: {\n                        email: 'john.doe@mail.com'\n                    }\n                },\n            ]\n        },\n        interactionType: 'Instant Message',\n        timeRange: {\n            type: 'fdc3.timeRange',\n            startTime: '2022-02-10T15:12:00Z'\n        },\n        description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n        initiator:  {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        origin: 'Outlook'\n        id:  {\n            Singletrack: 'a0S8d000000uO05EAE'\n        }\n    },\n    message: 'record with id \"a0S8d000000uO05EAE\" was created'\n}\n```\n\n## See Also\n\nContext\n- [Interaction](../../context/ref/Interaction)\n- [TransactionResult](../../context/ref/TransactionResult)"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/SendChatMessage.md",
    "content": "---\nid: SendChatMessage\nsidebar_label: SendChatMessage\ntitle: SendChatMessage\nhide_title: true\n---\n# `SendChatMessage`\n\nSend a message to an existing chat room.\n\n## Intent Name\n\n`SendChatMessage`\n\n## Display Name\n\n`Send Chat Message`\n\n## Possible Contexts\n\n* [ChatMessage](../../context/ref/ChatMessage)\n\n## Example\n\n```js\n// Start a chat and retrieve a reference to the chat room created\nconst intentResolution = await fdc3.raiseIntent(\"StartChat\", context);\nconst chatRoom = intentResolution.getResult();\n\n//Some time later\n\nlet chatMessage: ChatMessage = {\n    type: \"fdc3.chat.message\",\n    chatRoom,\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nawait fdc3.raiseIntent(\"SendChatMessage\", context, intentResolution.source);\n```\n\n## See Also\n\nContext\n- [ChatMessage](../../context/ref/ChatMessage)\n- [ChatRoom](../../context/ref/ChatRoom)\n\nIntents\n* [StartChat](StartChat)\n* [StartCall](StartCall)\n* [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/StartCall.md",
    "content": "---\nid: StartCall\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n\n- [StartChat](StartChat)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/StartChat.md",
    "content": "---\nid: StartChat\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\n---\n# `StartChat`\n\nInitiate a chat with a contact, a list of contacts or detailed initialization settings.  This could be launched from within another application. For example initiating a chat from a research or OMS application.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n\n// chat with initialization settings\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Chat ABCD',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane@mail.com'\n            }\n        },{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true\n    }\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nconst resolution = fdc3.raiseIntent('StartChat', initSettings);\n\n// Return a reference to the room\nconst chatRoom = await resolution.getResult();\n```\n\n## See Also\n\nContext\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\nIntents\n\n- [SendChatMessage](SendChatMessage)\n- [StartCall](StartCall)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/StartEmail.md",
    "content": "---\nid: StartEmail\nsidebar_label: StartEmail\ntitle: StartEmail\nhide_title: true\n---\n# `StartEmail`\n\nInitiate an email with a contact or list of contacts provided as part of an Email context.\n\n## Intent Name\n\n`StartEmail`\n\n## Display Name\n\n`Start Email`\n\n## Possible Contexts\n\n- [Email](../../context/ref/Email)\n\n## Example\n\n```js\nwindow.fdc3.raiseIntent('fdc3.StartEmail', {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n})\n```\n\n## See Also\n\nContext\n\n- [Email](../../context/ref/Email)\n\nIntents\n\n- [StartCall](StartCall)\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewAnalysis.md",
    "content": "---\nid: ViewAnalysis\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewChart.md",
    "content": "---\nid: ViewChart\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\n---\n# `ViewChart`\n\nDisplay a chart for the provided context.\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n## Example\n\nRequest a chart for an instrument:\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\nRequest a specific chart:\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: {\n        indicators: [\n            {\n                name: \"ma\",\n                parameters: {\n                    period: 14,\n                    type: \"ema\"\n                }\n            },\n            {\n                name: \"volume\"\n            }\n        ]\n    }\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nContext\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewQuote](ViewQuote)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewChat.md",
    "content": "---\nid: ViewChat\nsidebar_label: ViewChat\ntitle: ViewChat\nhide_title: true\n---\n# `ViewChat`\n\nOpen an existing chat room.\n\n## Intent Name\n\n`ViewChat`\n\n## Display Name\n\n`View Chat`\n\n## Possible Contexts\n\n* [ChatRoom](../../context/ref/ChatRoom)\n* [Contact](../../context/ref/Contact): It will open the **direct** chat where there is the current user and the contact\n* [ContactList](../../context/ref/ContactList): It will open the **room** where there is the current user and the listed contacts. Contact List may need to display search results if there are multiple matches.\n\n## Output\n\nThis intent returns as output:\n* If the chat doesn't exist, will display a modal to create a chat\n* if the chat gets created, return its ChatRoom context\n* if none is created return void\n\n## Example: ChatRoom\n\n```js\nconst chatRoom = {\n    type: 'fdc3.chat.room',\n    providerName: \"Symphony\",\n    id: {\n        streamId: \"j75xqXy25NBOdacUI3FNBH\"\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', chatRoom);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## Example: Contact\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contact);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the direct chat was found\n```\n\n## Example: ContactList\n\n```js\nconst contacts = {\n    type: 'fdc3.contactList',\n    contacts: [\n        {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john.doe@mail.com'\n            }\n        },\n    ]\n}\n\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contacts);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## See Also\n\nContext\n\n* [ChatRoom](../../context/ref/ChatRoom)\n* [Contact](../../context/ref/Contact)\n* [ContactList](../../context/ref/ContactList)\n\nIntents\n\n* [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewContact.md",
    "content": "---\nid: ViewContact\nsidebar_label: ViewContact (deprecated)\ntitle: ViewContact\nhide_title: true\n---\n# `ViewContact`\n\n:::caution\nViewContact has been deprecated in FDC3 2.0 in favour of the more general [ViewProfile](ViewProfile) intent.\n:::\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n\nIntents\n\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewHoldings.md",
    "content": "---\nid: ViewHoldings\nsidebar_label: ViewHoldings\ntitle: ViewHoldings\nhide_title: true\n---\n# `ViewHoldings`\n\nDisplay any holdings for the provided instrument, list of instruments, or organization.\n\n## Intent Name\n\n`ViewHoldings`\n\n## Display Name\n\n`View Holdings`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewHoldings', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewInstrument](ViewInstrument)\n- [ViewAnalysis](ViewAnalysis)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewInstrument.md",
    "content": "---\nid: ViewInstrument\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewInteractions.md",
    "content": "---\nid: ViewInteractions\nsidebar_label: ViewInteractions\ntitle: ViewInteractions\nhide_title: true\n---\n# `ViewInteractions`\n\nDisplay interactions (calls, meetings, etc.) related to an individual, an instrument or organization provided as context.\n\n## Intent Name\n\n`ViewInteractions`\n\n## Display Name\n\n`View Interactions`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewInteractions', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewProfile](ViewProfile)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewMessages.md",
    "content": "---\nid: ViewMessages\nsidebar_label: ViewMessages\ntitle: ViewMessages\nhide_title: true\n---\n# `ViewMessages`\n\nSearch and display a list of messages (for example in a chat application or CRM) to the user. \n\n## Intent Name\n\n`ViewMessages`\n\n## Display Name\n\n`View Messages`\n\n## Possible Contexts\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n\n## Example\n\nRequest display of messages relating to a specific `fdc3.instrument` (representing a ticker):\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.contact`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.organization`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific **phrase**:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages matching _multiple_ criteria:\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        },\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\n## See Also\n\nContext\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n* [Instrument](../../context/ref/Instrument)\n* [Contact](../../context/ref/Contact)\n* [Organization](../../context/ref/Organization)\n\nIntents\n\n* [ViewChat](ViewChat)"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewNews.md",
    "content": "---\nid: ViewNews\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'IBM'\n    },\n    market: {\n        MIC: \"XNYS\"\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewOrders.md",
    "content": "---\nid: ViewOrders\nsidebar_label: ViewOrders\ntitle: ViewOrders\nhide_title: true\n---\n# `ViewOrders`\n\nDisplay any orders related to the provided contact, instrument, or organization.\n\n## Intent Name\n\n`ViewOrders`\n\n## Display Name\n\n`View Orders`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewOrders', instrument)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInstrument](ViewInstrument)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewProfile.md",
    "content": "---\nid: ViewProfile\nsidebar_label: ViewProfile\ntitle: ViewProfile\nhide_title: true\n---\n# `ViewProfile`\n\nDisplay basic profile information for the individual or organization provided as context.\n\n## Intent Name\n\n`ViewProfile`\n\n## Display Name\n\n`View Profile`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewProfile', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInteractions](ViewInteractions)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewQuote.md",
    "content": "---\nid: ViewQuote\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\n---\n# `ViewQuote`\n\nDisplay pricing for an [Instrument](../../context/ref/Instrument).\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/ref/ViewResearch.md",
    "content": "---\nid: ViewResearch\nsidebar_label: ViewResearch\ntitle: ViewResearch\nhide_title: true\n---\n# `ViewResearch`\n\nShow research related to an instrument, an individual or organization provided as context.\n\n## Intent Name\n\n`ViewResearch`\n\n## Display Name\n\n`View Research`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewResearch', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/intents/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Intents Overview (2.1)\n---\n\nFDC3 Intents define a standard set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n\n- Applications register the intents and [context data](../context/spec) combinations they support in the [App Directory](../app-directory/spec).\n- The App Directory supports application discovery by intents and/or context data.\n- Intents are not full RPC, apps don’t need to enumerate every function with an intent.\n- FDC3 standard intents are a limited set, organizations can create their own intents.\n\n## Naming Conventions\n\nNaming of Intents SHOULD follow the below guidelines:\n\n- Intent names should be free of non-alphanumeric characters.\n- ‘.’ will be used to namespace the intent (see below).\n- Intent names should be in UpperCamelCase.\n\n:::note\nThe naming guidelines should be adhered to when creating future Intents.  This is to ensure they meet the criteria for addition to the FDC3 standard and to provide a consistent user experience.\n:::\n\n### Characteristics\n\nWhen creating Intents they should be:\n\n- Recognizable\n  - Generally self-evident what the thing is\n- Repeatable\n  - Many instances across the industry\n- Stateless\n  - Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n- Specific\n  - Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n- Distinct\n  - Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces\n\nAll standard intent names are reserved. Applications may use their own intents ad hoc.\nHowever, there is occasionally a need for applications to ensure that their intents avoid collision, for example, where a workflow is highly specific to or internal to an application. The recommended approach is to namespace the intent with the application name. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary intent.\n\n### Intent Name Prefixes\n\nEarly versions of the FDC3 standard included 8 intents, which used one of two different prefixes ( `View___` and `Start___`) that are focused on UI interactions.  The prefixes are used to help define the expected behavior of an app when resolving an intent with that prefix. The list of intent name prefixes was expanded in FDC3 2.0 to include prefixes that indicate that CRUD operations should be performed on data.\n\n#### `View___`\n\n- Expected behavior: Content should be displayed to the user.\n\n#### `Start___`\n  \n- Expected behavior: An interaction, such as a chat room or email thread, should be initiated.\n\nAs more use cases were identified it was clear further Intents were required.  FDC3 2.0 expanded this set to include the following:\n\n#### `Create___`\n\n- Expected behavior: A new record or entity should be created. The operation should fail if it already exists.\n\n#### `Update___`\n\n- Expected behavior: An existing record or entity should be updated. The operation should fail if it does not exist.\n\n#### `CreateOrUpdate___`\n\n- Expected behavior: A new record or entity should be created, or an existing one updated if it exists.\n\n#### `Delete___`\n\n- Expected behavior: An existing record or entity should be deleted. The operation should fail if it does not exist.\n\n#### `Get___`\n\n- Expected behavior: A record or entity should be retrieved and returned as an intent result. The operation should fail if the record does not exist.\n\n#### `Share___`\n\n- Expected behavior: A record or entity should shared. The operation should fail if it does not exist\n\n## Using Intents\n\nCombined with [context data](../context/spec) and [App Directory](../app-directory/overview) standards, intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.contact\",\n  name: \"Jane Doe\",\n  id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n\n## Intents that return data\n\nFrom FDC3 2.0, intents raised through the Desktop Agent API may return results in the form of a `Context` object or a `Channel`. Where an intent implements a transaction with another application, for example for a CRUD operation, the [`fdc3.transactionResult` context type](../context/ref/TransactionResult) SHOULD be used to provide a result status for the transaction and may wrap a context object that would otherwise be returned.\n\nFor more details on retrieving a result from a raised intent, see the [documentation for `raiseIntent`](../api/ref/DesktopAgent#raiseintent).\n\n## Intents Standard Compliance\n\nAn FDC3 Standard compliant application that supports intents **MUST**:\n\n- Meet the expected context and behavior defined for any FDC3-defined standard intents used.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) after it is launched. This facilitates delivery of raised intents to the application.\n\nAn FDC3 Standard compliant application that supports intents **SHOULD**:\n\n- Prefer FDC3-defined standard intents over proprietary intents, where a suitable standardized intent is available.\n- Ensure that proprietary intents follow the recommended naming conventions in the specification.\n- Apply [namespacing](#namespaces) to proprietary intent names, where it is necessary to avoid collision with those created by other applications.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n- Use the `fdc3.transactionResult` context type to return a status for any transactions relating to CRUD operations.\n\nAn FDC3 Standard compliant application that supports intents **MAY**:\n\n- Define proprietary intents to support use cases not currently supported via FDC3-defined standard intents.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Intents\n\nA list of standardized intents are defined in the following pages:\n\n* [`CreateInteraction`](ref/CreateInteraction)\n* [`StartCall`](ref/StartCall)\n* [`StartChat`](ref/StartChat)\n* [`StartEmail`](ref/StartEmail)\n* [`ViewAnalysis`](ref/ViewAnalysis)\n* [`ViewChat`](ref/ViewChat)\n* [`ViewChart`](ref/ViewChart)\n* [`ViewHoldings`](ref/ViewHoldings)\n* [`ViewInstrument`](ref/ViewInstrument)\n* [`ViewInteractions`](ref/ViewInteractions)\n* [`ViewMessages`](ref/ViewMessages)\n* [`ViewNews`](ref/ViewNews)\n* [`ViewOrders`](ref/ViewOrders)\n* [`ViewProfile`](ref/ViewProfile)\n* [`ViewQuote`](ref/ViewQuote)\n* [`ViewResearch`](ref/ViewResearch)\n\n### Deprecated Intents\n\n- [`ViewContact`](ref/ViewContact)\n\n## Using Intents without a context\n\nAs the [Desktop Agent API](../api/ref/DesktopAgent) and [App Directory](../app-directory/overview) both require a context to be specified wherever intents are used, using an intent without a context is achieved through the use of the explicit `null` context type [`fdc3.nothing`](../context/ref/Nothing). By using an explicit type to represent an absence of context we allow applications to declare their support for an absence of context.\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.nothing\",\n});\n\nconst result = await fdc3.raiseIntent(\"StartChat\", {\n  type: \"fdc3.nothing\"\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/references.md",
    "content": "---\nid: references\ntitle: References & Bibliography\nsidebar_label: References\n---\n\n\nThe following normative documents contain provisions, which, through reference in this text, constitute provisions of this Standard. For dated references, subsequent amendments to, or revisions of, any of these publications do not apply. However, parties to agreements based on this Standard are encouraged to investigate the possibility of applying the most recent editions of the normative documents indicated below. For undated references, the latest edition of the normative document referred to applies:\n\n- **Apache 2.0 open-source license**, [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0).\n- **Community Specification license**, [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0)\n- **ISO 3166-1**, _Codes for the representation of names of countries and their subdivisions – Part 1: Country codes_, [https://www.iso.org/iso-3166-country-codes.html](https://www.iso.org/iso-3166-country-codes.html).\n- **ISO 8601-1:2019**, _Date and time — Representations for information interchange — Part 1: Basic rules_, [https://www.iso.org/standard/70907.html](https://www.iso.org/standard/70907.html)\n- **JSON Schema**, [https://json-schema.org/](https://json-schema.org/).\n- **OpenAPI Standard v3.0**, [https://www.openapis.org/](https://www.openapis.org/).\n- **quicktype**, [https://quicktype.io/](https://quicktype.io/).\n- **RFC 2119**, _Keywords for use in RFCs to Indicate Requirement Levels, March 1997_, [https://datatracker.ietf.org/doc/html/rfc2119](https://datatracker.ietf.org/doc/html/rfc2119).\n- **RFC 2782**, _A DNS RR for specifying the location of services (DNS SRV), February 2000_, [https://datatracker.ietf.org/doc/html/rfc2782](https://datatracker.ietf.org/doc/html/rfc2782).\n- **RFC 4122**, _A Universally Unique IDentifier (UUID) URN Namespace, July 2005_, [https://datatracker.ietf.org/doc/html/rfc4122](https://datatracker.ietf.org/doc/html/rfc4122).\n- **RFC 5646**, _Tags for Identifying Languages, September 2009_, [https://datatracker.ietf.org/doc/html/rfc5646](https://datatracker.ietf.org/doc/html/rfc5646).\n- **TypeScript Programming Language**, [https://www.typescriptlang.org/](https://www.typescriptlang.org/).\n- **Web Application Manifest**, _W3C Working Draft_, February 2022 [https://www.w3.org/TR/appmanifest/](https://www.w3.org/TR/appmanifest/)\n\nThe following documents may be useful in understanding certain aspects of this Standard; however, knowledge of them is not essential to the creation of a compliant implementation of this Standard:\n\n- **CUSIP**, _Committee on Uniform Security Identification Procedures_, [https://www.cusip.com/identifiers.html#/CUSIP](https://www.cusip.com/identifiers.html#/CUSIP).\n- **FIGI**, _Financial Instrument Global Identifier_, [https://www.openfigi.com/about/figi](https://www.openfigi.com/about/figi).\n- **ISIN**, _International Securities Identification Number_, [https://www.isin.org/isin/](https://www.isin.org/isin/)\n- **LEI**, _Legal Entity Identifier based on the ISO 17442 standard_, [https://www.legalentityidentifier.co.uk/what-is-lei-code/](https://www.legalentityidentifier.co.uk/what-is-lei-code/).\n- **npm**,  [https://docs.npmjs.com/about-npm](https://docs.npmjs.com/about-npm).\n- **PermID**, _Permanent Identifiers_, [https://permid.org/](https://permid.org/).\n- **pnpm**, [https://pnpm.io/motivation](https://pnpm.io/motivation).\n- **REST**, [https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm), [https://restfulapi.net/](https://restfulapi.net/).\n- **SEDOL**, _Stock Exchange Daily Official List_, [https://www.lseg.com/sedol](https://www.lseg.com/sedol).\n- **yarn**, [https://yarnpkg.com/getting-started](https://yarnpkg.com/getting-started).\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/supported-platforms.md",
    "content": "---\nid: supported-platforms\ntitle: Supported Platforms\n---\n\nFDC3 is platform- and programming language-independent. An FDC3-capable platform requires a Desktop Agent that supports the FDC3 standard, and that agent is responsible for coordinating application interactions.\n\nThere are two main categories of platform: web and native, both of which are described below. There exists a third category, hybrid, where a web application runs within the context of a standalone native application via a web view.\n\n## Web\n\nFor a web application to be FDC3-enabled, it needs to run in the context of an environment or **_Platform Provider_** that makes the FDC3 API available to the application. This environment could be a browser extension, a web or native app, or a fully-fledged desktop container framework.\n\n### Usage\n\nThere are two main ways FDC3 can be used from web applications:\n\n#### 1. Direct Usage\n\nSimply rely on the global object being made available by your desktop agent, and address the API directly:\n\n```javascript\nfunction sendData() {\n  window.fdc3.broadcast({\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n  })\n}\n\nif (window.fdc3) {\n  sendData();\n} else {\n  window.addEventListener(\"fdc3Ready\", sendData);\n}\n```\n\n#### 2. NPM Wrapper\n\nFDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can by used by web applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n<Tabs>\n<TabItem value=\"npm\" label=\"npm\">\n\n```bash\nnpm install @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"yarn\" label=\"yarn\">\n\n```bash\nyarn add @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"pnpm\" label=\"pnpm\">\n\n```bash\npnpm install @finos/fdc3\n```\n\n</TabItem>\n</Tabs>\n\nThe npm package provides a wrapper around FDC3, allowing you to use it with ES6 import syntax:\n\n```javascript\nimport * as fdc3 from '@finos/fdc3';\n\nawait fdc3.raiseIntent('ViewAnalysis', {\n    type: 'fdc3.instrument',\n    id: { ticker: 'AAPL' }\n});\n```\n\nIt also includes a helper function you can use to wait for FDC3 to become available:\n\n```javascript\nimport { fdc3Ready, addIntentListener } from '@finos/fdc3'\n\nawait fdc3Ready();\n\nconst listener = await addIntentListener('ViewAnalysis', instrument => {\n  // handle intent\n});\n```\n\n**See also:**\n\n- [`fdc3Ready() Function`](api/ref/Globals#fdc3ready-function)\n\n## Native\n\nThe FDC3 Standard does not currently define wire formats for an app to communicate with a Desktop Agent, nor does it define language specific API bindings, other than JavaScript and TypeScript. Hence, for a native application to be FDC3-enabled, it needs to either:\n\n- Make use of a shared library (such as a .NET DLL or JAR file) that provides it with an implementation of the FDC3 API (which ties it to a specific desktop agent implementation).\n- Model itself as a Desktop Agent (rather than just an app working with one) and use the Agent Bridging protocol to connect to a Desktop Agent Bridge and work through it to interoperate with apps managed by other Desktop Agents.\n\n## Hybrid\n\nIn a hybrid application, a standalone native application incorporates a web view, within which a web application runs. This may be considered a special case of the web platform where all platform-provider requirements for web applications must be satisfied, but it is the responsibility of the associated native application, rather than a platform provider, to ensure they are fulfilled. This may be achieved, for example, by injecting an implementation of the DesktopAgent API and ensuring that it is accessible at the usual location, `window.fdc3`.\n\n## Compliance\n\nSupport for each platform is optional and compliance with the FDC3 standard should be assessed for each platform implemented independently of any other, with the exception of ensuring that where applications running on multiple platforms are used together, communication between them still complies with the standard.\n\nThe Web API binding is expressed using TypeScript syntax that defines the API interface (for both TypeScript and JavaScript). Adherence to the specific binding is required for Web application platforms. No specific API binding for native platforms is currently expressed in the Standard. Hence, native applications may be implemented with any programming language binding that supports the constructs required by the API specification, until such time that the FDC3 Standard introduces an appropriate language-specific binding.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/trademarks.md",
    "content": "---\nid: trademarks\ntitle: Trademarks\n---\n\nThe trademarks, logos, and service marks not owned on behalf of FDC3 and FINOS and that are displayed on the Site are the registered and unregistered marks of their respective owners. No rights are granted by the FDC3 or FINOS to use such marks, whether by implication, estoppel, or otherwise.\n\nTrademarks used within this site and the FDC3 Standard include, but are not limited to:\n\n- Autobahn is a registered trademark of DEUTSCHE BANK AG, LONDON\n- Chromium is a trademark of Google LLC\n- Eikon is a registered trademark of Refinitiv\n- FDC3 is a registered trademark and brand of The Linux Foundation\n- Excel is a Microsoft Corporation product name\n- Finsemble is a registered trademark and product name of interop.io, Inc.\n- Glue42 is a trademark and product name of interop.io, Inc.\n- io.Connect is a trademark and product name of interop.io, Inc.\n- Java is a registered trademark of Oracle America, Inc.\n- JavaScript  is a registered trademark of Oracle America, Inc.\n- .NET is a trademark of Microsoft Corporation\n- npm is a trademark of npm, Inc.\n- OpenFin is a registered trademark of OpenFin Inc.\n- Outlook is a registered trademark of Microsoft Corporation\n- Python is a registered trademark of the Python Software Foundation\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\n---\n\n## Preconditions\nOn their desktop, this user has:\n- Their firm's internal research & analytics platform containing liquidity tools and internal research. The product is running and the liquidity tool is open\n- An installed chat application - product is running\n- A third party market data terminal with 3 open applications. These applications are all 'linked' through a channel. \n    - A Watchlist\n    - An Order Book\n    - An Overview of pricing and fundamental data\n- A third party Charting Application access via a browser window. This is not open. \n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/009-call-transcription-to-crm.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Call Transcription to CRM\"\nsidebar_label: 9. Call Transcription to CRM\nlayout: use_case\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/010-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Real-Time voice trades -> trade ticket population\"\nsidebar_label: \"10. Real-Time voice trades -> trade ticket population\"\nlayout: use_case\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/013-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-13\ntitle: \"Use Case 13: User launches multiple apps from a single container\"\nsidebar_label: 13. User launches multiple apps from a single container\nlayout: use_case\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/015-sales-floor-base-workflow.md",
    "content": "---\nid: uc-15\ntitle: \"Use Case 15: Sales Floor Base Workflow\"\nsidebar_label: 15. Sales Floor Base Workflow\nlayout: use_case\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/016-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-16\ntitle: \"Use Case 16: Quantifying FDC3 Interactions\"\nsidebar_label: 16. Quantifying FDC3 Interactions\nlayout: use_case\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/017-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-17\ntitle: \"Use Case 17: Fine-tuning InterOp with Channels\"\nsidebar_label: 17. Fine-tuning InterOp with Channels\nlayout: use_case\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/meeting-minutes/2020-01-16 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n\n\n## Agenda\n### 1. 2020 Move to GitHub - JT (15 min)\n- Goal: manage all new UCWG content in GitHub in 2020\n\n**Proposal:** how to manage the UCWG content \n- Meeting Minutes \n  - legacy [keep them on confluence and link to them] AGREED - link to be added\n  - new [in github, [this folder](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases/meeting-minutes), we also could create a GitHub Issue template] AGREED - link to be updated\n- Governance Docs [to be refreshed and moved to the [use cases intro](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/use-cases-intro.md) page]  - AGREED to move to intro doc, but need to be reviewed and cleaned up. \n  - Ratifying use cases via GitHub PRs - voting done via GitHub (👍 / 👎 on an issue - see [UC 17](https://github.com/finos/FDC3/pull/153)) rather than Google Groups - AGREED \n- Use Cases \n  - 1. In Review [will be managed via submitted pull requests - see [this](https://github.com/finos/FDC3/pulls?q=is%3Aopen+is%3Apr+label%3Ause-cases)]\n  - 2. Accepted [DONE - listed [here](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases)]\n  - 3. Rejected \n  - 4. Deleted \n  - 5. Backlog \n  - Use Case XX: Template [we can create this as a github issue type] - JT to try and prove this works\n- Action Items \n  - to be reviewed and closed out. Relevant ones will be migrated. \n- Process: \n  - One of the participants edits meeting minutes live on a screenshare during the call. All participants on the call review and approve the minutes at the end of the call. Once approved verbally on the call, the meeting minutes PR can be merged. \n\n### 2. UC 17 Vote - Johan (5 min)\n- Voting directly on the PR: https://github.com/finos/FDC3/pull/153\n- APPROVED AND MERGED!\n\n### 3. UCWG Goals and Roadmap - JT (15 min)\n- see proposal [here](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/fdc3-okrs.md#use-case-working-group)\n- UCWG to review offline and comment\n\n### 4. AOB \n- lean UCWG + new recruits\n- clean up open action items in confluence\n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/meeting-minutes/2020-02-20 uc-wg meeting notes.md",
    "content": "---\n\n---\n\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n| Leslie Spiro | Tick42 |  |\n\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/meeting-minutes/2020-03-19 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Meeting not held due to low attendance**\n\n**Date**: 19 March 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/overview.md",
    "content": "---\nid: overview\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-2.1/use-cases/readme.md",
    "content": "---\n\n---\n# Overview \nHere are business use cases that have been documented and ratified by the Use Cases Working Group\n\n# Adoption of Use Cases into the FDC3 Standard\n\n**Use Cases Accepted onto Roadmap of Standards or Implemented**\n\n| Use Cases                                                           | Count         | %       |\n| -------------                                                       |:-------------:| :----:  |\n| 001-equity-sell-side-trader                                         | \t2 / 5       |   40%   | \n| 002-buy-side-portfolio-manager                                      | \t0 / 3\t      |   33%   | \n| 003-inhouse-cross-platform-launcher                                 | \t0 / 8       |    0%   | \n| 004-client-side-fx-trader                                           | \t0 / 1\t      |    0%   | \n| 005-buy-side-treasurer                                              | \t0 / 3\t      |    0%   | \n| 009-call-transcription-to-crm                                       | \t0 / 2\t      |    0%   | \n| 010-realtime-trade-ticket-population                                | \t0 / 1\t      |    0%   | \n| 013-user-launches-multiple-apps-from-a-single-container             | \t0 / 3\t      |    0%   | \n| 015-sales-floor-base-workflow                                       | \t0 / 2\t      |    0%   | \n| 016-quantifying-fdc3-interactions                                   | \t0 / 3\t      |    0%   | \n| total                                                               | \t2 / 31      |  6.5%   | \n\n\n\n**Summary**\n\n| Status                                | Count         | %       |\n| -------------                         |:-------------:| :----:  |\n| New                                   | \t24\t        |   77.5%   | \n| Proposed                              | \t5           | \t16%   | \n| **Accepted onto Roadmap of Standard** | \t0           | \t**0%**  | \n| **Implemented**                       | \t2         \t|  **6.5%** | \n| Rejected                              | \t0           | \t0%    | \n| N/R                                   | \t3           |         | \t\n| Total (excl. N/R)                     | \t31          | \t100%  | \n"
  },
  {
    "path": "website/versioned_docs/version-2.1/why-fdc3.md",
    "content": "---\nid: why-fdc3\nsidebar_label: Why FDC3?\ntitle: Why FDC3?\n---\n\n## Why look for FDC3-enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go.\n\nThe main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3-enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context).\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still, much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc..\n\nEvery application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3-enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3-enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration. With an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/.markdownlint.jsonc",
    "content": "{\n\t//Disabled as we often use manual H1 heading for reference pages, \n\t// where the markdown metadata is picked up as the top level heading\n\t\"single-h1\": false,\n\t//Many lines in md files are longer than 80 chars\n\t\"line-length\": false,\n\t//We have repeated headings, like 'Properties' or 'Fields' in reference docs.\n\t\"no-duplicate-header\": {\n\t\t\"siblings_only\": true\n\t},\n\t\"no-inline-html\": {\n\t\t\"allowed_elements\": [\n\t\t\t\"Tabs\",\n\t\t\t\"TabItem\"\n\t\t]\n\t},\n\t\"ul-style\": {\n\t\t\"style\": \"dash\"\n\t}\n}"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.broadcast.md",
    "content": "---\nid: PrivateChannel.broadcast\nsidebar_label: PC.broadcast\ntitle: PrivateChannel.broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast` API call on a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.broadcast(context: Context)`](../../api/ref/Channel#broadcast) (inherited from the [Channel](../../api/ref/Channel#broadcast) class)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.broadcast()\n    DA ->> DAB: PrivateChannel.broadcast\n    DAB ->> DB: PrivateChannel.broadcast\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelBroadcastAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelBroadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelBroadcastBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelBroadcastBridgeRequest.schema.json)\n\n### Example\n\n```javascript\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const privateChannel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = privateChannel.onAddContextListener((contextType) => {\n        // broadcast price quotes as they come in from our quote feed\n        feed.onQuote(symbol, (price) => {\n            privateChannel.broadcast({ type: \"price\", price});\n        });\n    });\n\n    ...\n\n    return channel;\n});\n```\n\nBroadcast messages that are sent from Agents that received the private channel from a remote agent are sent to the Desktop Agent that created the channel and returned it as an `IntentResult`, which is responsible for forwarding them onto other subscribers. If a broadcast message is generated on the Agent that created the channel it simply forwards it onto each subscriber.\n\nHence, the broadcast message should be repeated once for each subscriber, and modified such that it includes a destination, specified as a full `AppIdentifier`, and the `type` should indicate that it is a `PrivateChannel` broadcast:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.broadcast\", //modified type for PrivateChannel broadcasts\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.eventListenerAdded.md",
    "content": "---\nid: PrivateChannel.eventListenerAdded\nsidebar_label: PC.eventListenerAdded\ntitle: PrivateChannel.eventListenerAdded\n---\n\nDesktop Agent bridging message exchange for the addition of an event handler to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`PrivateChannel.onAddContextListener(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onaddcontextlistener)\n- [`PrivateChannel.onUnsubscribe(handler: (contextType?: string) => void): Listener`](../../api/ref/PrivateChannel#onunsubscribe)\n- [`PrivateChannel.onDisconnect(handler: () => void): Listener`](../../api/ref/PrivateChannel#ondisconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application adds one of these event listeners to a private channel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel to facilitate routing of event messages. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: adds an event listener\n    DA ->> DAB: PrivateChannel.eventListenerAdded\n    DAB ->> DB: PrivateChannel.eventListenerAdded\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerAddedAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelEventListenerAddedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelEventListenerAddedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerAdded\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.eventListenerRemoved.md",
    "content": "---\nid: PrivateChannel.eventListenerRemoved\nsidebar_label: PC.eventListenerRemoved\ntitle: PrivateChannel.eventListenerRemoved\n---\n\nDesktop Agent bridging message exchange for the removal of an event handler from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe(): void`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) functions:\n    - [`onAddContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onaddcontextlistener)\n    - [`onUnsubscribe(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/PrivateChannel#onunsubscribe)\n    - [`onDisconnect(handler: () => void): Promise<Listener>`](../../api/ref/PrivateChannel#ondisconnect)\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nPrivate channels support a number of additional event listeners (`onAddContextListener`, `onUnsubscribe`, `onDisconnect`), when an application removes an event listener from a PrivateChannel that was created remotely and returned as an `IntentResult` (which should be tracked by the Desktop Agent Bridge client) a message needs to be sent to the agent that created the channel so it can discard retained routing information. A single message type is used for this with a `payload.listenerType` field.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: removes an event listener\n    DA ->> DAB: PrivateChannel.eventListenerRemoved\n    DAB ->> DB: PrivateChannel.eventListenerRemoved\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelEventListenerRemovedAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelEventListenerRemovedBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.eventListenerRemoved\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"listenerType\": \"onAddContextListener\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.onAddContextListener.md",
    "content": "---\nid: PrivateChannel.onAddContextListener\nsidebar_label: PC.onAddContextListener\ntitle: PrivateChannel.onAddContextListener\n---\n\nDesktop Agent bridging message exchange for the addition of a [`ContextHandler`](../../api/ref/Types#contexthandler) to a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is added to a `PrivateChannel` any applications that have added an `onAddContextListener` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.addContextListener()\n    DA ->> DAB: PrivateChannel.onAddContextListener\n    DAB ->> DB: PrivateChannel.onAddContextListener\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnAddContextListenerAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnAddContextListenerBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onAddContextListener\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.onDisconnect.md",
    "content": "---\nid: PrivateChannel.onDisconnect\nsidebar_label: PC.onDisconnect\ntitle: PrivateChannel.onDisconnect\n---\n\nDesktop Agent bridging message exchange for a `disconnect()` API call on  [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API call:\n\n- [`PrivateChannel.disconnect(): void`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen the `disconnect` function is is called on a `PrivateChannel` any applications that have added an `onDisconnect` handler or an `onUnsubscribe` handler (which is automatically called when an application disconnects) MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information. If the `PrivateChannel` was created by a remote agent, only the single `PrivateChannel.onDisconnect` is required. It is the responsibility of the Desktop Agent that created the channel to ensure that any relevant `onUnsubscribe` handlers are also called by sending additional `PrivateChannel.onUnsubscribe` messages to them before forwarding the `PrivateChannel.onDisconnect`. This applies whether the disconnection occurred on that agent or on a remote agent.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: privateChannel.disconnect()\n    DA ->> DAB: PrivateChannel.onDisconnect\n    DAB ->> DB: PrivateChannel.onDisconnect\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnDisconnectAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnDisconnectAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnDisconnectBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnDisconnectBridgeRequest.schema.json)\n\n### Example\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"PrivateChannel.onDisconnect\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/PrivateChannel.onUnsubscribe.md",
    "content": "---\nid: PrivateChannel.onUnsubscribe\nsidebar_label: PC.onUnsubscribe\ntitle: PrivateChannel.onUnsubscribe\n---\n\nDesktop Agent bridging message exchange for the removal of a [`ContextHandler`](../../api/ref/Types#contexthandler) from a [`PrivateChannel`](../../api/ref/PrivateChannel). Generated by API calls:\n\n- [`listener.unsubscribe()`](../../api/ref/Types#listener)\n  - for [`Listener`](../../api/ref/Types#listener) objects returned by [`PrivateChannel`](../../api/ref/PrivateChannel) function:\n    - [`addContextListener(handler: (contextType?: string) => void): Promise<Listener>`](../../api/ref/Channel#addcontextlistener) (inherited from `Channel`)\n- [`PrivateChannel.disconnect()`](../../api/ref/PrivateChannel#disconnect)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\n:::caution\n\nSome additional tracking of PrivateChannel metadata is required on the Desktop Agent that created each PrivateChannel and on any Desktop Agent interacting with it, in order to use these message exchanges. Please see the [relevant section of the Agent Bridging overview](../spec#privatechannels) for more details.\n\n:::\n\nWhen a `ContextListener` is removed from a `PrivateChannel` (via `listener.unsubscribe`) any applications that have added an `onSubscribe` handler MUST be notified. If the listener is on the agent that created that channel, it should forward the message onto all the registered listeners. If the listener is added on a remote agent it MUST send the message to the agent that created the channel which will repeat it onto the other listeners without modifying the source information.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: listener.unsubscribe()\n    DA ->>+ DAB: PrivateChannel.onUnsubscribe\n    DAB ->>+ DB: PrivateChannel.onUnsubscribe\n```\n\n### Request message schemas\n\n### Schema\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnUnsubscribeAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/privateChannelOnUnsubscribeBridgeRequest.schema.json)\n\n### Example\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"PrivateChannel.onUnsubscribe\",\n    \"payload\": {\n        \"channelId\": \"private-channel-ABC123\",\n        \"contextType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AnotherApp\",\n            \"instanceId\": \"02e235ba-acad-4b66-4c3a-547073be23f1\",\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        },\n        \"destination\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\"\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/broadcast.md",
    "content": "---\nid: broadcast\nsidebar_label: broadcast\ntitle: broadcast\n---\n\nDesktop Agent bridging message exchange for a `broadcast()` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent) or a [`Channel`](../../api/ref/Channel). Generated by API calls:\n\n- [`fdc3.broadcast(context: Context): Promise<void>`](../../api/ref/DesktopAgent#broadcast)\n- [`Channel.broadcast(context: Context): Promise<void>`](../../api/ref/Channel#broadcast)\n\n:::caution\n\nBroadcasts on a [`PrivateChannel`](../../api/ref/PrivateChannel) have a separate message exchange, see [`PrivateChannel.broadcast`](PrivateChannel.broadcast).\n\n:::\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request only**\n\nE.g.\n\n```javascript\nfdc3.broadcast(contextObj);\n```\n\nor\n\n```javascript\n(await fdc3.getOrCreateChannel(\"myChannel\")).broadcast(contextObj)\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.broadcast() / channel.broadcast()\n    DA ->> DAB: broadcastRequest\n    DAB ->> DB: broadcastRequest\n    DAB ->> DC: broadcastRequest\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/broadcastAgentRequest.schema.json](pathname:///schemas/2.2/bridging/broadcastAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/broadcastBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/broadcastBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/ }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2022-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nwhich it repeats on to agent-B AND agent-C with the `source.desktopAgent` metadata added.\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"broadcastRequest\",\n    \"payload\": {\n        \"channelId\": \"myChannel\",\n        \"context\": { /*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/findInstances.md",
    "content": "---\nid: findInstances\nsidebar_label: findInstances\ntitle: findInstances\n---\n\nDesktop Agent bridging message exchange for a `findInstances` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>`](../../api/ref/DesktopAgent#findinstances)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)** or **Request Response (single)**\n\nA Desktop Agent's [`findInstances`](../../api/ref/DesktopAgent#findinstances) API call should return an empty array for known applications and [`ResolveError.NoAppsFound`](../../api/ref/Errors#resolveerror) for unknown apps. Hence, if a findInstances request is received through bridging for a known app with no instances then a normal response should be returned with an empty array. The bridge should add the responding agent to the `sources` array in the collated response as this is a valid response. If the application is not known to the agent an error response should be used instead with the `ResolveError.NoAppsFound` message and the responding Desktop Agent should be added to the `meta.errorSources` of the bridge response.\n\nIn the event that all agents returned an error response, then the bridge will also return an error response, which is passed back to the calling application. However, if any agent returned a valid response (including with an empty array) then the application was known, but had no instances, resulting in an empty array being returned to the calling application.\nE.g.\n\n```javascript\n// Retrieve a list of all instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Retrieve a list of instances of an application on a specified Desktop Agent\nlet instances = await fdc3.findInstances({appId: \"MyAppId\", desktopAgent: \"agent-A\"});\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findInstances()\n    DA ->> DAB: findInstancesRequest\n    DAB ->> DB: findInstancesRequest\n    DAB ->> DC: findInstancesRequest\n    DB ->> DAB: findInstancesResponse (B)\n    DC ->> DAB: findInstancesResponse (C)\n    DAB ->> DA: findInstancesResponse (B + C)\n    DA --) AA: resolve (AppIdentifier[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentRequest.schema.json](pathname:///schemas/2.2/bridging/findInstancesAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/findInstancesBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n:::note\nIf the `findInstancesRequest` from the requesting agent does not include a `meta.source` field then the Bridge MUST set the `meta.source.desktopAgent` field to attribute the request to the requesting agent. This is the case for all agent request messages that don't require application details.\n:::\n\nIf results should be constrained to a particular Desktop Agent, then set a `desktopAgent` field in `payload.app` and a matching `destination` field in `meta`:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findInstancesRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\": \"agent-B\" // destination agent\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"destination\": { \"desktopAgent\": \"agent-B\" }, //destination agent\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nThe Desktop Agent Bridge should only forward the request to the requested Desktop Agent and handle the message exchange as a **Request Response (single)**.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentResponse.schema.json](pathname:///schemas/2.2/bridging/findInstancesAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findInstancesAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/findInstancesBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findInstancesBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findInstancesBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, augmenting each appIdentifier with a `desktopAgent` field, producing the following collated response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findInstancesResponse\",\n    \"payload\": {\n        \"appIdentifiers\":  [\n            { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n            //\"desktopAgent\" added by DAB\n            { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n            { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\", \n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::info\nIf a target Desktop Agent was specified in the request (via a `desktopAgent` field in `payload.app`), then the DAB is not collating responses and does not need to generate a unique `meta.responseUuid` and MUST quote that given by the responding Desktop Agent.\n:::\n\n:::note\nIn the event that an agent times out or returns an error, where others respond, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources`.\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// DAB -> agent-A\n[\n    { \"appId\": \"myApp\", \"instanceId\": \"4bf39be1-a25b-4ad5-8dbc-ce37b436a344\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"4f10abb7-4df4-4fc6-8813-bbf0dc1b393d\", \"desktopAgent\": \"agent-B\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"920b74f7-1fef-4076-adef-63b82bae0dd9\", \"desktopAgent\": \"agent-C\" },\n    { \"appId\": \"myApp\", \"instanceId\": \"688dbd5e-21dc-4469-b8cf-4b6a606f9a27\" } //local response\n]\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/findIntent.md",
    "content": "---\nid: findIntent\nsidebar_label: findIntent\ntitle: findIntent\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>`](../../api/ref/DesktopAgent#findintent)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with `appId: \"agentA-app1\"` and `instanceId: \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.findIntent(\"StartChat\", context);\n```\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A \n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntent()\n    DA ->> DAB: findIntentRequest\n    DAB ->> DB: findIntentRequest\n    DAB ->> DC: findIntentRequest\n    DB ->> DAB: findIntentResponse (B)\n    DC ->> DAB: findIntentResponse (C)\n    DAB ->> DA: findIntentResponse (B + C)\n    DA --) AA: resolve (AppIntent)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentRequest.schema.json](pathname:///schemas/2.2/bridging/findIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/findIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB (with `intent` and `context` specified, but not `resultType`):\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C):\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\nNote that the `source.desktopAgent` field has been populated with the id of the agent that raised the requests, enabling the routing of responses.\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentBridgeErrorResponse.schema.json)\n\n### Example\n\nNormal response from agent-A, where the request was raised.\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"myChat\" }\n    ]\n}\n```\n\nDA agent-B would produce the following response if the request was generated locally:\n\n```json\n{\n    \"intent\": { \"name\": \"StartChat\" },\n    \"apps\": [\n        { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n        { \"appId\": \"Symphony\", \n          \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n          \"title\": \"Symphony\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\" }\n    ]\n}\n```\n\nHence, the response it sends to the bridge is encoded as follows:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */ },\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\" }\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nNote the response UUID generated by the agent-B and the reference to the request UUID produced by agent-A where the request was originated. Further, note that the `AppMetadata` elements in the `AppIntent` do not have a `desktopAgent` field yet, and the `meta` element does not contain a `sources` element, both of which the bridge will add.\n\nDA agent-C would produce the following response locally:\n\n```json\n{\n    \"intent\":  { \"name\": \"StartChat\" },\n    \"apps\": [\n       { \"appId\": \"WebIce\"}\n    ]\n}\n```\n\nwhich is sent back over the bridge as a response to the request message as:\n\n```json\n// agent-C -> DAB\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"WebIce\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentC>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives and collates the responses, producing the following collated response which is sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentResponse\",\n    \"payload\": {\n        \"intent\":  \"StartChat\",\n        \"appIntent\":  {\n            \"intent\":  { \"name\": \"StartChat\" },\n            \"apps\": [\n                { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" }, //desktopAgent added by DAB\n                { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Symphony\", \n                  \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                  \"title\": \"Symphony\", \n                  \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n            ]\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [ //added by DAB\n            { \"desktopAgent\": \"agent-A\" },\n            { \"desktopAgent\": \"agent-B\" },\n        ]\n    }\n}\n```\n\n:::note\n\nIn the event that an agent referred to in the API call is not connected to the bridge, an agent that was connected times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` and the appropriate error ([`ResolveError.DesktopAgentNotFound`](../../api/ref/Errors#resolveerror), [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::\n\nFinally, agent-A combines the data received from the bridge, with its own local response to produce the response to the requesting application:\n\n```json\n// agent-A -> requesting App\n{\n    \"intent\":  { \"name\": \"StartChat\", \"displayName\": \"Chat\" },\n    \"apps\": [\n        // local to this agent\n        { \"appId\": \"myChat\" },\n        //agent-B responses\n        { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Symphony\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"Symphony\", \n            \"desktopAgent\": \"agent-B\" },\n        { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n        //agent-C responses\n        { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n    ]\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/findIntentsByContext.md",
    "content": "---\nid: findIntentsByContext\nsidebar_label: findIntentsByContext\ntitle: findIntentsByContext\n---\n\nDesktop Agent bridging message exchange for a `findIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API call:\n\n- [`findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>`](../../api/ref/DesktopAgent#findintentsbycontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (collated)**\n\nE.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntentArr = await fdc3.findIntentsByContext(context);\n```\n\n:::note\nThe message exchanges for this API call are nearly identical to that used for [`findIntent()`](findIntent), differing only by the lack of an `intent` field in the request message payload and the structure of the response message (where an array of `AppIntents` is returned).\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.findIntentsByContext\n    DA ->> DAB: findIntentsByContextRequest\n    DAB ->> DB: findIntentsByContextRequest\n    DAB ->> DC: findIntentsByContextRequest\n    DB ->> DAB: findIntentsByContextResponse (B)\n    DC ->> DAB: findIntentsByContextResponse (C)\n    DAB ->> DA: findIntentsByContextResponse (B + C)\n    DA --) AA: resolve (AppIntent[])\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentRequest.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/},\n        \"resultType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        }\n    }\n}\n```\n\nThe DAB fills in the `source.desktopAgent` field and forwards the request to the other Desktop Agents (agent-B AND agent-C).\n\n```json\n// DAB -> agent-B\n// DAB -> agent-C\n{\n    \"type\": \"findIntentsByContextRequest\",\n    \"payload\": {\n        \"context\": {/*contextObj*/},\n        \"resultType\": \"fdc3.instrument\"\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/findIntentsByContextBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/findIntentsByContextBridgeErrorResponse.schema.json)\n\n### Example\n\nAn individual agent (for example agentB) would generate a local response as an array of `AppIntent` objects:\n\n```json\n[\n    {\n        \"intent\": { \"name\": \"StartChat\" },\n        \"apps\": [\n            { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n            { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n            { \"appId\": \"Symphony\", \n                \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                \"title\": \"Symphony\" },\n            { \"appId\": \"Slack\", \"title\": \"Slack\" }\n        ]\n    },\n    {\n        \"intent\": { \"name\": \"ViewProfile\" },\n        \"apps\": [\n            { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n            { \"appId\": \"myCRM\", \n            \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n            \"title\": \"My CRM\" }\n        ]\n    }\n]\n```\n\nThis response is encoded and sent to the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    { \"appId\": \"Skype\", \"title\": \"Skype\" /* other AppMetadata fields may be included */},\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\" }\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nEach `AppMetadata` object is augmented by the bridge with a `desktopAgent` field, the responding `DesktopAgentIdentifier` value is added to the `meta.sources` element and the message payload is collated with responses from other agents into a response to the requesting agent:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"findIntentsByContextResponse\",\n    \"payload\": {\n        \"appIntents\": [\n            {\n                \"intent\": { \"name\": \"StartChat\" },\n                \"apps\": [\n                    //agent-B responses\n                    { \"appId\": \"Skype\", \"title\": \"Skype\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \"title\": \"Symphony\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Symphony\", \n                        \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                        \"title\": \"Symphony\", \n                        \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"Slack\", \"title\": \"Slack\", \"desktopAgent\": \"agent-B\" },\n                    //agent-C response\n                    { \"appId\": \"WebIce\", \"desktopAgent\": \"agent-C\"}\n                ]\n            },\n            {\n                \"intent\": { \"name\": \"ViewProfile\" },\n                \"apps\": [\n                    //agent-A responses\n                    { \"appId\": \"myCRM\", \"title\": \"My CRM\", \"desktopAgent\": \"agent-B\" },\n                    { \"appId\": \"myCRM\", \n                    \"instanceId\": \"93d2fe3e-a66c-41e1-b80b-246b87120859\", \n                    \"title\": \"My CRM\",\n                    \"desktopAgent\": \"agent-B\" }\n                    //agent-C responses\n                    { \"appId\": \"riskToolkit\", \"title\": \"Client Risk Toolkit\", \"desktopAgent\": \"agent-C\" },\n                    { \"appId\": \"linkedIn\", \"title\": \"LinkedIn\", \"desktopAgent\": \"agent-C\" }\n                ]\n            }\n        ]\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidDAB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [\n            { \"desktopAgent\": \"agent-B\" }, \n            { \"desktopAgent\": \"agent-C\" }\n        ]\n    }\n}\n```\n\nFinally agent-A combines the payload received with it own response and returns it to the requesting application.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/getAppMetadata.md",
    "content": "---\nid: getAppMetadata\nsidebar_label: getAppMetadata\ntitle: getAppMetadata\n---\n\nDesktop Agent bridging message exchange for a `getAppMetadata` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`getAppMetadata(app: AppIdentifier): Promise<AppMetadata>`](../../api/ref/DesktopAgent#getappmetadata)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\nlet appIdentifier = { appId: \"myApp@my.appd.com\", desktopAgent: \"agent-B\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n:::info\n`fdc3.getAppMetadata` calls should only involve the Desktop Agent Bridge where a `desktopAgent` field appears in the AppIdentifier being queried, all other calls should be handled locally by the Desktop Agent. Hence, the `payload.app.desktopAgent` is required on all requests.\n:::\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.getAppMetadata()\n    DA ->> DAB: getAppMetadataRequest\n    DAB ->> DB: getAppMetadataRequest\n    DB ->> DAB: getAppMetadataResponse (B)\n    DAB ->> DA: getAppMetadataResponse (B)\n    DA --) AA: resolve (AppMetadata)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentRequest.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"getAppMetadataRequest\",\n    \"payload\": {\n        \"app\": {\n            { \"appId\": \"myApp@my.appd.com\", \"desktopAgent\": \"agent-B\" }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentResponse.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/getAppMetadataBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/getAppMetadataBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from a Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...] \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n    }\n}\n```\n\nThe bridge receives the response, augments the appMetadata with a `desktopAgent` field, producing the following response which it sends back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\":  \"getAppMetadataResponse\",\n    \"payload\": {\n        \"appMetadata\": { \n            \"appId\": \"myApp@my.appd.com\",\n            \"name\": \"myApp\",\n            \"version\": \"1.0\",\n            \"title\": \"My example application\",\n            \"tooltip\": \" A tooltip for the application that can be used to render UI elements.\",\n            \"description\": \"A longer, multi-paragraph description for the application that could include mark-up.\",\n            \"icons\": [..],\n            \"screenshots\": [...],\n            \"desktopAgent\": \"agent-B\" //added by DAB\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\":  \"<responseUuidAgentB>\",\n        \"timestamp\":  \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }]\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/open.md",
    "content": "---\nid: open\nsidebar_label: open\ntitle: open\n---\n\nDesktop Agent bridging message exchange for a `open` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>`](../../api/ref/DesktopAgent#open)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Response (single)**\n\nE.g.\n\n```javascript\n// Open an app without context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n\n// Open an app with context, using an AppIdentifier object to specify the target and Desktop Agent\nlet AppIdentifier = {appId: 'myApp-v1.0.1', desktopAgent:\"DesktopAgentB\"};\nlet instanceMetadata = await fdc3.open(AppIdentifier, contextObj);\n```\n\nNote that it is not currently possible to identify resolve all available applications within a Desktop Agent via the FDC3 API. Hence, `fdc3.open` calls without a specified `desktopAgent` field in their `AppIdentifier`, e.g.:\n\n```javascript\n// Open a target app via AppIdentifier, without a specified Desktop Agent \nlet AppIdentifier = {appId: 'myApp-v1.0.1'};\nlet instanceMetadata = await fdc3.open(AppIdentifier);\n```\n\nshould always be processed locally without be passed to the bridge.\n\nThe `fdc3.open` command should result in a single copy of the specified app being opened and its instance data returned, or an error if it could not be opened. When receiving a response from invoking `fdc3.open` via the Desktop Agent Bridge, the new app instances MUST be initialized before responding as the responding Desktop Agent will need to return an `AppIdentifier` with an `instanceId` field set.\n\nIf the remote Desktop Agent is not currently connected from the bridge, the [`OpenError.DesktopAgentNotFound` error](../../api/ref/Errors#openerror) should be returned in the response from the bridge and the promise returned  from the call to `fdc3.open` rejected with it.\n\n## Message exchange\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.open()\n    DA ->> DAB: openRequest\n    DAB ->> DB: openRequest\n    DB ->> DAB: openResponse\n    DAB ->> DA: openResponse\n    DA --) AA: resolve (AppIdentifier)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/openAgentRequest.schema.json](pathname:///schemas/2.2/bridging/openAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/openBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/openBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the bridge:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"agent-B\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\"\n        }\n    }\n}\n```\n\nwhich is repeated on to the target agent as:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"openRequest\",\n    \"payload\": {\n        \"app\": {\n            \"appId\": \"myApp\",\n            \"desktopAgent\":\"DesktopAgentB\"\n        },\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": 2020-03-...,\n        \"source\": {\n            \"appId\": \"AChatApp\",\n            \"instanceId\": \"02e575aa-4c3a-4b66-acad-155073be21f6\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/openAgentResponse.schema.json](pathname:///schemas/2.2/bridging/openAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/openAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/openAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/openBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/openBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/openBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/openBridgeErrorResponse.schema.json)\n\n### Example\n\nResponse message from target Desktop Agent:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nwhich is augmented and repeated on by the bridge as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"openResponse\",\n    \"payload\": {\n        \"appIdentifier\": {\n            \"appId\": \"myApp\",\n            \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/ref/raiseIntent.md",
    "content": "---\nid: raiseIntent\nsidebar_label: raiseIntent\ntitle: raiseIntent\n---\n\nDesktop Agent bridging message exchange for a `raiseIntent` API call on the [`DesktopAgent`](../../api/ref/DesktopAgent). Generated by API calls:\n\n- [`raiseIntent(intent: string, context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintent)\n- [`raiseIntentForContext(context: Context, app: AppIdentifier): Promise<IntentResolution>`](../../api/ref/DesktopAgent#raiseintentforcontext)\n\n[Message Exchange Type](../spec#individual-message-exchanges): **Request Multiple Response (single)**\n\nFor Desktop Agent Bridging, a `raiseIntent` message exchange MUST always pass an `app: AppIdentifier` argument to target the intent. Further, if no `instanceId` is set in the `AppIdentifier`, then it should be interpreted to mean *'spawn a new instance of the target application'*. A local FDC3 API implementation call would normally defer to a resolver UI or similar if there are multiple options for resolving a specified `appId` (i.e. existing instance(s) and the option spawning a new instance), whereas this message exchange assumes that resolution has already taken place on the source Desktop Agent.\n\nHence, if a target [`AppIdentifier`](../../api/ref/Types#appidentifier) is not passed in the original `DesktopAgent` API call, then the [`findIntent`](findIntent) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange may then be used (if a remote option was selected as the resolution) to raise the intent.\n\n:::info\n\nThe same approach applies to `fdc3.raiseIntentForContext` calls, in that a [`findIntentByContext`](findIntentsByContext) message exchange should be used to collect options for the local resolver to use. Once an option has been selected (for example because there is only one option, or because the user selected an option in a local intent resolver UI), the `raiseIntent` message exchange is then used (if a remote option was selected as the resolution) to raise the intent.\n\n:::\n\ne.g. An application with appId `agentA-app1` makes the following API call:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context);\n```\n\nAgent A should then conduct the `findIntent` message exchange as described above, displaying its Intent resolver UI if necessary. Once an option is selected, the `raiseIntent` message exchange is conducted as if the API call had been made with a target app:\n\n```javascript\nlet appIntent = await fdc3.raiseIntent(\"StartChat\", context, {\"appId\": \"Slack\", \"desktopAgent\": \"agent-B\"});\n```\n\nIn the event that an agent referred to in the API call is not connected to the bridge, it is connected but times out or returns an error, its `DesktopAgentIdentifier` should be added to the `meta.errorSources` element instead of `meta.sources` in the `raiseIntentResponse` and the appropriate error (which might include any error from the [`ResolveError`](../../api/ref/Errors#resolveerror) enumeration, [`BridgingError.ResponseTimedOut`](../../api/ref/Errors#bridgingerror) or [`BridgingError.AgentDisconnected`](../../api/ref/Errors#bridgingerror)) should be added to `meta.errorDetails`.\n\n:::tip\n\nDesktop Agents MAY support the deprecated `raiseIntent` signature that uses the app `name` field by using the `findIntent` message exchange to attempt to resolve the `name` to an `AppIdentifier`.\n\n:::\n\n## Message exchange\n\n:::note\n\nAgent-C is not involved in the diagram below as the `raiseIntent` is always specified with a target application and Desktop Agent.\n\n:::\n\n```mermaid\nsequenceDiagram\n    box Desktop Agent A\n    participant AA as App A\n    participant DA as Desktop Agent A\n    end\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    AA --) DA: fdc3.raiseIntent \n    DA ->> DAB: raiseIntentRequest\n    DAB ->> DB: raiseIntentRequest\n    DB ->> DAB: raiseIntentResponse\n    DAB ->> DA: raiseIntentResponse\n    DA -->> AA: resolve (IntentResolution)\n    AA --) DA: resolution.getResult()\n    DB ->> DAB: raiseIntentResultResponse\n    DAB ->> DA: raiseIntentResultResponse\n    DA --) AA: resolve (IntentResult)\n```\n\n## Request format\n\n### Request message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentRequest.schema.json](pathname:///schemas/2.2/bridging/raiseIntentAgentRequest.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeRequest.schema.json](pathname:///schemas/2.2/bridging/raiseIntentBridgeRequest.schema.json)\n\n### Example\n\nOutward message to the DAB:\n\n```json\n// agent-A -> DAB\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": { // AppIdentifier for chosen resolution including desktopAgent value\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\"\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\nThe bridge fills in the `source.desktopAgent` field and forwards the request to the target Desktop Agent:\n\n```json\n// DAB -> agent-B\n{\n    \"type\": \"raiseIntentRequest\",\n    \"payload\": {\n        \"intent\": \"StartChat\",\n        \"context\": {/*contextObj*/},\n        \"app\": {\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n            //Note an instanceId may be included to target an already running instance\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"source\": {\n            \"appId\": \"agentA-app1\",\n            \"instanceId\": \"c6ad5174-6f78-4582-8e96-728d93a4d7d7\",\n            \"desktopAgent\": \"agent-A\" //added by DAB\n        },\n        \"destination\": { // duplicates the app argument so that the message is routed like any other\n            \"appId\": \"Slack\",\n            \"desktopAgent\": \"agent-B\"\n        }\n    }\n}\n```\n\n## Response format\n\n### Response message schemas\n\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultAgentResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentResultAgentResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultAgentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentResultAgentErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentBridgeErrorResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultBridgeResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentResultBridgeResponse.schema.json)\n- [https://fdc3.finos.org/schemas/2.2/bridging/raiseIntentResultBridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/raiseIntentResultBridgeErrorResponse.schema.json)\n\n### Example\n\nIf the `raiseIntent` request were made locally, agent-B would deliver the intent and context to the target app's `IntentHandler` and respond to the raising application with an `IntentResolution`:\n\n```javascript\n{\n    \"intent\": \"StartChat\",\n    \"source\": {\n        \"appId\": \"Slack\",\n        \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"   \n    },\n    getResult: ƒ\n}\n```\n\nThis is encoded and sent to the bridge (omitting the `getResult()` function) as:\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\"      \n            }\n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nWhen producing a response to a `raiseIntent` request, the instance of the receiving application MUST be initialized (if it does not already exist) and an `instanceId` generated for it before the `IntentResolution` is generated so that it can include the `instanceId`.\n\n:::\n\nThe bridge will fill in the `intentResolution.source.DesktopAgent` & `source.desktopAgent` and relay the message back to agent-A:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"intentResolution\": {\n            \"intent\": \"StartChat\",\n            \"source\": {\n                \"appId\": \"Slack\",\n                \"instanceId\": \"e36d43e1-4fd3-447a-a227-38ec48a92706\",\n                \"desktopAgent\": \"agent-B\" // added by DAB\n            }  \n        }\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nWhen `Slack` produces an `IntentResult` from its `IntentHandler`, or the intent handler finishes running without returning a result, it should send a further `raiseIntentResultResponse` message to indicate that it's finished running and to pass any `IntentResult` onto the raising application (setting either `payload.intentResult.context` or `payload.intentResult.channel` to indicate the type of the `IntentResult`, or leaving `payload.intentResult` empty to indicate a `void` result). There is no need to provide a `source` field in this response as the source information was already provided in the `raiseIntentResponse` message preceding it.\n\n```json\n// agent-B -> DAB\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"intentResult\": {\n            \"context\": {/*contextObj*/}\n            /* for a channel IntentResult use:\n            \"channel\": {\n                \"id\": \"app-channel xyz\",\n                \"type\": \"user\"\n            }\n\n            or for a void result use leave this object empty.\n            */\n\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\", //a different UUID should be used for the result response\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\n:::tip\n\nIf intent result is private channel see [PrivateChannels](../spec#privatechannels) for additional message exchanges that may be needed.\n\n:::\n\nFinally, the bridge augments the response with `sources[0].desktopAgent` and passes it back to Agent-A.\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {\n        \"context\": {/*contextObj*/}\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n\nIf the `IntentHandler` returned `void` rather than an intent result `payload` should be empty, e.g.:\n\n```json\n// DAB -> agent-A\n{\n    \"type\": \"raiseIntentResultResponse\",\n    \"payload\": {},\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid 2>\",\n        \"timestamp\": \"2020-03-...\",\n        \"sources\": [{ \"desktopAgent\": \"agent-B\" }] // added by DAB\n    }\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/agent-bridging/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Agent Bridging Overview (2.2)\n---\n\n:::info _[@experimental](../fdc3-compliance#experimental-features)_\n\nDesktop Agent Bridging is an experimental feature added to FDC3 in 2.1, hence, its design may change in the future and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\n<!-- ## TODO list\n\n* Expand on how the DAB should create the JWT token (and its claims, which must change to avoid replay attacks) which it sends out in the `hello` message for DAs to validate.\n* Link to BackPlane project somewhere \n\n-->\n\nThe FDC3 Desktop Agent API addresses interoperability between apps running within the context of a single Desktop Agent (DA), enabling cross-application workflows and context sharing.\n\n![A single desktop and FDC3 Desktop Agent](/assets/dab-overview-1.png)\n\nIt is clear, however, that user desktops are substantially more complicated in reality. Some Desktop Agent implementations already provide additional features allowing \"external\" applications (e.g. those not launched by the Desktop Agent) to connect in order to participate in interoperability.\n\n![A single desktop and Desktop Agent, with external apps](/assets/dab-overview-2.png)\n\nFirms that make extensive use of FDC3 have also identified use cases where interoperability workflows span different physical desktops, and have built proprietary bridging solutions (e.g. [Backplane](https://backplane.finos.org/) was originally developed as an in-house solution to this problem).\n\n![Two physical desktops with a desktop agent each](/assets/dab-overview-3.png)\n\nWith the success of FDC3, usage of vendor-provided Desktop Agents has increased substantially among banks and buy-side institutions. Buy-side firms who are clients of multiple banks' platforms have multiple desktop agents delivered to their desktops. Several software vendors also deliver FDC3-compatible software: some as apps that can run in any Desktop Agent, but some as self-contained applications running in their own desktop agent. They are often multi-component suites of functionality with a customized user experience, and are not simple to export to a different Desktop Agent. In these cases, being able to provide a single installable platform bundled with a Desktop Agent is a far more practical solution for the vendor and customer.\n\n![Two physical desktops, one with multiple desktop agents](/assets/dab-overview-4.png)\n\nHowever, unless the Desktop Agents themselves can interoperate, unfortunately, this approach prevents interoperability rather than promoting it. To support user workflows spanning the whole environment there needs to be some form of network connectivity between Desktop Agents.\n\nDesktop Agent Bridging addresses the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can also interoperate, allowing workflows to span multiple Desktop Agents. This is achieved, without implementation changes or special handling in the apps, by providing a protocol and service for the Desktop Agents to interoperate with each other instead, allowing application interop to extend across the bridged agents, seamlessly.\n\nIn any Desktop Agent Bridging scenario, it is expected that each DA is being operated by the same user (as the scope of FDC3 contemplates cross-application workflows for a single user, rather than cross-user workflows), although DAs may be run on different machines operated by the same user. Whether a bridge is running for Desktop Agents to connect to, whether it requires the agents to authenticate etc., is in the hands of the user (and their local IT team).\n\n## Bridging Desktop Agents\n\nThe Desktop Agent Bridging Part of the FDC3 Standard is composed of three components:\n\n- **[Bridge Connection](#connection)**: A means for Desktop Agents to communicate with a bridge, and through that bridge, with each other.\n- **[Bridge Connection Protocol (BCP)](#bridge-connection-protocol)**: A protocol defining message exchanges necessary to connect to a Bridge and to perform initial state synchronization.\n- **[Bridge Messaging Protocol (BMP)](#bridge-messaging-protocol)**: A protocol defining message exchanges that allow FDC3 API interop to extend across multiple Desktop Agents.\n\nDetail on each of these components is defined in the following sections.\n\n:::note\n\nAlthough this specification defines a particular [connection](#connection) type (based on a websocket server), it has been divided into parts so that the protocol definitions might be reused to implement a bridge over an alternative connection in future.\n\n::: \n\n:::tip\n\nThe Desktop Agent Bridging protocol has been designed such that an application using the FDC3 API does not need to make any significant changes in order to make use of the Bridging connection between its Desktop Agent and another agent. This is achieved via messaging workflows that allow the bridged agents to cooperate on behalf of the applications, for example, by retrieving options for intent resolution from other agent or forwarding on messages that were broadcast on channels.\n\nHowever, Bridging should still be visible to applications, which is achieved through the addition of a `desktopAgent` field to the `AppIdentifier` type allowing it to indicate that an app or app instance exists on another agent, as well as a number of new error messages that may be returned to indicate bridging issues.\n\n:::\n\n### Agent Bridging Compliance\n\nAgent Bridging is introduced in FDC3 2.1 as an [@experimental](../fdc3-compliance#experimental-features) feature of the FDC3 Standard, included to enable implementation by and feedback from the FDC3 community. As such, it is currently optional for the purposes of compliance and is exempted from the normal versioning and deprecation polices in order to facilitate any refinement needed.\n\n### JSON Message Protocol & JSON Schema\n\nThe Bridge Connection Protocol (BCP) and Bridge Messaging Protocols (BMP) that the Desktop Agent Bridging Part defines are based on messages encoded in JSON. [JSON Schema](https://json-schema.org/) is used to define the format of each message in the protocol. These schema files should be considered the 'source of truth' for each and may be used to validate that individual messages are in the correct format. However, examples are provided in the documentation in TypeScript and JavaScript formats for convenience. TypeScript interfaces for individual messages, included in the FDC3 NPM module, are generated from the JSON Schema source files using [quicktype](https://quicktype.io/).\n\n## Connection\n\n### Topology\n\nIn order to implement Desktop Agent Bridging some means for Desktop Agents to connect to and communicate with each other is needed. This Standard assumes that Desktop Agent Bridging is implemented via a standalone 'bridge' which each agent connects to and will use to route messages to or from other agents. This topology is similar to a star topology in networking, where the Desktop Agent Bridge (a 'bridge') will be the central node acting as a router.\n\n```mermaid\nflowchart TD;\n    A[DA A]\n    B[DA B]\n    C[DA C]\n    D[DA D]\n    E{Bridge} \n    E <--> |websocket| A\n    E <--> |websocket| B\n    C <--> |websocket| E\n    D <--> |websocket| E\n```\n\nOther possible topologies include peer-to-peer or client/server networks, however, these introduce significant additional complexity into multiple aspects of the bridging protocol that must be implemented by Desktop Agents, (including discovery, authentication and message routing), where a star topology/standalone bridge enables a relatively simple set of protocols, with the most difficult parts being implemented in the bridge itself.\n\nWhilst the standalone bridge represents a single point of failure for the interconnection of Desktop Agents, it will also be significantly simpler than a full Desktop Agent implementation. Further, failures may be mitigated by setting the bridge up as a system service, such that it is started when the user's computer is started and may be restarted automatically if it fails. In the event of a bridge failure or manual shutdown, then Desktop Agents will no longer be bridged and should act as single agents.\n\nBy using the Desktop Agent Bridging Connection and Messaging protocols, a bridge will implement \"server\" behavior by:\n\n- Accepting connections from client Desktop Agents, receiving and authenticating credentials and assigning a name (for routing purposes)\n- Receiving requests from client Desktop Agents.\n- Routing requests to client Desktop Agents.\n- Receiving responses from client Desktop Agents and collating them.\n- Routing responses to client Desktop Agents.\n\nA Desktop Agent will implement \"client\" behavior by:\n\n- Connecting to the bridge, providing authentication credentials and receiving an assigned named (for routing purposes).\n- Forwarding requests to the bridge.\n- Awaiting response(s) from the bridge.\n- Receiving requests from the bridge.\n- Sending responses to the bridge.\n\nHence, message paths and propagation are simple. All messages to other Desktop Agents are passed to the bridge for routing and all messages (both requests and responses) are received back from it, i.e. the bridge is responsible for all message routing.\n\n#### Multi-Machine Use Cases\n\nIn financial services it is not unusual for a single user to be working with applications on more than one desktop. As Desktop Agents do not span desktops bridging Desktop Agents across multiple machines is an additional use case for Desktop Agent bridging. However, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user.\n\n```mermaid\nflowchart LR;\n    A[DA A]\n    B[DA B]\n    B1{Bridge 1} \n    C[DA C]\n    D[DA D]\n    B2{Bridge 2}\n\n    subgraph PC1 [PC 1]\n      direction RL\n      B1 <--> |websocket| A\n      B1 <--> |websocket| B\n    end\n    subgraph PC2 [PC 2]\n      direction LR\n      B2 <--> |websocket| C\n      B2 <--> |websocket| D\n    end\n    PC1 .- |Bridge interconnect| PC2\n```\n\nHowever, cross-machine routing is currently considered to be an internal concern of a Desktop Agent Bridge implementation, with each Desktop Agent simply communicating with a bridge instance located on the same machine. Hence, the connection protocol between bridges themselves is currently beyond the scope of this standard and my be implemented via any suitable means.\n\nFurther, as FDC3 only contemplates interoperability between apps for a single user, it is expected that in multi-machine use cases each machine is being operated by the same user. However, methods of verifying the identity of users are currently beyond the scope of the Standard.\n\n### Websocket Connection\n\nConnections between Desktop Agents and the Desktop Agent Bridge will be made via websocket connections, with the bridge acting as the websocket server and each connected Desktop Agent as a client.\n\nThe bridge MUST run on the same machine as the Desktop Agents, and the websocket MUST be bound to the loopback adapter IP address (127.0.0.1), ensuring that the websocket is not exposed to wider networks.\n\nBridge implementations SHOULD default to binding the websocket server to a port in the recommended port range 4475 - 4575, enabling simple discovery of a running bridge via attempting socket connections to ports in that range and attempting a handshake (as defined later in this proposal) that will identify the websocket as belong to a Desktop Agent Bridge. A port range MAY be used, in preference to a single nominated port, in order to enable the automatic resolution of port clashes with other services.\n\nBoth DAs and bridge implementations SHOULD support at least connection to the recommended port range and MAY also support configuration for connection to an alternative bridging port or port range.\n\n#### WebSockets and Multiple Machines\n\nAs the bridge binds its websocket on the loopback address (127.0.0.1) it cannot be connected to from another device. Hence, an instance of the standalone bridge may be run on each device and those instances exchange messages by other means in order to implement the bridge cross-device.\n\n## Bridge Connection Protocol\n\nOn connection to the bridge's websocket, a handshake must be completed that may include an authentication step before a name is assigned to the Desktop Agent for use in routing messages. The purpose of the handshake is to allow:\n\n- The Desktop Agent to confirm that it is connecting to the Desktop Agent Bridge, rather than another service exposed via a websocket.\n- The Desktop Agent Bridge to require that the Desktop Agent authenticate itself, allowing it to control access to the network of bridged Desktop Agents.\n- The Desktop Agent to request a particular name by which it will be addressed by other agents and for the bridge to assign the requested name, after confirming that no other agent is connected with that name, or a derivative of that name if it is already in use.\n\nThe bridge is ultimately responsible for assigning each Desktop Agent a name and for routing messages using those names. Desktop Agents MUST accept the name they are assigned by the bridge.\n\nExchange standardized handshake messages that identify:\n\n- That the server is a bridge, including:\n  - implementation details for logging by DA.\n  - supported FDC3 version(s).\n- That the client is an FDC3 DA, including:\n  - implementation details (ImplementationMeta returned by fdc3.getInfo() call) for logging by DA and sharing with other DAs.\n    - already includes supported FDC3 version.\n  - request for a specific agent name.\n\n```mermaid\nsequenceDiagram\n    participant DA as Desktop Agent A\n    participant DAB as Desktop Agent Bridge\n    participant DB as Desktop Agent B\n    participant DC as Desktop Agent C\n    DA -->>+ DAB: connect (step 1)\n    DAB ->>+ DA: hello (step 2)\n    DA ->>+ DAB: handshake (steps 3-5)\n    DAB ->>+ DA: connectedAgentsUpdate (step 6)\n    DAB ->>+ DB: connectedAgentsUpdate (step 6)\n    DAB ->>+ DC: connectedAgentsUpdate (step 6)\n```\n\n### Step 1. Connect to Websocket\n\nThe Desktop Agent attempts to connect to the websocket at the first port in the defined port range. If a connection cannot be made on the current port, move to the next port in the range and reattempt connection.\n\nIn the event that there are no ports remaining in the range, the Desktop Agent SHOULD reset to the beginning of the range, SHOULD pause its attempts to connect and resume later (a minimum wait period of 5 seconds SHOULD be used)\n\nNote, if the Desktop Agent is configured to run at startup (of the user's machine) it is possible that the Desktop Agent Bridge may start later (or be restarted at some point). Hence, Desktop Agents SHOULD be capable of connecting to the bridge once they are already running (rather than purely at startup).\n\n### Step 2. Hello\n\nWhen a new connection is made to the Desktop Agent Bridge websocket, it sends a `hello` message, including its metadata.\n\n```typescript\n{\n    type: \"hello\",\n    payload: {\n        desktopAgentBridgeVersion: string,\n        supportedFDC3Versions: string[],\n        authRequired: boolean,\n        /** The DAB JWT authentication token */\n        authToken?: string\n    },\n    meta: {\n        timestamp: date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/connectionStep2Hello.schema.json](pathname:///schemas/2.2/bridging/connectionStep2Hello.schema.json)\n\nA Desktop Agent can use the structure of this message to determine that it has connected to a Desktop Agent Bridge (i.e by checking `msg.type === \"hello\" && msg.payload.desktopAgentBridgeVersion`), whether it supports a compatible FDC3 version and whether it is expected to provide authentication credentials in the next step (`if(msg.payload.authRequired) { ... }`).\n\nAn optional JWT token can be included in the `hello` message to allow the connecting agent to authenticate the bridge. Verification of the supplied JWT by the DA is optional but recommended, meaning that the DA SHOULD verify the received JWT when one is included in the `hello` message.\n\nIf no hello message is received, the message doesn't match the defined format or validation of the optional JWT fails, the Desktop Agent should return to step 1 and attempt connection to the next port in the range.  \n\n### Step 3. Handshake & Authentication\n\nThe DA must then respond to the `hello` message with a `handshake` request to the bridge, including an auth token (JWT) if required.\n\n```typescript\n{\n    type:  \"handshake\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** The JWT authentication token */\n        authToken?: string,\n        /** Metadata about the Desktop Agent connecting, normally retrieved within the \n         *  context of the Desktop Agent via `fdc3.getInfo()`.*/\n        implementationMetadata: {\n          /** The version number of the FDC3 specification that the implementation\n          *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1. */\n          fdc3Version: string,\n          /** The name of the provider of the FDC3 Desktop Agent Implementation\n           *  (e.g.Finsemble, io.Connect, OpenFin etc.). */\n          provider: string,\n          /** The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0). */\n          providerVersion: string,\n          /** Metadata indicating whether the Desktop Agent implements optional features of\n           *  the Desktop Agent API. */\n          readonly optionalFeatures: {\n            /** Used to indicate whether the exposure of 'originating app metadata' for\n             *  context and intent messages is supported by the Desktop Agent.*/\n            \"OriginatingAppMetadata\": boolean;\n            /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n             *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n             *  the Desktop Agent.*/\n            \"UserChannelMembershipAPIs\": boolean;\n            /** Used to indicate whether the experimental Desktop Agent Bridging\n             *  feature is implemented by the Desktop Agent.*/\n            \"DesktopAgentBridging\": boolean;\n          }\n        },\n        /** The requested DA name */\n        requestedName: string,\n        /** The current state of the Desktop Agent's App and User channels (exclude any \n         *  Private channels), as a mapping of channel id to an array of Context objects, \n         *  one per type found in the channel, most recent first.*/\n        channelsState: Record<string, Context[]>\n    },\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/connectionStep3Handshake.schema.json](pathname:///schemas/2.2/bridging/connectionStep3Handshake.schema.json)\n\nNote that the `meta` element of of the handshake message contains both a `timestamp` field (for logging purposes) and a `requestUuid` field that should be populated with a Universally Unique Identifier (UUID), generated by the Desktop Agent. This `responseUuid` will be used to link the handshake message to a response from the Desktop Agent Bridge that assigns it a name. For more details on UUID generation see [Universally Unique Identifier](#universally-unique-identifier) section.\n\nIf requested by the server, the JWT auth token payload should take the form:\n\n```typescript\n{\n    \"sub\": string, // UUID for the key pair used to sign the token\n    \"iat\": date    // timestamp at which the the token was generated as specified in ISO 8601\n}\n```\n\ne.g.\n\n```json\n{\n    \"sub\": \"65141135-7200-47d3-9777-eb8786dd31c7\",\n    \"iat\": \"2022-07-06T10:11:43.492Z\"\n}\n```\n\nNote that the `sub` SHOULD be a UUID that does NOT need to match the name requested by the Desktop Agent. It will be used to identify the key pair that should be used to validate the JWT token. Further, multiple Desktop Agent's MAY share the same keys for authentication and hence the same `sub`, but they will be assigned different names for routing purposes by the Desktop Agent Bridge. If an agent disconnects from the bridge and later re-connects it MAY request and be assigned the same name it connected with before.\n\n### Step 4. Auth Confirmation and Name Assignment\n\nThe Desktop Agent Bridge will extract the authentication token `sub` from the JWT token's claims and then verify the token's signature against any public key it has been configured with. If the signature can't be verified, the bridge should respond with the below authentication failed message and the socket should be disconnected by the bridge.\n\n```typescript\n{\n    type:  \"authenticationFailed\",\n    payload: {\n        message: string\n    },\n    meta: {\n        /** Timestamp at which response was generated */\n        timestamp:  Date,\n        /** UUID for the handshake request */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/connectionStep4AuthenticationFailed.schema.json](pathname:///schemas/2.2/bridging/connectionStep4AuthenticationFailed.schema.json)\n\nIf authentication succeeds (or is not required), then the Desktop Agent Bridge should assign the Desktop Agent the name requested in the `handshake` message, unless another agent is already connected with that name in which case it should generate a new name which MAY be derived from the requested name. Note that the assigned name is not communicated to the connecting agent until step 6.\n\n### Step 5. Synchronize the Bridge's Channel State\n\nChannels are the main stateful mechanism in the FDC3 that we have to consider. The state of any FDC3 channel includes the most recent context broadcast on the channel, plus the most recent context of each type that has been broadcast on it (allowing applications to receive the most recent context of the type that they listen for, rather than just the most recent context of any type).\n\nA key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync. To do so, the states must be synchronized whenever a new agent connects. Hence, the Bridge MUST process the `channelState` provided by the new agent in the `handshake` request, which MUST contain details of each known User Channel or App Channel and its state (the most recent context object and the most recent context object of each type that it has received). The bridge MUST compare the received channel names and states to its own representation of the current state of channels in connected agents, merge that state with that of the new agent and communicate the updated state to all connected agents to ensure that they are synchronized with it.\n\nHence, if we assume that the state of each channel can be represented by an array of the most recent context object of each type, with the most recent context occupying the first position in the array, the Desktop Agent Bridge MUST merge the incoming `channelsState` with the `existingChannelsState` as follows:\n\n```typescript\nObject.keys(channelsState).forEach((channelId) => {\n    if (!existingChannelsState[channelId]) {\n        //unknown channels: just adopt its state\n        existingChannelsState[channelId] = channelsState[channelId];\n    } else {\n        //known channels: merge state, with existing state taking precedence\n        const currentState = existingChannelsState[channelId];\n        const incoming = channelsState[channelId];\n        incoming.forEach((context) => {\n            //only add previously unknown context types to the state\n            if (!currentState.find(element => element.type === context.type)){\n                //add to end of array to avoid setting most recent context type at the beginning\n                currentState.push(context);\n            } \n            // else ignore any types that are already known          \n        });\n    }\n});\n```\n\nWhen multiple agents attempt to connect to the Desktop Agent Bridge at the same time, steps 3-6 of the connection protocol MUST be handled by the Desktop Agent Bridge serially to ensure correct channel state synchronization.\n\n### Step 6. Connected Agents Update\n\nThe updated `existingChannelsState` will then be shared with all connected agents along with updated details of all connected agents via a `connectedAgentsUpdate` message sent to all connected sockets. The newly connected agent will receive both its assigned name and channel state via this message. The `connectedAgentsUpdate` message will be linked to the handshake request by quoting the `meta.requestUuid` of the `handshake` message.\n\nThe `connectedAgentsUpdate` message will take the form:\n\n```typescript\n{\n    type:  \"connectedAgentsUpdate\",\n    /** Request body, containing the arguments to the function called.*/\n    payload: {\n        /** Should be set when an agent first connects to the bridge and provide \n         * its assigned name. */\n        addAgent?: string,\n        /** Should be set when an agent disconnects from the bridge and provide \n         * the name that no longer is assigned. */\n        removeAgent?: string,\n        /** Desktop Agent Bridge implementation metadata of all connected agents. \n         *  Note that this object is extended to include a `desktopAgent` field \n         *  with the name assigned by the DAB. */\n        allAgents: ImplementationMetadata[],\n        /** The updated state of channels that should be adopted by the agents. \n         *  SHOULD only be set when an agent is connecting to the bridge. */\n        channelsState?: Record<string, Context[]> // see step4\n    },\n    meta: {\n        /** For a new connection, should be the same as the handshake requestUuid. \n         *  Should be the same as the responseUuid for a disconnection.\n        */\n        requestUuid: string,\n        /** Unique UUID for this message */\n        responseUuid: string,\n        /** Timestamp at which response was generated */\n        timestamp:  date,\n    }\n}\n```\n\n**Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/connectionStep6ConnectedAgentsUpdate.schema.json](pathname:///schemas/2.2/bridging/connectionStep6ConnectedAgentsUpdate.schema.json)\n\nWhen an agent connects to the bridge, it and other agents connected to the bridge, should adopt the state of any channels that do not currently exist or do not currently contain state of a particular type. This synchronization is NOT performed via broadcast as the context being merged would become the most recent context on the channel, when other contexts may have been broadcast subsequently. Rather, it should be adopted internally by each Desktop Agent, merging it such that it would be received by applications that have added a context listener to the channel or call `channel.getCurrentContext()` on it.\n\nIt should be noted that Desktop Agents will not have context listeners for previously unknown channels, and SHOULD simply record that channel's state for use when that channel is first used.\n\nFor known channel names, the Desktop Agents MUST also compare their current state to that which they have just received and may need to internally adopt context of types not previously seen on a channel. As context listeners can be registered for either a specific type or all types some care is necessary when doing so (as only the most recently transmitted Context should be received by un-typed listeners). Hence, the new context MUST only be passed to a context listener if it was registered specifically for that type and a context of that type did not previously exist on the channel.\n\nIn summary, updating listeners for a known channel should be performed as follows:\n\n1. The incoming channel state `channelState` for a particular channel should be processed from last to first (most recent context broadcast).\n2. If there is no current context of that type, broadcast it to any listeners of that specific type only.\n3. If there is a current context of that type, and it does not match the incoming object exactly, broadcast it to listeners of that specific type only.\n4. If the most recent (first in the incoming array) type OR value of that type doesn't match the most recent context broadcast on the channel, broadcast it to un-typed listeners only.\n\nThis procedure is the same for both previously connected and connecting agents, however, the merging procedure used by the Desktop Agent Bridge in step 5 will result in apps managed by previously connected agents only rarely receiving context broadcasts (and only for types they have not yet seen on a channel).\n\nAfter applying the `connectedAgentsUpdate` message, the newly connected Desktop Agent and other already connected agents are able to begin communicating through the bridge.\n\n#### Channels\n\nIt is assumed that Desktop Agents SHOULD adopt the recommended 8 channel set (and the respective display metadata). Desktop Agents MAY support channel customization through configuration.\n\nThe Desktop Agent Bridge MAY support channel mapping ability, to deal with issues caused by differing channel sets.\n\nA key responsibility of the Desktop Agent Bridge is ensuring that the channel state of the connected agents is kept in-sync, which requires an initial synchronization step as part of the connection protocol.\n\n#### Atomicity and handling concurrent operations\n\nHandling by the Desktop Agent of the synchronization message from the Desktop Agent Bridge in step 6 of the connection protocol should be atomic to prevent message overlap with `fdc3.broadcast`, `channel.broadcast`, `fdc3.addContextListener` or `channel.getCurrentContext`. I.e. the `connectedAgentsUpdate` message must be processed immediately on receipt by Desktop Agents and updates applied before any other messages are sent or responses processed.\n\nSimilarly, the Desktop Agent Bridge must process steps 3-6 of the connection protocol (receiving a `handshake` messages up to issuing the `connectedAgentsUpdate` messages to all participants) as a single atomic unit, allowing no overlap with the processing of other messages from connected agents (as they might modify the state information it is processing during those steps).\n\n#### Notification to users of connection events\n\nDesktop Agents SHOULD provide visual feedback to end users when they or other agents connect or disconnect from the Desktop Agent Bridge (i.e. whenever a `connectedAgentsUpdate` message is received, or a disconnection happens). Doing so will ensure that the end user understands whether their apps and Desktop Agent can communicate with other apps running under other Desktop Agents, and can better attribute any issues with interoperability between them to the probable source.\n\n### Step 7. Disconnects\n\nAlthough not part of the connection protocol, it should be noted that the `connectedAgentsUpdate` message sent in step 6 should also be sent whenever an agent disconnects from the bridge to update other agents. If any agents remain connected, then the `channelState` does not change and can be omitted. However, if the last agent disconnects the bridge SHOULD discard its internal `channelState`, instead of issuing the update.\n\n## Bridge Messaging Protocol\n\nIn order for Desktop Agents to communicate with the Desktop Agent Bridge and thereby other Desktop Agents, a messaging protocol is required. FDC3 supports both 'fire and forget' interactions (such as the broadcast of context messages) and interactions with specific responses (such as raising intents and returning a resolution and optional result), both of which must be handled by that messaging protocol and message formats it defines, as described in this section.\n\n### Collating Responses\n\nWhilst some FDC3 requests are 'fire and forget' (e.g. broadcast) the main requests such as `findIntent` or `raiseIntent` expect a response. In a bridging scenario, the response can come from multiple Desktop Agents and therefore need to be aggregated and augmented before they are sent back to the requesting DA.\n\n:::note\nA set of classifications for message exchange types are provided in the [Individual message exchanges](#individual-message-exchanges) section.\n:::\n\nThe Desktop Agent Bridge is the responsible entity for collating responses together from all DAs. Whilst this approach may add some complexity to bridge implementations, it will simplify DA implementations since they only need to handle one response.\n\nThe Desktop Agent Bridge MUST allow for timeout configuration.\n\nThe Bridge SHOULD also implement timeout for waiting on DA responses. Assuming the message exchange will be all intra-machine, a recommended maximum timeout of 1500ms SHOULD be used. Similarly, Desktop Agents SHOULD apply a timeout to requests made to the bridge that require a response (collated or otherwise), to handle situations where the bridge is not responding as expected. A recommended maximum timeout of 3000ms SHOULD be used in this case.\n\n### Message Format\n\nAll messages sent or received by the Desktop Agent Bridge will be encoded in JSON and will have the same basic structure (including those already defined in the connection protocol):\n\n```typescript\n{\n    /** Identifier used to declare what aspect of FDC3 that the message relates to. */\n    type:  string,\n    /** Request body, containing any the arguments to the FDC3 interactions. */\n    payload: { ... },\n    /** Metadata relating to the message, its sender and destination. */\n    meta: { ... }\n}\n```\n\nMessages can be divided into four categories:\n\n- Requests from a Desktop Agent: Messages that initiate a particular interaction.\n- Requests forwarded by the Bridge: Messages augmented and forwarded on by the Bridge.\n- Responses from a Desktop Agent: Messages from a single Desktop Agent that respond to a prior request from the Bridge.\n- Responses collated and forwarded by the Bridge: Messages from the Bridge back to the Desktop Agent that initiated an interaction, which may combine the responses from multiple other Desktop Agents.\n\nDetails specific to each are provided in the following sections.\n\n#### Request Messages\n\nRequest messages from a Desktop Agent use the following format:\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the FDC3\n     * function name that the message relates to, e.g. 'findIntent', with \n     * 'Request' appended. */\n    type:  string,\n    /** Request body, typically containing the arguments to the function called.*/\n    payload: {\n        /** Used to indicate which channel `broadcast` functions were called on.*/\n        channelId?: string,\n        /** Used as an argument to `findIntent` and `raiseIntent` functions.`*/\n        intent?: string,\n        /** Used as an argument to `broadcast`, `findIntent` and `raiseIntent` \n         * functions.*/\n        context?: Context,\n        /** Used as an argument to `open`, `raiseIntent`, `getAppMetadata`, and \n         * `findInstances` functions.*/\n        app?: AppIdentifier,\n        /** Used as an argument to `findIntent` functions. */\n        resultType?: string,\n        /** Context type name used in Private Channel event messages. */\n        contextType?: string\n    },\n    /** Metadata used to uniquely identify the message and its sender. */\n    meta: {\n        /** Unique UUID for this request */\n        requestUuid: string,\n        /** Timestamp at which request was generated */\n        timestamp:  date,\n         /** Field that represents the source application that the request was \n          * received from, or the source Desktop Agent if it issued the request \n          * itself. */\n        source: AppIdentifier | DesktopAgentIdentifier,\n        /** Optional field that represents the destination that the request\n         * should be routed to. Must be set by the Desktop Agent for API calls\n         * that include a target app parameter and must include the name of the\n         * Desktop Agent hosting the target application. */\n        destination?: AppIdentifier | DesktopAgentIdentifier\n    }\n}\n```\n\n**Request Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/agentRequest.schema.json](pathname:///schemas/2.2/bridging/agentRequest.schema.json)\n\nIf the FDC3 API call underlying the request message includes a target (typically defined by an `app` argument, in the form of an AppIdentifier object) it is the responsibility of the Desktop Agent to copy that argument into the `meta.destination` field of the message and to ensure that it includes a `meta.destination.desktopAgent` value. If the target is provided in the FDC3 API call, but without a `meta.destination.desktopAgent` value, the Desktop Agent should assume that the call relates to a local application and does not need to send it to the bridge.\n\nRequests without a `meta.destination` field will be forwarded to all other agents by the bridge, which will also handle the collation of responses which quote the `meta.requestUuid`.\n\n##### Request Messages Forwarded by the Bridge\n\nRequest messages forwarded by the Bridge onto other Desktop Agents use the same format as incoming requests from Desktop Agents, with the exception that the `desktopAgent` properties of the `meta.source` field MUST be provided, and should be overwritten by the Bridge (based on the connection that the message was received from) to prevent spoofing of request message origins.\n\n**Bridge Request Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/bridgeRequest.schema.json](pathname:///schemas/2.2/bridging/bridgeRequest.schema.json)\n\n#### Response Messages\n\nResponse messages from a Desktop Agent back to the Bridge use a similar format that is differentiated from requests by the presence of a `meta.responseUuid` field. They MUST also quote the `meta.requestUuid` that they are responding to.\n\n:::info\nResponse messages do not include a `meta.destination` as the routing of responses is handled by the Bridge via the `meta.requestUuid` field. They also do not include a `source` field as responses are currently always from the Desktop Agent, and the bridge is required to provide this information itself to prevent spoofing.\n:::\n\nThere are two types of each response message, a successful response and an error response.\n\n##### Successful Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/agentResponse.schema.json](pathname:///schemas/2.2/bridging/agentResponse.schema.json)\n\n##### Error Responses\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error strings from an appropriate FDC3 API Error \n         *  enumeration. */\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** UUID for this specific response message. */\n        responseUuid:  string,\n        /** Timestamp at which request was generated */\n        timestamp:  Date\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/agentErrorResponse.schema.json](pathname:///schemas/2.2/bridging/agentErrorResponse.schema.json)\n\n##### Response Messages Collated and Forwarded by the Bridge\n\nResponses from individual Desktop Agents are collated by the Bridge and are forwarded on to the the Desktop Agent that initiated the interaction. The format used is very similar to that used for responses by the Desktop Agents, with the exception of the source information in the `meta` field. Specifically, the `meta.source` field does not need to be provided by agents, as responses are currently always provided by the Desktop Agent, whose details will be provided by the bridge when it receives the response. In responses from the bridge, the `meta.source` is replaced by two arrays, `meta.sources` and `meta.errorSources`, which provide details on the Desktop Agents that responded normally or responded with errors. The detail of any errors returned (in the `payload.error` field of a Desktop Agent's response) is collected up into a `meta.errorDetails` field. Moving the error details from the `payload` to the `meta` field enables the return of a valid response to the originating Desktop Agent in cases where some agents produced valid responses, and others produced errors.\n\nHence, for responses forwarded by the bridge there are two type of response messages from the Bridge returned to agents, one for requests that received at least one successful response, and another for use when all agents (or the targeted agent) returned an error.\n\n##### At Least One Successful Response\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Response to `open` */\n        appIdentifier?: AppIdentifier,\n        /** Response to `findInstances` */\n        appIdentifiers?: Array<AppIdentifier>,\n        /** Response to `getAppMetadata` */\n        appMetadata?: AppMetadata,\n        /** Response to `findIntent`*/\n        appIntent?:  AppIntent,\n        /** Response to `findIntentsByContext`*/\n        appIntents?:  AppIntent[],\n        /** Response to `raiseIntent` functions, returned on delivery of the\n         * intent and context to the target app.\n         *  Note `getResult()` function should not / can not be included in JSON. */\n        intentResolution?: IntentResolution,\n        /** Secondary response to `raiseIntent`, sent when the `IntentHandler` \n         *  has returned.\n         *  Note:\n         *  - return an empty payload object if the `IntentHandler` returned void. \n         *  - `Channel` functions (`broadcast`, `getCurrentContext`, \n         *    `addContextListener` do not need to be included in JSON).*/\n        intentResult?: {\n            context?: Context, \n            channel?: Channel\n        }\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for the sources\n         * that generated responses to the request. Will contain a single value\n         * for individual responses and multiple values for responses that were\n         * collated by the bridge. May be omitted if all sources errored. MUST\n         * include the `desktopAgent` field when returned by the bridge. */\n        sources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. May be omitted if all sources responded. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Response Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/bridgeResponse.schema.json](pathname:///schemas/2.2/bridging/bridgeResponse.schema.json)\n\n##### All Responses are Errors\n\n:::info\nIn this case there are no successful responses and the bridge must populate the `payload.error` field in the response to the agent with one of the error messages returned, so that the receiving Desktop Agent may return it to the app that made the original call.\n:::\n\n```typescript\n{\n    /** Identifies the type of the message and it is typically set to the\n     * FDC3 function name that the message relates to, e.g. 'findIntent', \n     * with 'Response' appended.*/\n    type:  string,\n    /** Response body, containing the actual response data. */\n    payload: {\n        /** Standardized error string from an appropriate FDC3 API Error \n         *  enumeration. This should also appear in `meta.errorDetails`.*/\n        error?: string,\n    },\n    meta: {\n        /** UUID for the request this message is responding to.*/\n        requestUuid: string,\n        /** Unique UUID for this collated response (generated by the bridge). */\n        responseUuid:  string,\n        /** Timestamp at which the collated response was generated */\n        timestamp:  Date,\n        /** Array of AppIdentifiers or DesktopAgentIdentifiers for responses\n         * that were not returned to the bridge before the timeout or because\n         * an error occurred. May be omitted if all sources responded without\n         * errors. MUST include the `desktopAgent` field when returned by the\n         * bridge. */\n        errorSources?: (AppIdentifier | DesktopAgentIdentifier)[],\n        /** Array of error message strings for responses that were not returned\n         * to the bridge before the timeout or because an error occurred. \n         * Should be the same length as the `errorSources` array and ordered the\n         * same. */\n        errorDetails?: string[]\n    }\n}\n```\n\n**Error Response Schema**: [https://fdc3.finos.org/schemas/2.2/bridging/bridgeErrorResponse.schema.json](pathname:///schemas/2.2/bridging/bridgeErrorResponse.schema.json)\n\n### Identifying Individual Messages\n\nThere are a variety of message types that need to be sent between bridged Desktop Agents, several of which will need to be replied to specifically (e.g. a `fdc3.raiseIntent` call should receive an `IntentResolution` when an app has been chosen, and may subsequently receive an `IntentResult` after the intent handler has run). Hence, messages also need a unique identity, which should be generated at the Desktop Agent that is the source of that message, in the form of a Universally Unique Identifier (UUID). Response messages will include the identity of the request message they are related to, allowing multiple message exchanges to be 'in-flight' at the same time.\n\nHence, whenever a request message is generated by a Desktop Agent it should contain a unique `meta.requestUuid` value. Response messages should quote that same value in the `meta.requestUuid` field and generate a further unique identity for their response, which is included in the `meta.responseUuid` field. Where a response is collated by the Desktop Agent Bridge, the Bridge should generate its own `meta.responseUuid` for the collated response message.\n\nDesktop Agent Bridge implementations should consider request messages that omit `meta.requestUuid` and response messages that omit either `meta.requestUuid` or `meta.responseUuid` to be invalid and should discard them.\n\n#### Universally Unique Identifier\n\nA UUID (Universally Unique IDentifier), also known as a Globally Unique IDentifier (GUID), is a generated 128-bit text string that is intended to be 'unique across space and time', as defined in [IETF RFC 4122](https://www.ietf.org/rfc/rfc4122.txt).  \n\nThere are several types of UUIDs, which vary how they are generated. As Desktop Agents will typically be running on the same machine, system clock and hardware details may not provide sufficient uniqueness in UUIDs generated (including during the connect step, where Desktop Agent name collisions may exist). Hence, it is recommended that both Desktop Agents and Desktop Agent Bridges SHOULD use a version 4 generation type (random).\n\n### Identifying Desktop Agents Identity and Message Sources\n\nDesktop Agents will prepare messages in the above format and transmit them to the bridge. However, to target intents and perform other actions that require specific routing between DAs, DAs need to have an identity. Identities should be assigned to Desktop Agents when they connect to the bridge. This allows for multiple copies of the same underlying Desktop Agent implementation to be bridged and ensures that identity clashes can be avoided.\n\nTo facilitate routing of messages between agents, the `AppIdentifier` is expanded to contain an optional `desktopAgent` field:\n\n```typescript\ninterface AppIdentifier {\n  readonly appId: string;\n  readonly instanceId?: string;\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental Introduced in FDC3 2.1 and may be refined by further changes\n   *  outside the normal FDC3 versioning policy.\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\nFurther, a new `DesktopAgentIdentifier` type is introduced to handle cases where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. This is particularly relevant for `findIntent` message exchanges:\n\n```typescript\n/** @experimental Introduced in FDC3 2.1 and may be refined by further changes\n *  outside the normal FDC3 versioning policy. */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent. */ \n  readonly desktopAgent: string;\n}\n```\n\nHence, either an `AppIdentifier` or `DesktopAgentIdentifier` is used as the `meta.source` value of both request or response messages and the source Desktop Agent identity for bridging messages will always be found at `meta.source.desktopAgent`. To prevent spoofing and to simplify the implementation of clients, the source Desktop Agent identity MUST be added to (or overwritten in) each message by the bridge when received.\n\nA request message may include a `destination` field, set by the source Desktop Agent if the message is intended for a particular Desktop Agent (e.g. to support a `raiseIntent` call with a specified target app or app instance on a particular Desktop Agent).\n\nResponse messages do not include a `destination` field. Instead, a Desktop Agent Bridge implementation MUST retain a record of `requestUuid` fields for request message, until the request is fully resolved, allowing them to determine the destination for the collated responses and effectively enforcing the routing policy for interactions.\n\nFurther, the Desktop Agent Bridge should also inspect the `payload` of both request and response messages and ensure that any `AppIdentifier` objects have been augmented with the correct `desktopAgent` value for the app's host Desktop Agent (e.g. if returning responses to `findIntent`, ensure each `AppIntent.apps[]` entry includes the correct `desktopAgent` value). Further details of any such augmentation are provided in the description of each message exchange.\n\n### Handling of Error Responses\n\nThe FDC3 Desktop Agent API specifies a number of error enumerations that define specific error strings that should be used as the `message` element of a JavaScript `Error` to be returned to the requesting application via a rejected promise. In the event that an Error must be returned by a Desktop Agent to the Desktop Agent Bridge, the message should be selected from the [Error enumeration](../api/ref/Errors) normally used by the corresponding FDC3 function (i.e. `OpenError` for `open` calls, `ResolveError` for `findIntent` and `raiseIntent` etc.). However, Desktop Agent Bridging does NOT require that an `Error` object is returned across the bridge as it cannot be fully recreated from its constituent fields in JavaScript. Rather, return only the specified message string in the `error` field of the `payload`, which should then be used to initialize a JavaScript `Error` on the receiving end. It is also advisable to output additional logging (in the Desktop Agent Bridge) indicating that the error was originally generated by a remote Desktop Agent and to provide the relevant details.\n\nFor example, a `raiseIntent` targeted at an app instance that no longer exists might generate the following response from the Desktop Agent:\n\n```json\n// e.g. agent-B -> DAB in response to a raiseIntent call\n{\n    \"type\": \"raiseIntentResponse\",\n    \"payload\": {\n        \"error\": \"TargetInstanceUnavailable\", //<error string from the relevant error enum\n    },\n    \"meta\": {\n        \"requestUuid\": \"<requestUuid>\",\n        \"responseUuid\": \"<responseUuid>\",\n        \"timestamp\": \"2020-03-...\"\n    }\n}\n```\n\nFor messages that target a specific agent, the Desktop Agent Bridge will augment the message with source information and return it to the calling agent, which will then respond to the app that made the original request.\n\nIf all agents (or the targeted agent) return errors, then a suitable error string should be forwarded in the `payload.error` field as returned by at least one of the agents. This allows the agent that made the original request to return that error to the app that made the original API call. All agents that returned errors should be listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`).\n\nHowever, API calls that require a collated response from all agents where at least one agent returns a successful response, will result in a successful response from the Desktop Agent Bridge (i.e. no `error` element should be included), with the agents returning errors listed in the `errorSources` array and the error message strings they returned (or that were applied because they timed out) listed in the `errorDetails` array (in the same order as `errorSources`). This allows for successful exchanges on API calls such as `fdc3.findIntent` where some agents do not have options to return and would normally respond with (for example) `ResolveError.NoAppsFound`.\n\nFinally, to facilitate easier debugging, errors specific to Desktop Agent Bridge are added to the Error enumerations, including:\n\n```typescript\nenum OpenError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n\nenum ResolveError {\n  ...\n  /** Returned if the specified Desktop Agent is not found, via a connected \n      Desktop Agent Bridge. */\n  DesktopAgentNotFound = 'DesktopAgentNotFound',\n}\n```\n\nAnd an error enumeration is created for errors related to bridging that may occur on any request, and are returnable through the FDC3 API.\n\n```typescript\nenum BridgingError {\n  /** Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging,\n   * within the allotted timeout. */\n  ResponseTimedOut = 'ResponseToBridgeTimedOut',\n  /** Returned if a Desktop Agent that has been targeted by a particular request has\n   * been disconnected from the Bridge before a response has been received from it. */\n  AgentDisconnected = 'AgentDisconnected',\n  /** Returned for FDC3 API calls that are specified with arguments indicating that\n   *  a remote Desktop Agent should be targeted (e.g. raiseIntent with an app on a\n   *  remote DesktopAgent targeted), when the local Desktop Agent is not connected to\n   *  a bridge. */\n  NotConnectedToBridge = 'NotConnectedToBridge',\n  /** Returned if a message to a Bridge deviates from the schema for that message\n   * sufficiently that it could not be processed.\n   */\n  MalformedMessage = 'MalformedMessage'\n}\n```\n\n### Handling Malformed Messages\n\nIt is the Bridge's responsibility to validate all messages that flow to and from Desktop Agents. When a request message is malformed the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` error to the sender.  For 'request only' message exchanges, no specific error response schema is provided. Hence, the generic [Bridge Error Response Message schema](#all-responses-are-errors) should be used for such messages (with the type set to match the request message type).\n\nWhere responses to requests from other agents are malformed, the bridge MUST send a bridge error response message with  `BridgingError.MalformedMessage` to the sender and record `BridgingError.MalformedMessage` as the error response from the responder that sent the malformed message.\n\n### Forwarding of Messages and Collating Responses\n\nWhen handling request messages, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive request messages from connected Desktop Agents.\n- Augment request messages with `meta.source.desktopAgent` information (as described above).\n- Forward request messages onto either a specific Desktop Agent or all other Desktop Agents.\n  - The bridge MUST NOT forward the request to the agent that sent the request, nor expect a reply from it.\n\nFor message exchanges that involve responses, it is the responsibility of the Desktop Agent Bridge to:\n\n- Receive and collate response messages (where necessary) according the `meta.requestUuid` (allowing multiple message exchanges to be 'in-flight' at once).\n- Augment response messages with `meta.source.desktopAgent` information (as described above).\n- Apply a timeout to the receipt of response messages for each request.\n- Produce a single collated response message (where necessary) that incorporates the output of each individual response received and has its own unique `meta.responseUuid` value.\n- Deliver the collated and/or augmented response message to the source Desktop Agent that sent the request.\n\nCollated response messages generated by the bridge use the same format as individual response messages.\n\nThe following pseudo-code defines how messages should be forwarded or collated by the bridge:\n\n- **if** the message is a request (`meta.requestUuid` is set, but `meta.responseUuid` is not),\n  - **if** the message includes a `meta.destination` field,\n    - forward it to the specified destination agent,\n    - annotate the request as requiring only a response from the specified agent,\n    - await the response or the specified timeout.\n  - **else**\n    - forward it to all other Desktop Agents (not including the source),\n    - annotate the request as requiring responses from all other connected agents,\n    - await responses or the specified timeout.\n- **else if** the message is a response (both `meta.requestUuid` and `meta.responseUuid` are set)\n  - **if** the `meta.requestUuid` is known,\n    - augment any `AppIdentifier` types in the response message with a `desktopAgent` field matching that of the responding Desktop Agent,\n    - **if** `payload.error` is set in the response add the DesktopAgentIdentifier to the `meta.errorSources` element.\n    - **else**\n      - add the DesktopAgentIdentifier to the `meta.sources` element.\n    - **if** the message exchange requires collation,\n      - add the message to the collated responses for the request,\n      - **if** all expected responses have been received (i.e. all connected agents or the specified agent has responded, as appropriate),\n        - produce the collated response message and return to the requesting Desktop Agent.\n      - **else**\n        - await the configured response timeout or further responses,\n        - **if** the timeout is reached without any responses being received\n          - produce and return an appropriate [error response](../api/ref/Errors), including details of all Desktop Agents in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n        - **else if** the timeout is reached with a partial set of responses,\n          - produce and return, to requesting Desktop Agent, a collated response and include details of Desktop Agents that timed out in `errorSources` and the `BridgingError.ResponseTimeOut` message for each in the `errorDetails` array.\n          - log the timeout for each Desktop Agent that did not respond and check disconnection criteria.\n    - **else**\n      - forward the response message on to requesting Desktop Agent.\n  - **else**\n    - discard the response message (as it is a delayed to a request that has timed out or is otherwise invalid).\n- **else**\n  - the message is invalid and should be discarded.\n\n### Workflows Broken By Disconnects\n\nTargeted request and request/response workflows may be broken when a Desktop Agent disconnects from the bridge, which bridge implementations will need to handle.\n\nThree types of requests:\n\n1. Fire and forget (i.e. `broadcast`).\n2. Requests that require the bridge to collate multiple responses from the bridged Desktop Agents (e.g. `findIntent`).\n3. Requests targeted at a specific Desktop Agent that are forwarded to the target Desktop Agent (e.g. `raiseIntent`).\n\nThe latter two types embody workflows that may be broken by an agent disconnecting from the bridge either before or during the processing of the request.\n\nWhen processing the disconnection of an agent from the bridge, the bridge MUST examine requests currently 'in-flight' and:\n\n- For requests that require the bridge to collate multiple responses:\n  - add the disconnected Desktop Agent's details to the `errorSources` array in the response and the `BridgingError.AgentDisconnected` message to the `errorDetails` array.\n  - complete requests that no longer require further responses (all other agents have responded), or\n  - continue to await the timeout (if other agents are yet to respond), or\n  - return an 'empty' response in the expected format (if no other agents are connected and no data will be received).\n- For requests that target a specific agent:\n  - return the `BridgingError.AgentDisconnected` in the response's `payload.error` field (as the request cannot be completed).\n\nFinally, in the event that either a Desktop Agent or the bridge itself stops responding, but doesn't fully disconnect, the timeouts (specified earlier in this document) will be used to handle the request as if a disconnection had occurred.\n\nIn the event that a Desktop Agent repeatedly times out, the bridge SHOULD disconnect that agent (and update other agents via the `connectedAgentsUpdate` message specified in the connection protocol), to avoid all requests requiring the full timeout to complete.\n\nIn the event that the bridge repeatedly times out, connected Desktop Agents MAY disconnect from the bridge and attempt to reconnect by returning to Step 1 of the connection protocol.\n\n### Individual message exchanges\n\nIndividual message exchanges are defined for each of the Desktop Agent methods that require bridging in the reference section of this Part.\n\nEach section assumes that we have 3 agents connected by a bridge (itself denoted by `DAB` in diagrams):\n\n- agent-A (denoted by `DA A` in diagrams)\n- agent-B (denoted by `DA A` in diagrams)\n- agent-C (denoted by `DA A` in diagrams)\n\nMessage exchanges come in a number of formats, which are known as:\n\n- **Request only**: A request message that does not require a response ('fire and forget'), such as a [`broadcast`](ref/broadcast).\n- **Request Response (single)**: A request message that expects a single response from a single Desktop Agent, such as `open` or `getAppMetadata`.\n- **Request Response (collated)**: A request message that expects responses from all other Desktop Agents that are collated by the bridge and returned as a single response to the requestor, such as `findIntent` or `findInstances`.\n- **Request Multiple Response (single)**: A request message that expects multiple responses from a single Desktop Agent, such as `raiseIntent`.\n\nThe message exchanges defined are:\n\n- [`broadcast`](ref/broadcast)\n- [`findInstances`](ref/findInstances)\n- [`findIntent`](ref/findIntent)\n- [`findIntentsByContext`](ref/findIntentsByContext)\n- [`getAppMetadata`](ref/getAppMetadata)\n- [`open`](ref/open)\n- [`raiseIntent`](ref/raiseIntent)\n- [`PrivateChannel.broadcast`](ref/PrivateChannel.broadcast)\n- [`PrivateChannel.eventListenerAdded`](ref/PrivateChannel.eventListenerAdded)\n- [`PrivateChannel.eventListenerRemoved`](ref/PrivateChannel.eventListenerRemoved)\n- [`PrivateChannel.onAddContextListener`](ref/PrivateChannel.onAddContextListener)\n- [`PrivateChannel.onUnsubscribe`](ref/PrivateChannel.onUnsubscribe)\n- [`PrivateChannel.onDisconnect`](ref/PrivateChannel.onDisconnect)\n\n#### PrivateChannels\n\n`PrivateChannels` are intended to provide a private communication channel for applications. In order to do so, there are differences in how their broadcasts and event messages (used to manage the channel's lifecycle) MUST be handled.\n\nBroadcasts and event messages should be addressed to the Desktop Agent that created the channel, which will route it to the relevant application and any other listeners. If any of those listeners are remote, the message should be repeated back to the bridge, once for each listener with the destination set as a full `AppIdentifier`. Both these messages and broadcast messages MUST NOT be repeated back to the application that generated them. The source information on repeated messages should be unmodified to ensure that the message is attributed to the original source.\n\nTo facilitate the addressing of messages to the relevant Desktop Agent and `AppIdentifier` some additional tracking of private channel metadata is necessary in each Desktop Agent (or Desktop Agent Bridge Client implementation). For applications receiving a private channel as an `IntentResult`, the `AppIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id. This data MUST be retained until the receiving application sends a `disconnect` message, after which it can be discarded. For applications that have created and returned a private channel, and have subsequently received event messages subscriptions (`onAddContextListener`, `onSubscribe`, `onDisconnect`) the `appIdentifier` with `desktopAgent` field MUST be tracked against the private channel's id and listener type, which will facilitate repeating of messages to registered listeners. This data MUST be retained until the remote application sends a `disconnect` message or a message indicating that the listener has been removed.\n\n#### FDC3 API calls that do NOT generate bridge messages\n\nSome FDC3 API calls can be handled locally and do not need to generate request messages to the Desktop Agent Bridge, but are likely to be involved in other exchanges that do generate messages to the bridge (for example adding context or intent handlers). Those calls include:\n\n- `addContextListener` functions (excluding those for `PrivateChannel` instances)\n- `listener.unsubscribe` (excluding those for `PrivateChannel` instances)\n- `addIntentListener`\n- `getOrCreateChannel`\n- `createPrivateChannel`\n- `getUserChannels` and `getSystemChannels`\n- `joinUserChannel` and `joinChannel`\n- `getCurrentChannel`\n- `leaveCurrentChannel`\n- `getInfo`\n\nHowever, `PrivateChannel` instances allow the registration of additional event handlers (for the addition or removal of context listeners) that may be used to manage streaming data sent over them by starting or stopping the stream in response to those events. Hence, the following calls DO generate request messages when used on a PrivateChannel instance:\n\n- `addContextListener`\n- `listener.unsubscribe`\n- `disconnect`\n\n#### Message Schemas and generated sources\n\nJSONSchema definitions are provided for all Desktop Agent Bridging message exchanges defined by the Bridge Messaging Protocol (see links in each reference page), which may be used to validate the correct generation of messages to or from a bridge (a separate schema is provided for the agent and bridge versions of each message).\n\nThe JSONSchema definitions are also used to generate TypeScript interfaces for the messages to aid in implementation of a Desktop Agent Bridge or client library. These may be imported from the FDC3 npm module:\n\n```typescript\nimport { BridgingTypes } from \"@finos/fdc3\";\nconst aMessage: BridgingTypes.BroadcastAgentRequest\n```\n\nor\n\n```typescript\nimport { BroadcastAgentRequest } from \"@finos/fdc3/dist/bridging/BridgingTypes\";\nconst aMessage: BroadcastAgentRequest\n```\n\nSources may also be generated from the JSONSchema files for other languages.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/App-Channel-Tests.md",
    "content": "---\nid: App-Channel-Tests\nsidebar_label: App Channel Tests\ntitle: App Channel Tests\nhide_title: true\n---\n\n# App Channel Tests  \n<!-- markdownlint-disable MD033 -->\n\n## Basic Broadcast\n\n| App | Step                    | Details                                                                    |\n|-----|-------------------------|----------------------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add an _untyped_ context listener to the channel, using: <br /> !`await testChannel.addContextListener(null,handler)` |\n| B   | 3. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4. Broadcast            | Broadcast an `fdc3.instrument` Context to the channel with: <br />`testChannel.broadcast(<fdc3.instrument>)`|\n| A   | 5. Receive Context      | The handler added in step 2 will receive the instrument context. Ensure that the instrument received by A is identical to that sent by B.  |\n\n- `ACBasicUsage1` Perform above test.\n\n## Current Context\n\n| App | Step                        | Details                                                                    |\n|-----|-----------------------------|----------------------------------------------------------------------------|\n| B   | 1. Retrieve `Channel`       |Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2. Broadcast                | Broadcast an `fdc3.instrument` to the channel using: <br />`testChannel.broadcast(<fdc3.instrument>)`|\n| A   | 3. Retrieve `Channel`       |Retrieve a `Channel` object representing the same 'App' channel B did (`test-channel`)|\n| A   | 4. Retrieve Current Context | A gets the _current context_ of the user channel. via:  `await testChannel.getCurrentContext()` <br />Ensure that the instrument received by A is identical to that sent by B    |\n\n- `ACBasicUsage2` Perform above test\n\n## Filtered Context\n\n| App | Step                    | Details                                                         |\n|-----|-------------------------|-----------------------------------------------------------------|\n| A   | 1. Retrieve `Channel`   | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| A   | 2. Add Context Listener | Add a _typed_ context listener for `fdc3.instrument`, using: <br />`await testChannel.addContextListener(\"fdc3.instrument\", handler)`|\n| B   | 3. Retrieve `Channel`   | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 4. Broadcast            | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)`|\n| A   | 5. Receive Context      | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received.                                                                   |\n\n- `ACFilteredContext1`: Perform above test.\n- `ACFilteredContext2`: Perform above test, but add listeners for both `fdc3.instrument` and `fdc3.contact` in step2.  Ensure that both context objects are received.\n- `ACFilteredContext3`: Perform above test, except creating a _different_ channel in app B. Check that you _don't_ receive anything (as the channels don't match).\n- `ACFilteredContext4`: Perform above test, except that after creating the channel **A** creates another channel with a further _different_ channel id and adds a further context listener to it.  Ensure that **A** is still able to receive context on the first channel (i.e. it is unaffected by the additional channel) and does NOT receive anything on the second channel.\n- `ACUnsubscribe`: Perform above test, except that after creating the channel **A** then `unsubscribe()`s the listener it added to the channel. Check that **A** does NOT receive anything.\n\n### App Channel History\n\n| App | Step                        | Details                                                 |\n|-----|-----------------------------|---------------------------------------------------------|\n| A   | 1. Retrieve `Channel`       | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel(\"test-channel\")` |\n| B   | 2. Retrieve `Channel`       | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|\n| B   | 3. Broadcast                | B broadcasts both the instrument context and a contact context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)` |\n| A   | 4. Add Context Listener     | A adds a context listener to the channel _after_ B has completed all its broadcasts, via: <br />`await testChannel.addContextListener(\"fdc3.instrument\", handler)` <br /> Ensure that A does NOT receive any context via these listeners (past context is only retrieved via a `getCurrentContext()` call on App channels). |\n| A   | 5. Retrieve Current Context | A is able to retrieve the most recent context of each context type from the `Channel`  via: <br />`const instrument = await testChannel.getCurrentContext(\"fdc3.instrument\")`<br />`const contact = await testChannel.getCurrentContext(\"fdc3.contact\")`<br />Ensure that both contexts retrieved by A are identical to those sent by B|\n\n- `ACContextHistoryTyped`: Perform above test.\n- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types.  Ensure that only the last version of each type is received by **A**.\n- `ACContextHistoryLast`: In step 5. **A** retrieves the _untyped_ current context of the channel via `const currentContext = await testChannel.getCurrentContext()`. Ensure that A receives only the very last broadcast context item _of any type_.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/Basic-Tests.md",
    "content": "---\nid: Basic-Tests\nsidebar_label: Basic Tests\ntitle: Basic Tests\nhide_title: true\n---\n\n# Basic Tests\n<!-- markdownlint-disable MD033 -->\n\n_These are some basic sanity tests implemented in the FDC3 Conformance Framework.  It is expected that Desktop Agent testers will run these first before commencing the much more thorough tests in section 2 onwards._\n\n## Connection\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface was introduced to support Browser-based FDC3 Desktop Agents, known as a 'Desktop Agent Proxy', and a new [`getAgent`](../ref/GetAgent) API call was introduced to all apps to retrieve the Desktop Agent API via that interface or the existing 'Desktop Agent Preload' interface. This test pack checks that the a connection is made correctly via `getAgent`.\n\n| App | Step            | Description                                              |\n|-----|-----------------|----------------------------------------------------------|\n| A   | `getAgent`      | App A calls `getAgent` and waits for the promise to resolve to a `DesktopAgent` instance. |\n| A   | `getInfo`       | App A can call the `getInfo()` method on the `DesktopAgent` instance to get the `ImplementationMetadata` object. <br /> Check that fdc3Version is set to 2.2.  <br />Check that provider and providerVersion are populated. |\n| A   | `getUserChannels`| App A can call the `getUserChannels()` method on the `DesktopAgent` instance to get the `Channel` objects representing the system channels.<br />Check **user** channels are returned.|\n\n- `GetAgentAPI`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n\n## Basic API Usage\n\n- `BasicCL1`: A context listener can be created for a specific context type by calling `fdc3.addContextListener(\"fdc3.contact\",<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicCL2`: An **unfiltered** context listener can be created by calling `fdc3.addContextListener(null,<handler>)`.  A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicIL1`: An intent listener can be created for a specific intent by calling `fdc3.addIntentListener(<intentName>,<handler>)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.\n- `BasicGI1`: An `ImplementationMetadata` object can be retrieved, to find out the version of FDC3 that is in use along with details of the provider, by calling:\n  - `await fdc3.getInfo()`. The FDC3 version should match the API version being tested for conformance.\n- `BasicAC1`: A named 'App' channel can be retrieved by calling `fdc3.getOrCreateChannel(<name>)`. The `Channel` object returned conforms to the defined interface.\n- `BasicUC1`: The list available user/system channels can be retrieved, as an array of `Channel` Objects conforming to the defined interface, by calling `await fdc3.getUserChannels()`.\n- `BasicJC1`: A user/system channel can be joined with the with the channel's id by calling `fdc3.joinUserChannel(<channelId>)`.  Having done so, the current channel, retrieved by calling `fdc3.getCurrentChannel()` should NOT be null and should match _the channel id given_.  After leaving the current channel by calling `fdc3.leaveCurrentChannel()`, it should go back to being `null`.\n- `BasicRI1`: A specified intent can be raised by invoking `fdc3.raiseIntent(<intent name>, <context>)`. A promise should be returned.\n- `BasicRI2`: An intent can be raised for some item of context by invoking: `fdc3.raiseIntentForContext(<context>)`. A promise should be returned.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/Intents-Tests.md",
    "content": "---\nid: Intents-Tests\nsidebar_label: Intents Tests\ntitle: Intents Tests\nhide_title: true\n---\n\n# Intents Tests\n<!-- markdownlint-disable MD033 -->\n\n_Please note that API calls (and associated test cases) relating to API calls based on the `name` property of an appD record (used to specify a target application) were deprecated in FDC3 2.0 in favour of those based on `AppIdentifier`. Hence, those API calls have become optional and test cases related to them have been removed._\n\n## Setup\n\nWe assume 6 context types in the below tests (and associated AppD records):\n\n- `testContextX`\n- `testContextY`\n- `testContextZ`\n- `nonExistentContext` (context object with a unique type that does NOT appear in any of the apps (metadata or otherwise).\n- `privateChannelDetails`\n- `privateChannelIsPrivateResult`\n\nThese may be used in a test as a context object `{ \"type\": \"<typeName>\" }` or just the base type name.  Where the base type name is used it is surround with \"quotes\". If not wrapped in quotes assume it is an instance of that context type (generally just an object with a `type` field set to the type name - but occasionally with other data).\n\nYou will need to pre-populate the AppDirectory with the following items (some of which will never be started, but must be configured to confirm correct behavior from various API functions):\n\n| App | Usage                                                 | ListensFor `(pattern: intent([context-types…]) (=> result-type)`)                               | On Startup                                                                   |\n|-----|-------------------------------------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|\n| A   | Raise Intent tests without results                    | `aTestingIntent(testContextX,testContextZ)`<br />`sharedTestingIntent1(testContextX)`           | `addIntentListener()` for given intents                                       |\n| B   | Raise Intent tests with Context results               | `bTestingIntent(testContextY)`<br />`sharedTestingIntent1(testContextX, testContextY) => testContextY` | `addIntentListener()` for given intents                                       |\n| C   | Find Intent tests (never started)                     | `cTestingIntent(testContextX) => testContextZ`                                                  | `addIntentListener()` for given intents                                       |\n| D   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextX) => testContextZ`                                            | `addIntentListener()` for given intents                                       |\n| E   | Find Intent & Raise Intent with Channel result        | `sharedTestingIntent2(testContextY) => channel`                                                 | `addIntentListener()` for given intents                                       |\n| F   | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel<testContextZ>` *                                 | `addIntentListener()` for given intents                                       |\n| G   | Find Intent tests (never started)                     | `sharedTestingIntent2(testContextY)`                                                            | `addIntentListener()` for given intents                                       |\n| H   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                            | - no action                                                                   |\n| I   | Raise Intent (bad config/behavior)                    | `sharedTestingIntent2(testContextY) => testContextZ`                                           | `addIntentListener(\"MadeUpIntent\", handler)`                          |\n| J   | PrivateChannels are private                           | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult`                   | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |\n| K   | PrivateChannel lifecycle events                       | `kTestingIntent(testContextX) => channel<testContextZ>`                                         | `addIntentListener()` for given intents                                       |\n\nNB:\n\n- There is no way to indicate in the app directory the difference between a private channel and app channel.\n- We assume a final test app `Test` that will discover the Intent support in the others using the API.\n\nFinally, please note that this is a larger set of apps than were required for 1.2 tests. This is due to an increased number of parameters to API calls and AppD records, which multiplies the number of apps required. The apps are all specified here (rather than broken down over multiple issues) to ensure that clashes between test case sets can be worked out here. For example, adding one additional app that works with a particular intent/context pair might corrupt the results of multiple `findIntent` or `raiseIntent` tests. Hence, please stick to the defined type and report any issues you find so that they can be rectified in these definitions.\n\n## Find Intent basic usage\n\n- `2.0-FindIntentAppD`: Calls `fdc3.findIntent(\"aTestingIntent\")`.  Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** `AppMetadata`.\n- `2.0-FindNonExistentIntentAppD`: Calls `fdc3.findIntent(\"nonExistentIntent\")`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDRightContext`: Calls `fdc3.findIntent(\"aTestingIntent\",\"testContextX\")`.  Receives promise containing an `AppIntent` with metadata containing `aTestingIntent` and only metadata for app **A**.\n- `2.0-FindIntentAppDWrongContext`: Calls `fdc3.findIntent(\"aTestingIntent\",\"testContextY\")`.  Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n- `2.0-FindIntentAppDMultiple1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and metadata for apps  **D**, **E**, **F**, **G**, **H**  and **I** only.\n- `2.0-FindIntentAppDMultiple2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",\"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and `AppMetadata` for apps  **E**, **F**, **G**, **H**  and **I** only.\n\n## Find Intents By Context\n\n- `2.0-FindIntentByContextSingleContext`: Call `fdc3.findIntentsByContext(testContextX)`.  Should return:\n  - `aTestingIntent` (app **A**),\n  - `sharedTestingIntent1` (**A**, **B**)\n  - `cTestingIntent` (**C**),\n  - `sharedTestingIntent2` (**D**)\n  - `kTestingIntent` (**K**),\n  - AND nothing else.\n- `2.0FindIntentByContextWrongIntentAppD`: Calls `fdc3.findIntentsByContext(nonExistentContext)`. Rejects with an Error whose `message` is [`ResolveError.NoAppsFound`](https://fdc3.finos.org/docs/api/ref/Errors#resolveerror)\n\n## Find Intents By Result Type\n\n- `2.0-FindIntentAppDByResultSingle`: Calls `fdc3.findIntent(\"cTestingIntent\",testContextX,\"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultSingleNullContext`: Calls `fdc3.findIntent(\"cTestingIntent\",null,\"testContextZ\")`.  Receives promise containing an `AppIntent` with metadata containing `cTestingIntent` and only **C** app metadata.\n- `2.0-FindIntentAppDByResultMultiple`: Calls `fdc3.findIntent(\"sharedTestingIntent1\",testContextX,\"testContextY\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **B** app metadata.\n- `2.0-FindIntentAppDByResultChannel1`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",testContextY,\"channel\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent2` and only **E** and **F** app metadata.\n- `2.0-FindIntentAppDByResultChannel2`: Calls `fdc3.findIntent(\"sharedTestingIntent2\",testContextY,\"channel<testContextZ>\")`.  Receives promise containing an `AppIntent` with metadata containing `sharedTestingIntent1` and only **F** app metadata.\n\n## Raise Intent (Ignoring any result)\n\n| App   | Step                        | Details                                                                                           |\n|-------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test  | 1. Raise                    | `fdc3.raiseIntent(\"aTestingIntent\",testContextX)`<br />starts app A.                       |\n| A     | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent1\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test  | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.**                       |\n\n- `2.0-RaiseIntentSingleResolve`: Perform above test\n- `2.0-RaiseIntentTargetedAppResolve`: Repeat the above test, but:\n  - In the first step use `fdc3.raiseIntent(\"sharedTestingIntent1\",testContextX,{\"appID\":\"<B’s-appId>\"})` to start app B,\n  - Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveOpen`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})` to start A and retrieve its `AppIdentifier` with instance details.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentTargetedInstanceResolveFindInstances`: Repeat the above test, but:\n  - Before the first step, use `let appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})` to start A.\n  - Then use `const instances = await fdc3.findInstances({appId:\"<A's-appId>\"})` to retrieve a list of instances of app A. Confirm that only one is present and retrieve its `AppIdentifier`, confirming that it contains an `instanceId` field that matches that returned by the `fdc3.open` call.\n  - Then in the first step, use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,appIdentifier)` to target the running instance of app A.\n  - Confirm that the intent is delivered to the correct instance and that another instance is NOT started. Otherwise, as above.\n- `2.0-RaiseIntentFailedResolve`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextY)`.  Note that no app supports this intent and context combination.**\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve1`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextY,{appId:\"<A's-appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound`.\n- `2.0-RaiseIntentFailTargetedAppResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextX,{appId:\"NonExistentApp\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.TargetAppUnavailable`.\n- `2.0-RaiseIntentFailTargetedAppResolve3`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<H's-appId>\"})`.\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but does not add any intent listeners).\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppResolve4`: Perform above test, but:\n  - `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<I's-appId>\"})`\n  - You should receive a JavaScript Error with the message `ResolveError.IntentDeliveryFailed` (as this app is configured for the intent and context pair, but adds intent listeners of the wrong type.\n  - **Note:  Test will need an extended timeout to allow for this to be returned in time by the desktop agent, which will have a vendor-defined timeout.**\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve1`: Perform above test, but:\n  - First spawn an instance of App **A** and collect its `AppIdentifier` with `const appIdentifier = await fdc3.open({appId:\"<A's-appId>\"})`.\n  - Then use `fdc3.raiseIntent(\"aTestingIntent\",testContextY,appIdentifier)` to target that instance.  \n  - You should receive a JavaScript Error with the message `ResolveError.NoAppsFound` (since A doesn't support this context type).\n- `2.0-RaiseIntentFailTargetedAppInstanceResolve2`: Perform above test, but:\n  - Use `fdc3.raiseIntent(\"aTestingIntent\",testContextX, {appId:\"<A's-appId>\",instanceId:\"NonExistentInstanceId\"})`.  \n  - You should receive a JavaScript Error with the message `ResolveError.TargetInstanceUnavailable`.\n\n## Raise Intent Result (void result)\n\n| App    | Step                        | Details                                                                                           |\n|--------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise          | `fdc3.raiseIntent(\"aTestingIntent\",testContextX)`<br />starts app A.                       |\n| A      | 2. Receive Intent & Context | After starting up, A runs `fdc3.addIntentListener(\"aTestingIntent\")` to register its listener.<br />It then receives `testContextX`, matching that sent by Test |\n| Test   | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App A's `appId` and `instanceId` set.                     |\n| Test   | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.                        |\n| A      | 5. return void              | A should return `void` after a short delay (e.g. 5 seconds).                        |\n| Test   | 6. receive void result      | The promise received by Test from `resolution.getResult()` should resolve to void. Confirm that the promise could be retrieved before the handler function returned and that the result was received _after_ the result was returned by A, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited.                      |\n\n- `2.0-RaiseIntentVoidResult5secs`: Perform above test\n- `2.0-RaiseIntentVoidResult0secs`: Perform above test, but A should return its result immediately (no delay). Ignore test step 6 (as there is too little time between the IntentResolution and IntentHandler completing).\n- `2.0-RaiseIntentVoidResult61secs`: Perform above test, but A should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n## Raise Intent Result (Context result)\n\n| App    | Step                        | Details                                                                                           |\n|--------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. Raise                    | `fdc3.raiseIntent(\"sharedTestingIntent1\",testContextY)`<br />starts app **B**. |\n| B      | 2. Receive Intent & Context | After starting up, B runs `fdc3.addIntentListener(\"sharedTestingIntent1\")` to register its listener.<br />It then receives `testContextY`, matching that sent by Test |\n| Test   | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App B's `appId` and `instanceId` set. |\n| Test   | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |\n| B      | 5. return `testContextY`    | B should return a `testContextY` instance after a short delay (e.g. 5 seconds). |\n| Test   | 6. receive context result   | The promise received by Test from `resolution.getResult()` should resolve to the `testContextY` instance. Confirm that the promise could be retrieved before the handler function returned and that the result was received _after_ the result was returned by B, NOT before. I.e. confirm that `resolution.getResult()` does NOT block until the result is returned, but rather returns a promise that can be awaited. |\n\n- `2.0-RaiseIntentContextResult5secs`: Perform the above test.\n- `2.0-RaiseIntentContextResult0secs`: Perform the previous test but B should return its result immediately (no delay).\n- `2.0-RaiseIntentContextResult61secs`: As above, but B should return its result **after 61 seconds** (arbitrary delay to test timeout does NOT occur)\n\n## Raise Intent Result (Channel results)\n\n| App  | Step                        | Details                                                                                           |\n|------|-----------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Raise Intent             | Test raises an intent with `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY,{appId:\"<E's-appId>\"})`<br />starts app E. |\n| E    | 2. Receive Intent & Context | After starting up, E runs `fdc3.addIntentListener(\"sharedTestingIntent2\")` to register its listener.<br />It them receives `testContextY`, matching that sent by Test |\n| Test | 3. IntentResolution         | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App E's `appId` and `instanceId` set.   |\n| Test | 4. await results            | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| E    | 5. return Channel           | E should retrieve a Channel object via `fdc3.getOrCreateChannel(\"someChannelName\")` and return it immediately. |\n| Test | 6. receive Channel result   | The promise received by Test from `resolution.getResult()` should resolve to a `Channel` object with the expected id. Confirm that the `type` of the Channel object is \"app\". |\n| Test | 7. addContextListener       | Add a context listener to the Channel object via `channelObj.addContextListener(\"testContextZ\",handler)` |\n| E    | 8. broadcast context        | After a short delay (of a few seconds) E should broadcast a `testContextZ` context object over the channel, including an `id` field with a unique identifier set (e.g. a uuid). |\n| Test | 9. receive context          | Test should receive the context broadcast by E and confirm that it contains the expected `id` value. |\n\n- `2.0-RaiseIntentChannelResult`: Perform the above test\n- `2.0-RaiseIntentPrivateChannelResult`: Perform the above test, but:\n  - Substitute app F throughout - which returns a PrivateChannel result instead of channel.\n  - At step 5, the PrivateChannel should be created via`fdc3.createPrivateChannel()`.\n  - At step 6 confirm that the type of the channel is \"private\".\n\n## PrivateChannels cannot be accessed as app channels\n\n| App  | Step                                      | Details                                                                                           |\n|------|-------------------------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Create a private channel               | Test creates a PrivateChannel with `const privChan = await fdc3.createPrivateChannel()`. Confirm that the Channel has an `id`. |\n| Test | 2. Confirm private channel `id` is unique | Test creates a second PrivateChannel with `const privChan2 = await fdc3.createPrivateChannel();`. Confirm that the Channel has an `id` and that it is distinct from the first channel created. |\n| Test | 3. Retrieve as app channel                | Attempt to retrieve the channels as App Channels with `const appChan = await fdc3.getOrCreateChannel(privChan.id)` this should fail with `ChannelError.AccessDenied`  |\n| Test | 4. Raise Intent & await result            | Start app J and pass it the id of the second PrivateChannel with `fdc3.raiseIntent(\"privateChannelIsPrivate\", privateChannelDetails)`, where the context object contains the id of the channel to attempt to retrieve. An IntentResolution should be returned and App J should start. Wait for a result to be returned via `await resolution.getResult()`. |\n| J    | 5. Receive Intent & Context               | J should add an Intent Listener and receive the context with `fdc3.addIntentListener(\"privateChannelIsPrivate\",handler)` |\n| J    | 6. Retrieve as app channel                | J should attempt to retrieve the channel as an App Channel by `id` with `const appChan = await fdc3.getOrCreateChannel(\"<idPassedInContext>\")` this should fail with `ChannelError.AccessDenied`. Return a `privateChannelIsPrivateResult` back to Test to complete the test. |\n| Test | 7. Receive result                         | Test receives the result back from J and confirms that the test was passed. |\n\n- `2.0-PrivateChannelsAreNotAppChannels`: Perform the above test\n\n## PrivateChannel Lifecycle Events\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, the existing [`PrivateChannel`](../ref/PrivateChannel) lifecycle event functions (`onAddContextListener`, `onUnsubscribe` and `onDisconnect`) functions were deprecated in favour of a new [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener) function which supports events of all three types. Hence, the tests in this section have been updated to use [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener).\n\n| App  | Step                                       | Details                                                                                                                                    |\n|------|--------------------------------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Raise intent                            | Test raises an intent with `fdc3.raiseIntent(\"kTestingIntent\", testContextX, {appId: \"<K's appId>\"})`<br />starts app K. |\n| K    | 2. Receive Intent & Context                | After starting up, K runs `fdc3.addIntentListener(\"kTestingIntent\")` to register its listener.<br />It them receives `testContextX`, matching that sent by Test |\n| Test | 3. IntentResolution                        | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set.   |\n| Test | 4. await results                           | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly.  |\n| K    | 5. Create PrivateChannel & event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,<br />it should then add listeners for the 3 events offered + a context listener via:<br />- `const listener1 = await privChan.addEventListener(\"addContextListener\", handler1);`<br />- `const listener2 = await privChan.addEventListener(\"unsubscribe\", handler2);`<br />- `const listener3 = await privChan.addEventListener(\"disconnect\", handler3);`<br />- `const listener4 = await privChan.addEventListener(null, handler4);`<br />- `const listener5 = await privChan.addContextListener(\"testContextX\", handler5)`<br />it should then return the `PrivateChannel`. |\n| Test | 6. receive PrivateChannel                  | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is \"private\". |\n| Test | 7. addContextListener                      | Test should add a context listener to the PrivateChannel object via `const testListener1 = privChan.addContextListener(\"testContextZ\", contextHandler)` |\n| K    | 8. Receive event & broadcast context       | The handlers for both the \"addContextListener\" event (`handler1`) and all events (`handler4`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |\n| Test | 9. Unsubscribe listener                    | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `testListener1.unsubscribe().` |\n| K    | 10. Receive unsubscribe event              | The handlers for both the \"unsubscribe\" event (`handler2`) and all events registered by K (`handler4`) should fire. If either does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|\n| Test | 11. Broadcast context                      | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |\n| K    | 12. Receive context                        | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|\n| Test | 13. re-run addContextListener              | Test should (again) add a context listener to the PrivateChannel object via `const testListener2 = privChan.addContextListener(\"testContextZ\", contextHandler)` |\n| K    | 14. Receive event & broadcast context      | Both the \"addContextListener\" event handler (`handler1`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |\n| Test | 15. Disconnect                             | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |\n| K    | 16. Receive events & cleanup               | Both the \"unsubscribe\" event handler (`handler2`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, both the \"disconnect\" handler (`handler3`) and handler for all events (`handler4`) also added in step 5 should fire. Once they have, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |\n\n- `2.2-PrivateChannelsLifecycleEvents`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n\n## Resolving Ambiguous Intents\n\nAn FDC3 Desktop Agent MUST provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForContext that return multiple options). This is often accomplished by providing a user interface allowing the user to select the desired target application or intent and application.\n\nAs the methods of resolving ambiguous intents are often user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. These tests are based on the same applications defined for and used in other intent tests - however a separate manual test app should be provided to enable the test.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY)` |\n| User | 2. Chooser Interaction    | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousIntentTarget`: Perform above steps to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 2.  Chooser Interaction   | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E`,`F`,`G`,`H` and `I`. |\n\n- `2.0-ResolveAmbiguousContextTarget`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Open 4 Apps | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntent(\"sharedTestingIntent2\",testContextY)` |\n| User | 3. Chooser Interaction    | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousIntentTargetMultiInstance`:  Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n\n| App  | Step                      | Details |\n|------|---------------------------|---------|\n| Test | 1. Open 4 Apps            | Use `fdc3.open()` to open 2 instances of App `E` and 2 instances of `F`. |\n| Test | 2. Raise Ambiguous Intent | `fdc3.raiseIntentForContext(testContextY)` |\n| User | 3.  Chooser Interaction   | A method of resolving the ambiguous request is provided (such as a User Interface allowing the user to choose an application or instance) for choosing one of `E (1)`,`F (1)`,`E (2)`,`F (2)` and options to open `G`, `H` and `I` |\n\n- `2.0-ResolveAmbiguousContextTargetMultiInstance`: Perform above steps  to invoke intent resolution for an unspecified target with multiple options. Confirm that test is able to complete successfully.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/Metadata-Tests.md",
    "content": "---\nid: Metadata-Tests\nsidebar_label: Metadata Tests\ntitle: Metadata Tests\nhide_title: true\n---\n\n# Metadata & Instance Test Cases\n<!-- markdownlint-disable MD033 -->\n\nYou will need to pre-populate the AppDirectory with the following items:\n\n| App | Required Metadata                        |\n|-----|------------------------------------------|\n| A   | Generic AppD Record which contains at least the following fields:<br />- `name`<br />- `version`<br />- `title`<br />- `tooltip`<br />- `description`<br />- `icons` (`Array<Icon>`)<br />- `screenshots` (`Array<Image>`)<br />- `interop.intents.listensFor` (`aTestingIntent` with at least context type `testContextX`)  |\n\n## Retrieve `AppMetadata`\n\n| App    | Step              | Details                                                                                           |\n|--------|-------------------|---------------------------------------------------------------------------------------------------|\n| Test   | 1. getAppMetadata | Retrieve metadata for the configured app A with <br/> `const metadata1 = await fdc3.getAppMetadata({appId:\"<A's-appId>\"})`  |\n| Test   | 2. Confirm        | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set  |\n\n- `GetAppMetadata`: perform the above steps.\n\n## Instance Metadata\n\n| App  | Step               | Details                                                                                           |\n|------|--------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Open1           | Open a first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId: \"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test | 2. Open2           | Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId: \"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test | 3. getAppMetadata1 | Retrieve metadata for the first instance of the app with<br/> `const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |\n| Test | 4. Confirm1        | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches.  |\n| Test | 5. getAppMetadata2 | Retrieve metadata for the second instance of the app with <br/>`const metadata2 = fdc3.getAppMetadata(appIdentifier2)`  |\n| Test | 6. Confirm2        | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2`  |\n\n- `AppInstanceMetadata`: Perform the above steps.\n\n## Finding Instances\n\n| App  | Step              | Details                                                                                           |\n|------|-------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. Open1          | Open the first instance of App A using <br/> `const appIdentifier1 = await fdc3.open({appId:\"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId`.  |\n| Test | 2. Open2          | Open a second instance of App A using <br />`const appIdentifier2 = await fdc3.open({appId:\"<A's-appId>\"})` <br/>and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |\n| Test | 3. FindInstances  | Retrieve details of open instances of app A with <br/> `let instances = await fdc3.findInstances({appId:\"<A's-appId>\"})` <br/> confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array. |\n| Test | 4. RaiseIntent    | Use `appIdentifier1` to raise an intent and target that instance, with<br/> `const resolution = fdc3.raiseIntent(\"aTestingIntent\",{\"type\":\"testContextX\"},appIdentifier1)` |\n| Test | 5. Confirm1       | Check that `resolution.source` matches `appIdentifier1` |\n| A    | 6. ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |\n\n- `FindInstances`: Perform the above steps.\n\n## Getting Info For The Agent\n\n| App  | Step             | Details                                                                                           |\n|------|------------------|---------------------------------------------------------------------------------------------------|\n| Test | 1. getInfo       | Retrieve the `ImplementationMetadata` for the DesktopAgent with <br/> - `fdc3.getInfo().then((implMetadata) => { subsequent steps }`   <br />**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|\n| Test | 2. CheckVersion  | Check that the `fdc3Version` variable is present and at or greater than:  <br /> - 2.0  <br />(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):<br />`const isFDC3v2 = versionIsAtLeast(implMetadata, \"2.0\")`  |\n| Test | 3. CheckProvider | Check that the `provider` variable is present and not an empty string  |\n| Test | 4. CheckFeatures | Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values  |\n\n- `GetInfo1`: Perform the above steps.\n\n| App      | Step       | Details                                                                                           |\n|----------|------------|---------------------------------------------------------------------------------------------------|\n| Test     | 1. Open1   | Start an instance of App A with <br/>`const appIdentifier1 = await fdc3.open({appId:\"<A's-appId>\"})` <br /> retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |\n| A        | 2 .getInfo |   Retrieve the `ImplementationMetadata` for the DesktopAgent with: <br  />`fdc3.getInfo().then((implMetadata) => {  ... subsequent steps ...}` <br/> This should include `AppMetadata` for the retrieving app. |\n| A + Test | 3. Confirm | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |\n\n- `GetInfo2`: Perform the above steps.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/Open-Tests.md",
    "content": "---\nid: Open-Tests\nsidebar_label: Open Tests\ntitle: Open Tests\nhide_title: true\n---\n\n# Open Tests\n<!-- markdownlint-disable MD033 -->\n\n## A Opens B  \n\n| App | Step              | Description                                              |\n|-----|-------------------|----------------------------------------------------------|\n| A   | 1. Opening App    | App A calls a function (see below) to open a second app, B |\n| A   | 2. Check Metadata | Ensure that the correct app was opened |\n\n- `AOpensB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"})`\n- `AOpensB4`:   **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId:\"<app-B-ID>\"})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.\n\n## A Fails To Open Another App\n\n| App | Step                    | Description                                              |\n|-----|-------------------------|----------------------------------------------------------|\n| A   | 1. Opening App          | App A calls a function (see below) to try and open a non-existent app |\n| A   | 2. Check Error Response | `fdc3.open` returns a promise that rejects with an Error with the message \"App Not Found\" |\n\n- `AFailsToOpenB3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"})`\n\n## A Opens B With Context\n\n| App | Step               | Description                                              |\n|-----|--------------------|----------------------------------------------------------|\n| A   | 1. Opening App     |App A opens app B with an `fdc3.instrument` Context Object by calling a function (see below) |\n| B   | 2. Receive Context | Add an untyped context listener via: <br/>`fdc3.addContextListener(null,handler)` <br /> B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open()` call made by A |\n\n- `AOpensBWithContext3`:  **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:\n  - `fdc3.open({appId:\"<app-B-ID>\"}, <fdc3.instrument context>)`\n- `AOpensBWithSpecificContext`: Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener(\"fdc3.instrument\",handler)`\n- `AOpensBMultipleListen`:  Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener(\"fdc3.contact\",handler)` prior to the existing `addContextListener` for `fdc3.instrument`.  The correct context listener should receive the context, and the promise completes successfully.\n- `AOpensBWithWrongContext`: Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.\n  - Confirm that NO context is received.\n  - The promise returned to **A** by `fdc3.open` rejects with an Error with message `AppTimeout`\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/Overview.md",
    "content": "---\nid: Conformance-Overview\nsidebar_label: Overview\ntitle: FDC3 Conformance Tests\nhide_title: true\n---\n\n# FDC3 Conformance Tests\n\nThis section contains test definitions that are used to test for conformance of a Desktop Agent API implementation with FDC3.\n\n:::note\n\nFDC3 2.2 introduces both a new interface to web-based FDC3 Desktop Agent, known as a \"Desktop Agent Proxy\", as an alternative to the injection of the FDC3 API at `window.fdc3`, which is now know as a \"Desktop Agent Preload\" interface `GetAgent`. 2.2 also introduces the [`getAgent`](../ref/GetAgent) function which can be used to connect to either interface and MUST be used by conformance testing apps to retrieve a interface (whichever is provided by the Desktop Agent being tested).\n\n:::\n\n:::info\n\nWhere tests were introduced in this version of FDC3, they are labelled with an in the header, like so: ![2.2](https://img.shields.io/badge/FDC3-2.2-purple)\n\n:::\n\nThere are currently 6 sections to the tests.  \n\n- [Basic Tests](Basic-Tests.md)\n- [Open Tests](Open-Tests.md)\n- [User Channel Tests](User-Channel-Tests.md)\n- [App Channel Tests](App-Channel-Tests.md)\n- [Metadata Tests](Metadata-Tests.md)\n- [Intents Tests](Intents-Tests.md)\n\nYou can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/conformance/User-Channel-Tests.md",
    "content": "---\nid: User-Channel-Tests\nsidebar_label: User Channel Tests\ntitle: User Channel Tests\nhide_title: true\n---\n\n# User Channel Tests\n<!-- markdownlint-disable MD033 -->\n\n## Basic Broadcast\n\n| App | Step                  | Details                                                                          |\n|-----|-----------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener | A adds an _unfiltered_ Context Listener using `addContextListener(null,handler)`. <br/>A promise resolving to  a `Listener` object is returned <br />Check that this has an `unsubscribe` method. |\n| A   | 2. joinUserChannel    | A joins the first available (non-global) user channel.  The available Channels are retrieved with: <br/>`fdc3.getUserChannels()` <br/> The first channel (that does not have the id 'global') is joined with: <br/>`fdc3.joinUserChannel(<channelId>)`  |\n| B   | 3. joinUserChannel    | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast(<fdc3.instrument>)`. <br/>Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the instrument object, matching the one broadcast by B.  |\n\n- `UCBasicUsage1` Perform above test.\n- `UCBasicUsage2` Perform steps in order: 2,1,3,4,5 to confirm that the order of `joinUserChannel` and `addContextListener` calls doesn't matter.\n- `UCBasicUsage3` Perform steps in order: 3,4,1,2,5 to confirm that the current context is automatically received on joining a channel.\n- `UCBasicUsage4` Perform steps in order: 3,4,2,1,5  to confirm that the current context is automatically received on adding a context listener to an already joined a channel.\n\n## Filtered Broadcast\n\n| App | Step                  | Details                                                                          |\n|-----|-----------------------|----------------------------------------------------------------------------------|\n| A   | 1. addContextListener | A adds an `fdc3.instrument` _typed_ Context Listener using `addContextListener(\"fdc3.instrument\",handler)`. <br/>A promise resolving a `Listener` object is returned <br />Check that this has an `unsubscribe` function.|\n| A   | 2. joinUserChannel    | A joins the first available user channel using: <br/>`getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel    | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast          | B broadcasts: <br/> 1.`fdc3.broadcast(<fdc3.instrument>)`. <br/> 2. `fdc3.broadcast(<fdc3.contact>)` <br />Check a `void` promise is returned. |\n| A   | 5. Receive Context    | A receives the `fdc3.instrument` object, matching the one broadcast by B. <br />Check that the `fdc3.contact` is NOT received. |\n\n- `UCFilteredUsage1` Perform above test.\n- `UCFilteredUsage2` Perform steps in order: 2,1,3,4,5.\n- `UCFilteredUsage3` Perform steps in order: 3,4,1,2,5.\n- `UCFilteredUsage4` Perform steps in order: 3,4,2,1,5.\n\n## Broadcast With Multiple Listeners\n\n| App | Step                   | Details                                                                                                     |\n|-----|------------------------|-------------------------------------------------------------------------------------------------------------|\n| A   | 1. addContextListeners | A sets up two Context Listeners.  One for `fdc3.instrument` and one for `fdc3.contact` by calling:  `addContextListener (\"fdc3.instrument\",handler)` <br/> `addContextListener(\"fdc3.contact\",handler)` <br/>A promise resolving a `Listener` object is returned for each. <br />Check that this has an `unsubscribe` method for each.  |\n| A   | 2. joinUserChannel     | A joins the first available user channel using: <br/>`getUserChannels()` Check **user** channels are returned.<br/>Call `fdc3.joinChannel()` on the first non-global channel.|\n| B   | 3. joinUserChannel     | B joins the same channel as A, via the same process in 2. |\n| B   | 4. Broadcast           | `fdc3.broadcast(<fdc3.instrument>)` <br/> `fdc3.broadcast(<fdc3.contact>)` . |\n| A   | 5. Receive Context     | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.<br />A's `fdc3.contact` object matches the one broadcast  by B, and arrives on the correct listener. |\n\n- `UCFilteredUsage5`: Perform above test.\n- `UCFilteredUsage6`: Perform above test, except B will join a _different_ channel to A. Check that you _don't_ receive anything.\n- `UCFilteredUsageChange`: Perform above test, except that after joining, **A** changes channel to a _different_ channel via a further call to `fdc3.joinUserChannel`.  Check that **A** does NOT receive anything.\n- `UCFilteredUsageUnsubscribe`: Perform above test, except that after joining, **A** then `unsubscribe()`s from the channel using the `listener.unsubscribe` function. Check that **A** does NOT receive anything.\n- `UCFilteredUsageLeave`: Perform above test, except that immediately after joining, **A** _leaves the channel_, and so receives nothing.\n- `UCFilteredUsageNoJoin`: Perform the above test, but skip step 2 so that **A** does NOT join a channel. Confirm that the _current channel_ for **A** is NOT set before continuing with the rest of the test.  **A** should receive nothing.\n\n## Event on channel changed\n\n![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface `addEventListener` function was added allowing an app to listen for events raised. In 2.2 only one event is supported, `userChannelChanged`.\n\nAn FDC3 Desktop Agent MUST provide a method to set the current User Channel for an application. This is often accomplished by providing a control within the user interface of a window or frame, allowing the user to select the desired channel.\n\nAs the method of setting the user channel is user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. A separate manual test app should be provided to enable the test.\n\n| App                 | Step                                       | Details |\n|---------------------|--------------------------------------------|---------|\n| ChannelChangedEvent | 1. Open the test application               | A dedicated test application for  FDC3ChannelChangedEvent should be opened. |\n| ChannelChangedEvent | 2. Register for `userChannelChanged` event | `await fdc3.addEventListener(\"userChannelChanged\", handler);`<br />The `handler` function should log or render details of events received|\n| User                | 3. Set User Channel                        | The user should set the current user channel of the app and change it a few times. Details of each change should be displayed by the test app. |\n\n- `2.2-ChannelChangedEvent`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/Channel.md",
    "content": "---\nid: Channel\nsidebar_label: Channel\ntitle: Channel\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `Channel`\n\nRepresents a context channel that applications can join to share context data and provides functions for interacting with it.\n\nA channel can be either a [\"User\" channel](../spec#joining-user-channels) (retrieved with [`getUserChannels`](DesktopAgent#getuserchannels)), a custom [\"App\" channel](../spec#app-channels) (obtained through [`getOrCreateChannel`](DesktopAgent#getorcreatechannel)) or a [\"Private\" channel](../spec#private-channels) (obtained via an intent result).\n\n:::note\n\nThere are differences in behavior when you interact with a User channel via the Desktop Agent interface and the Channel interface. Specifically, when 'joining' a User channel or adding a context listener when already joined to a channel via the `DesktopAgent` interface, existing context (matching the type of the context listener) on the channel is received by the context listener immediately. Whereas, when add a context listener via the Channel interface, context is not received automatically, but may be retrieved manually via the [`getCurrentContext()`](#getcurrentcontext) function.\n\n:::\n\nChannels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Channel {\n  // properties\n  id: string;\n  type: \"user\" | \"app\" | \"private\";\n  displayMetadata?: DisplayMetadata;\n\n  // functions\n  broadcast(context: Context): Promise<void>;\n  getCurrentContext(contextType?: string): Promise<Context|null>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n  \n  //deprecated functions\n  /**\n   * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n   */\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IChannel: IIntentResult\n{\n    string Id { get; }\n    ChannelType Type { get; }\n    IDisplayMetadata? DisplayMetadata { get; }\n    Task Broadcast(IContext context);\n    Task<IContext?> GetCurrentContext(string? contextType);\n    Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n\n## Properties\n\n### `id`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly id: string;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nstring Id { get; }\n```\n\n</TabItem>\n</Tabs>\n\nUniquely identifies the channel. It is either assigned by the desktop agent (User Channel) or defined by an application (App Channel).\n\n### `type`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly type: \"user\" | \"app\" | \"private\";\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nChannelType Type { get; }\n\npublic enum ChannelType\n{\n    User = 1,\n    App = 2,\n    Private = 3\n}\n```\n\n</TabItem>\n</Tabs>\n\nCan be _user_,  _app_ or _private_.\n\n### `displayMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic readonly displayMetadata?: DisplayMetadata;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIDisplayMetadata? DisplayMetadata { get; }\n```\n\n</TabItem>\n</Tabs>\n\nDisplayMetadata can be used to provide display hints for User Channels intended to be visualized and selectable by end users.\n\n**See also:**\n\n- [`DisplayMetadata`](Metadata#displaymetadata)\n\n## Functions\n\n### `addContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.\n\nIf, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the [`getCurrentContext(contextType)`](#getcurrentcontext) function.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**Examples:**\n\nAdd a listener for any context that is broadcast on the channel:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst listener = await channel.addContextListener(null, context => {\n    if (context.type === 'fdc3.contact') {\n        // handle the contact\n    } else if (context.type === 'fdc3.instrument') => {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIChannel channel;\nvar listener = await channel.AddContextListener<IContext>(null, (context, metadata) => {\n    if (context.Type == ContextTypes.Contact)\n    {\n        // handle the contact\n    }\n    else if (context.Type == ContextTypes.Instrument) {\n        // handle the instrument\n    }\n});\n\n// later\nlistener.Unsubscribe();\n```\n\n</TabItem>\n</Tabs>\n\nAdding listeners for specific types of context that is broadcast on the channel:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst contactListener = await channel.addContextListener('fdc3.contact', contact => {\n    // handle the contact\n});\n\nconst instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar contactListener = await channel.AddContextListener<Contact>(\"fdc3.contact\", (contact, metadata) => {\n    // handle the contact\n});\n\nvar instrumentListener = await channel.AddContextListener<Instrument>(\"fdc3.instrument\", (instrument, metadata) => {\n    // handle the instrument\n});\n\n// later\ncontactListener.unsubscribe();\ninstrumentListener.unsubscribe();\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`ContextHandler`](Types#contexthandler)\n- [`broadcast`](#broadcast)\n- [`getCurrentContext`](#getcurrentcontext)\n\n### `broadcast`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic broadcast(context: Context): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Broadcast(IContext context);\n```\n\n</TabItem>\n</Tabs>\n\nBroadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of.\n\nIf the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\nChannel implementations should ensure that context messages broadcast by an application on a channel should not be delivered back to that same application if they are joined to the channel.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [FDC3 Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\ntry {\n    channel.broadcast(instrument);\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar instrument = new Instrument(new InstrumentID() { Ticker = \"AAPL\" });\n\ntry\n{\n    channel.Broadcast(instrument);\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`getCurrentContext`](#getcurrentcontext)\n- [`addContextListener`](#addcontextlistener)\n\n### `getCurrentContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\npublic getCurrentContext(contextType?: string): Promise<Context|null>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IContext?> GetCurrentContext(string? contextType);\n```\n\n</TabItem>\n</Tabs>\n\nWhen a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found.\n\nIf no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned.  If no context has been set on the channel, it will return `null`.\n\nIt is up to the specific Desktop Agent implementation whether and how recent contexts are stored. For example, an implementation could store context history for a channel in a single array and search through the array for the last context matching a provided type, or context could be maintained as a dictionary keyed by context types. An implementation could also choose not to support context history, in which case this method will return `null` for any context type not matching the type of the most recent context.\n\nIf getting the current context fails, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Examples:**\n\nWithout specifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const context = await channel.getCurrentContext();\n} catch (err: ChannelError) {\n    // handle error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.GetCurrentContext();\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n</Tabs>\n\nSpecifying a context type:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const contact = await channel.getCurrentContext('fdc3.contact');\n} catch (err: ChannelError) {\n    // handler error\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var context = await channel.GetCurrentContext(\"fdc3.contact\");\n}\ncatch (Exception ex)\n{\n    // handle error\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ChannelError`](Errors#channelerror)\n- [`broadcast`](#broadcast)\n- [`addContextListener`](#addcontextlistener)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n/**\n * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`\n */\npublic addContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented\n```\n\n</TabItem>\n\n</Tabs>\n\nAdds a listener for incoming contexts whenever a broadcast happens on the channel.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/DesktopAgent.md",
    "content": "---\nid: DesktopAgent\nsidebar_label: DesktopAgent\ntitle: DesktopAgent\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `DesktopAgent`\n\nAn FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain.\n\nA Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nFor details of how implementations of the `DesktopAgent` are made available to applications please see [Supported Platforms](../supported-platforms).\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface DesktopAgent {\n  // apps\n  open(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n  findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n  getAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n\n  // context\n  broadcast(context: Context): Promise<void>;\n  addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n\n  // intents\n  findIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n  findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n  raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n  addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n\n  // channels\n  getOrCreateChannel(channelId: string): Promise<Channel>;\n  createPrivateChannel(): Promise<PrivateChannel>;\n  getUserChannels(): Promise<Array<Channel>>;\n\n  // OPTIONAL channel management functions\n  joinUserChannel(channelId: string) : Promise<void>;\n  getCurrentChannel() : Promise<Channel | null>;\n  leaveCurrentChannel() : Promise<void>;\n\n  // non-context events\n  addEventListener(type: FDC3EventTypes  | null, handler: EventHandler): Promise<Listener>;\n\n  //implementation info\n  getInfo(): Promise<ImplementationMetadata>;\n\n  //Deprecated functions\n  addContextListener(handler: ContextHandler): Promise<Listener>;\n  getSystemChannels(): Promise<Array<Channel>>;\n  joinChannel(channelId: string) : Promise<void>;\n  open(name: string, context?: Context): Promise<AppIdentifier>;\n  raiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n  raiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IDesktopAgent\n{\n    // Apps\n    Task<IAppIdentifier> Open(IAppIdentifier app, IContext? context = null);\n    Task<IEnumerable<IAppIdentifier>> FindInstances(IAppIdentifier app);\n    Task<IAppMetadata> GetAppMetadata(IAppIdentifier app);\n\n    // Context\n    Task Broadcast(IContext context);\n    Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n\n    // Intents\n    Task<IAppIntent> FindIntent(string intent, IContext? context = null, string? resultType = null);\n    Task<IEnumerable<IAppIntent>> FindIntentsByContext(IContext context, string? resultType = null);\n    Task<IIntentResolution> RaiseIntent(string intent, IContext context, IAppIdentifier? app = null);\n    Task<IIntentResolution> RaiseIntentForContext(IContext context, IAppIdentifier? app = null);\n    Task<IListener> AddIntentListener<T>(string intent, IntentHandler<T> handler) where T : IContext;\n\n    // Channels\n    Task<IChannel> GetOrCreateChannel(string channelId);\n    Task<IPrivateChannel> CreatePrivateChannel();\n    Task<IEnumerable<IChannel>> GetUserChannels();\n\n    // non-context events\n    Task<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n\n    // OPTIONAL channel management functions\n    Task JoinUserChannel(string channelId);\n    Task<IChannel?> GetCurrentChannel();\n    Task LeaveCurrentChannel();\n\n    // Implementation Information\n    Task<IImplementationMetadata> GetInfo();\n}\n```\n\n</TabItem>\n</Tabs>\n\n## Functions\n\n### `addContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or [`fdc3.open`](#open) API call). If the consumer is only interested in a context of a particular type, they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.\n\nContext broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from User channels. If this function is called after the app has already joined a channel and the channel already contains context that matches the type of the context listener, then it will be called immediately and the context passed to the handler function. If `null` was passed as the context type for the listener and the channel contains context, then the handler function will be called immediately with the most recent context - regardless of type.\n\nContext may also be received via this listener if the application was launched via a call to  [`fdc3.open`](#open), where context was passed as an argument. In order to receive this, applications SHOULD add their context listener as quickly as possible after launch, or an error MAY be returned to the caller and the context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the Desktop Agent implementation.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// any context\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n// listener for a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });\n\n// listener that logs metadata for the message a specific type\nconst contactListener = await fdc3.addContextListener('fdc3.contact', (contact, metadata) => {\n  console.log(`Received context message\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n  //do something else with the context\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// any context\nvar listener = await _desktopAgent.AddContextListener<IContext>(null, (context, meatadata) => { ... });\n\n// listener for a specific type\nvar listener = await _desktopAgent.AddContextListener<Instrument>(\"fdc3.contact\", (contact, metadata) => { ... });\n\n// listener that logs metadata for the message of a specific type\nvar contactListener = await _desktopAgent.AddContextListener<Contact>(\"fdc3.contact\", (contact, metadata) => {\n  System.Diagnostics.Debug.WriteLine($\"Received context message\\nContext: {contact}\\nOriginating app: {metadata?.Source}\");\n  // do something else with the context\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`ContextHandler`](Types#contexthandler)\n\n### `addEventListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddEventListener(type: FDC3EventTypes  | null, handler: EventHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n```\n\n</TabItem>\n</Tabs>\n\nRegisters a handler for non-context and non-intent events from the Desktop Agent. If the consumer is only interested in an event of a particular type, they can specify that type. If the consumer is able to receive events of any type or will inspect types received, then they can pass `null` as the `type` parameter to receive all event types.\n\nWhenever the handler function is called it will be passed an event object with details related to the event.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// any event type\nconst listener = await fdc3.addEventListener(null, event => { ... });\n\n// listener for a specific event type that logs its details\nconst userChannelChangedListener = await fdc3.addEventListener(\"userChannelChanged\", event => { \n  console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n  //do something else with the event\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar listener = await _desktopAgent.AddEventListener(null, (event) => { ... });\n\nvar userChannelChangedListener = await _desktopAgent.AddEventListener(\"userChannelChanged\", (event) => {\n  System.Diagnostics.Debug.Write($\"Received event ${event.Type}\\n\\tDetails: ${event.Details}\");\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`FDC3EventTypes`](./Events#fdc3eventtypes)\n- [`FDC3Event`](./Events#fdc3event)\n- [`EventHandler`](./Events#eventhandler)\n\n### `addIntentListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddIntentListener<T>(string intent, IntentHandler<T> handler) where T : IContext;\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming intents raised by other applications, via calls to [`fdc3.raiseIntent`](#raiseintent) or [`fdc3.raiseIntentForContext`](#raiseintentforcontext). If the application is intended to be launched to resolve raised intents, it SHOULD add its intent listeners as quickly as possible after launch or an error MAY be returned to the caller and the intent and context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.\n\nThe handler function may return void or a promise that resolves to a [`IntentResult`](Types#intentresult), which is either a [`Context`](Types#context) object, representing any data that should be returned to the app that raised the intent, or a [`Channel`](Channel), a [`PrivateChannel`](PrivateChannel) over which data responses will be sent, or `void`. The `IntentResult` will be returned to the app that raised the intent via the [`IntentResolution`](Metadata#intentresolution) and retrieved from it using the `getResult()` function.\n\nThe Desktop Agent MUST reject the promise returned by the `getResult()` function of `IntentResolution` if any of the following is true:\n\n1. The intent handling function's returned promise rejects.\n2. The intent handling function returns something other than a promise.\n3. The returned promise resolves to an invalid type.\n\nThe [`PrivateChannel`](PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n//Handle a raised intent\nconst listener = fdc3.addIntentListener('StartChat', context => {\n  // start chat has been requested by another application\n  return;\n});\n\n//Handle a raised intent and log the originating app metadata\nconst listener = fdc3.addIntentListener('StartChat', (contact, metadata) => {\n  console.log(`Received intent StartChat\\nContext: ${contact}\\nOriginating app: ${metadata?.source}`);\n    return;\n});\n\n//Handle a raised intent and return Context data via a promise\nfdc3.addIntentListener(\"CreateOrder\", (context) => {\n  return new Promise<Context>((resolve) => {\n    // go create the order\n    resolve({type: \"fdc3.order\", id: { \"orderId\": 1234}});\n  });\n});\n\n//Handle a raised intent and return a PrivateChannel over which response will be sent\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel: PrivateChannel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // Called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // Stop the feed if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n//Handle a raised intent\nvar listener = await _desktopAgent.AddIntentListener<IContext>(\"StartChat\", (context, metadata) => {\n    // start chat has been requested by another application\n    // return IIntentResult;\n});\n\n//Handle a raised intent and log the originating app metadata\nvar listener = await _desktopAgent.AddIntentListener<IContext>(\"StartChat\", (contact, metadata) => {\n    System.Diagnostics.Debug.Write($\"Received intent StartChat\\nContext: {contact}\\nOriginating app: {metadata?.Source}\");\n    // return IIntentResult;\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Register an Intent Handler](../spec#register-an-intent-handler)\n- [`PrivateChannel`](PrivateChannel)\n- [`Listener`](Types#listener)\n- [`Context`](Types#context)\n- [`IntentHandler`](Types#intenthandler)\n\n### `broadcast`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nbroadcast(context: Context): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Broadcast(IContext context);\n```\n\n</TabItem>\n</Tabs>\n\nPublishes context to other apps on the desktop.  Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User Channel_ the app is joined to.  If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect.  Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.\n\nDesktopAgent implementations SHOULD ensure that context messages broadcast to a channel by an application joined to it are not delivered back to that same application.\n\nIf you are working with complex context types composed of other simpler types (as recommended by the [Context Data specification](../../context/spec#assumptions)) then you should broadcast each individual type (starting with the simpler types, followed by the complex type) that you want other apps to be able to respond to. Doing so allows applications to filter the context types they receive by adding listeners for specific context types.\n\nIf an application attempts to broadcast an invalid context argument the Promise returned by this function should reject with the [`ChannelError.MalformedContext` error](Errors#channelerror).\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    id: {\n        ticker: 'AAPL'\n    }\n};\n\nfdc3.broadcast(instrument);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nInstrument instrument = new Instrument(\n    new InstrumentID()\n    {\n        Ticker = \"AAPL\"\n    }\n);\n\n_desktopAgent.Broadcast(instrument);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [addContextListener](#addcontextlistener)\n\n### `createPrivateChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ncreatePrivateChannel(): Promise<PrivateChannel>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IPrivateChannel> CreatePrivateChannel();\n```\n\n</TabItem>\n</Tabs>\n\nReturns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.\n\nIf the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\nThe `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n  const channel = await fdc3.createPrivateChannel();\n  const symbol = context.id.ticker;\n\n  // This gets called when the remote side adds a context listener\n  const addContextListener = channel.onAddContextListener((contextType) => {\n    // broadcast price quotes as they come in from our quote feed\n    feed.onQuote(symbol, (price) => {\n      channel.broadcast({ type: \"price\", price});\n    });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  const unsubscribeListener = channel.onUnsubscribe((contextType) => {\n    feed.stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  const disconnectListener = channel.onDisconnect(() => {\n    feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n_desktopAgent.AddIntentListener<Instrument>(\"QuoteStream\", async (context, metadata) => {\n  var channel = await _desktopAgent.CreatePrivateChannel();\n  var symbol = context?.ID?.Ticker;\n\n  // This gets called when the remote side adds a context listener\n  var addContextListener = channel.OnAddContextListener((contextType) => {\n      // broadcast price quotes as they come in from our quote feed\n      _feed.OnQuote(symbol, (price) => {\n          channel.Broadcast(new Price(price));\n      });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  var unsubscribeListener = channel.OnUnsubscribe((contextType) => {\n      _feed.Stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  var disconnectListener = channel.OnDisconnect(() => {\n      _feed.stop(symbol);\n  });\n\n  return channel;\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`PrivateChannel`](PrivateChannel)\n- [`raiseIntent`](#raiseintent)\n- [`addIntentListener`](#addintentlistener)\n\n### `findInstances`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IAppIdentifier>> FindInstances(IAppIdentifier app);\n```\n\n</TabItem>\n</Tabs>\n\nFind all the available instances for a particular application.\n\nIf the application is not known to the agent, the returned promise should be rejected with the `ResolverError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array.\n\nIf the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// Retrieve a list of instances of an application\nlet instances = await fdc3.findInstances({appId: \"MyAppId\"});\n\n// Target a raised intent at a specific instance\nlet resolution = fdc3.raiseIntent(\"ViewInstrument\", context, instances[0]);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Retrieve a list of instances of an application\nvar instances = await _desktopAgent.FindInstances(new AppIdentifier(\"MyAppId\"));\n\n// Target a raised intent at a specific instance\nvar resolution = await _desktopAgent.RaiseIntent(\"ViewInstrument\", context, instances.First());\n```\n\n</TabItem>\n</Tabs>\n\n### `findIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindIntent(intent: string, context?: Context, resultType?: string): Promise<AppIntent>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppIntent> FindIntent(string intent, IContext? context = null, string? resultType = null);\n```\n\n</TabItem>\n</Tabs>\n\nFind out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type.\n\n`findIntent` is effectively granting programmatic access to the Desktop Agent's resolver.\nIt returns a promise resolving to an `AppIntent` which provides details of the intent, its metadata and metadata about the apps and app instances that are registered to handle it. This can be used to raise the intent against a specific app or app instance.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no apps are found that resolve the intent, when the [`ResolveError.NoAppsFound`](Errors#resolveerror) message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nResult types 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.\n\n**Examples:**\n\nI know 'StartChat' exists as a concept, and want to know which apps can resolve it:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns a single AppIntent:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Slack\" }\n//   ]\n// }\n\n// raise the intent against a particular app\nawait fdc3.raiseIntent(appIntent.intent.name, context, appIntent.apps[0]);\n\n//later, we want to raise 'StartChat' intent again\nconst appIntent = await fdc3.findIntent(\"StartChat\");\n// returns an AppIntent, but with multiple options for resolution,\n// which includes an existing instance of an application:\n// {\n//   intent: { name: \"StartChat\" },\n//   apps: [\n//    { appId: \"Skype\" },\n//    { appId: \"Symphony\" },\n//    { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//    { appId: \"Slack\" }\n//   ]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\");\n\n// raise the intent against a particular app\nawait _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\n```\n\n</TabItem>\n</Tabs>\n\nAn optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntent = await fdc3.findIntent(\"StartChat\", contact);\n\n// returns only apps that support the type of the specified input context:\n// {\n//     intent: { name: \"StartChat\" },\n//     apps: { name: \"Symphony\" }]\n// }\n\nconst appIntent = await fdc3.findIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     intent: { name: \"ViewContact\" },\n//     apps: { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }\n\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     intent: { name: \"QuoteStream\" },\n//     apps: { appId: \"MyOMS\", resultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", contact);\n// returns only apps that support the type of the specified input context:\n// {\n//     Intent: { Name: \"StartChat\" },\n//     Apps: { Name: \"Symphony\" }]\n// }\n\nvar appIntent = await _desktopAgent.FindIntent(\"ViewContact\", \"fdc3.ContactList\");\n// returns only apps that return the specified result type:\n// {\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }\n\nvar appIntent = await _desktopAgent.fFindIntent(\"QuoteStream\", instrument, \"channel<fdc3.Quote>\");\n// returns only apps that return a channel which will receive the specified input and result types:\n// {\n//     Intent: { Name: \"QuoteStream\" },\n//     Apps: { AppId: \"MyOMS\", ResultType: \"channel<fdc3.Quote>\"}]\n// }\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ResolveError`](Errors#resolveerror)\n\n### `findIntentsByContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfindIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IAppIntent>> FindIntentsByContext(IContext context, string? resultType = null);\n```\n\n</TabItem>\n</Tabs>\n\nFind all the available intents for a particular context, and optionally a desired result context type.\n\n`findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.\nA 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.\n\nIf the resolution fails, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. This includes the case where no intents with associated apps are found, when the `ResolveError.NoAppsFound` message should be used, and when an invalid context object is passed as an argument, when the [`ResolveError.MalformedContext`](Errors#resolveerror) message should be used.\n\nThe 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 without a specified context type, 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.\n\n**Example:**\n\nI 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...\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntents = await fdc3.findIntentsByContext(context);\n\n// returns, for example:\n// [\n//   {\n//     intent: { name: \"StartCall\" },\n//     apps: [{ appId: \"Skype\" }]\n//   },\n//   {\n//     intent: { name: \"StartChat\" },\n//     apps: [\n//       { appId: \"Skype\" },\n//       { appId: \"Symphony\" },\n//       { appId: \"Symphony\", instanceId: \"93d2fe3e-a66c-41e1-b80b-246b87120859\" },\n//       { appId: \"Slack\" }\n//     ]\n//   },\n//   {\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n//   }\n// ];\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntents = await _desktopAgent.FindIntentsByContext(context);\n```\n\n</TabItem>\n</Tabs>\n\nor I look for only intents that are resolved by apps returning a particular result type\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst appIntentsForType = await fdc3.findIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     intent: { name: \"ViewContact\" },\n//     apps: [{ appId: \"Symphony\" }, { appId: \"MyCRM\", resultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nconst startChat = appIntents[1];\n\n// target a particular app or instance\nconst selectedApp = startChat.apps[2];\n\n// raise the intent, passing the given context, targeting the app\nawait fdc3.raiseIntent(startChat.intent.name, context, selectedApp);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIntentsForType = await _desktopAgent.FindIntentsByContext(context, \"fdc3.ContactList\");\n// returns for example:\n// [{\n//     Intent: { Name: \"ViewContact\" },\n//     Apps: [{ AppId: \"Symphony\" }, { AppId: \"MyCRM\", ResultType: \"fdc3.ContactList\"}]\n// }];\n\n// select a particular intent to raise\nvar startChat = appIntentsForType.First();\n\n// target a particular app or instance\nvar selectedApp = startChat.Apps.First();\n\n// raise the intent, passing the given context, targeting the app\nawait _desktopAgent.RaiseIntent(startChat.Intent.Name, context, selectedApp);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`findIntent()`](#findintent)\n- [`ResolveError`](Errors#resolveerror)\n\n### `getAppMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetAppMetadata(app: AppIdentifier): Promise<AppMetadata>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppMetadata> GetAppMetadata(IAppIdentifier app);\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves the [`AppMetadata`](Metadata#appmetadata) for an [`AppIdentifier`](Types#appidentifier), which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes.\n\nIf the app is not found, the promise MUST be rejected with an `Error` Object with the `message` given by [`ResolveError.TargetAppUnavailable`](Errors#resolveerror), or (if connected to a Desktop Agent Bridge) an error from the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nlet appIdentifier = { appId: \"MyAppId@my.appd.com\" }\nlet appMetadata = await fdc3.getAppMetadata(appIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appIdentifier = new AppIdentifier(\"MyAppId@my.appd.com\");\nvar appMetadata = await _desktopAgent.GetAppMetadata(appIdentifier);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`AppIdentifier`](Types#appidentifier)\n\n### `getCurrentChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetCurrentChannel() : Promise<Channel | null>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IChannel?> GetCurrentChannel();\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that returns the `Channel` object for the current User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nReturns `null` if the app is not joined to a channel.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// get the current channel membership\nlet current = await fdc3.getCurrentChannel();\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// get the current channel membership\nvar current = await _desktopAgent.GetCurrentChannel();\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getInfo`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetInfo(): Promise<ImplementationMetadata>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IImplementationMetadata> GetInfo();\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves information about the FDC3 Desktop Agent implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent.\n\nReturns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.  This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nimport {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar version = (await _desktopAgent.GetInfo()).Fdc3Version;\n```\n\n</TabItem>\n</Tabs>\n\nThe `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nlet implementationMetadata = await fdc3.getInfo();\nlet {appId, instanceId} = implementationMetadata.appMetadata;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar implementationMetadata = await _desktopAgent.GetInfo();\nvar appId = implementationMetadata.AppMetadata.AppId;\nvar instanceId = implementationMetadata.AppMetadata.InstanceId;\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`ImplementationMetadata`](Metadata#implementationmetadata)\n- [`AppMetadata`](Metadata#appmetadata)\n\n### `getOrCreateChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetOrCreateChannel(channelId: string): Promise<Channel>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IChannel> GetOrCreateChannel(string channelId);\n```\n\n</TabItem>\n</Tabs>\n\nReturns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist.\n\nIf the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const myChannel = await fdc3.getOrCreateChannel(\"myChannel\");\n  myChannel.addContextListener(null, context => { /* do something with context */});\n}\ncatch (err: ChannelError) {\n  //app could not register the channel\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var myChannel = await _desktopAgent.GetOrCreateChannel(\"myChannel\");\n    await myChannel.AddContextListener<IContext>(null, (context, metadata) => { /* do something with context */});\n}\ncatch (Exception ex)\n{\n    //app could not register the channel\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `getUserChannels`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetUserChannels() : Promise<Array<Channel>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IEnumerable<IChannel>> GetUserChannels();\n```\n\n</TabItem>\n</Tabs>\n\nRetrieves a list of the User Channels available for the app to join.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\nconst userChannels = await fdc3.getUserChannels();\nconst redChannel = userChannels.find(c => c.id === 'red');\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar userChannels = await _desktopAgent.GetUserChannels();\nvar redChannel = userChannels.First(c => c.Id == \"red\");\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n\n### `joinUserChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\njoinUserChannel(channelId: string) : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask JoinUserChannel(string channelId);\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nIf an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.\n\nIf the channel already contains context that would be passed to context listeners added via `fdc3.addContextListener` then those listeners will be called immediately with that context.\n\nAn app can only be joined to one channel at a time.\n\nIf an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// get all user channels\nconst channels = await fdc3.getUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\nfdc3.joinUserChannel(selectedChannel.id);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// get all user channels\nvar channels = await _desktopAgent.GetUserChannels();\n\n// create UI to pick from the User channels\n\n// join the channel on selection\n_desktopAgent.JoinUserChannel(selectedChannel.Id);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `leaveCurrentChannel`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nleaveCurrentChannel() : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask LeaveCurrentChannel();\n```\n\n</TabItem>\n</Tabs>\n\nOPTIONAL function that removes the app from any User channel membership.  In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.\n\nContext broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n//desktop-agent scope context listener\nconst fdc3Listener = fdc3.addContextListener(null, context => {});\n\nawait fdc3.leaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.addContextListener(null, channelListener);\n\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n//desktop-agent scope context listener\nvar fdc3Listener = await _desktopAgent.AddContextListener<IContext>(null, (context, metadata) => { });\n\nawait _desktopAgent.LeaveCurrentChannel();\n//the fdc3Listener will now cease receiving context\n\n//listening on a specific channel though, will continue to work\nredChannel.AddContextListener(null, channelListener);\n```\n\n</TabItem>\n</Tabs>\n\n### `open`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nopen(app: AppIdentifier, context?: Context): Promise<AppIdentifier>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IAppIdentifier> Open(IAppIdentifier app, IContext? context = null);\n```\n\n</TabItem>\n</Tabs>\n\nLaunches an app, specified via an [`AppIdentifier`](Types#appidentifier) object.\n\nThe `open` method differs in use from [`raiseIntent`](#raiseintent).  Generally, it should be used when the target application is known but there is no specific intent.  For example, if an application is querying an App Directory, `open` would be used to open an app returned in the search results.\n\n**Note**, if the intent, context and target app name are all known, it is recommended to instead use [`raiseIntent`](#raiseintent) with the `target` argument.\n\nIf a [`Context`](Types#context) object is passed in, this object will be provided to the opened application via a contextListener. The Context argument is functionally equivalent to opening the target app with no context and broadcasting the context directly to it.\n\nReturns an [`AppIdentifier`](Types#appidentifier) object with the `instanceId` field set to identify the instance of the application opened by this call.\n\nIf an error occurs while opening the app, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`OpenError`](Errors#openerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n ```js\n// Open an app without context, using an AppIdentifier object to specify the target\nlet appIdentifier = { appId: 'myApp-v1.0.1' };\nlet instanceIdentifier = await fdc3.open(appIdentifier);\n\n// Open an app with context\nlet instanceIdentifier = await fdc3.open(appIdentifier, context);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Open an app without context, using an AppIdentifier object to specify the target\nvar appIdentifier = new AppIdentifier(\"myApp-v1.0.1\");\nvar instanceIdentifier = await _desktopAgent.Open(appIdentifier);\n\n// Open an app with context\nvar instanceIdentifier = await _desktopAgent.Open(appIdentifier, context);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppMetadata`](Metadata#appmetadata)\n- [`OpenError`](Errors#openerror)\n\n### `raiseIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IIntentResolution> RaiseIntent(string intent, IContext context, IAppIdentifier? app = null);\n```\n\n</TabItem>\n</Tabs>\n\nRaises a specific intent for resolution against apps registered with the desktop agent.\n\nThe 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.\nAlternatively, 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).\n\nIf 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, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\nIf 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.\n\nReturns an [`IntentResolution`](Metadata#intentresolution) object with details of the app instance that was selected (or started) to respond to the intent.\n\nIssuing 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, Channel object or void 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 valid response (a promise or void), or (3) the returned promise resolves to an invalid type.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait fdc3.raiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Raise an intent without a context by using the null context type\nawait fdc3.raiseIntent(\"StartChat\", {type: \"fdc3.nothing\"});\n\n//Raise an intent and retrieve a result from the IntentResolution\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  if (result && result.broadcast) { //detect whether the result is Context or a Channel\n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result){\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`\n  }\n}\ncatch (error: ResultError) {\n  console.error(`${resolution.source} returned a result error: ${error}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// raise an intent for resolution by the desktop agent\n// a resolver UI may be displayed, or another method of resolving the intent to a\n// target applied, if more than one application can resolve the intent\nawait _desktopAgent.RaiseIntent(\"StartChat\", context);\n\n// or find apps to resolve an intent to start a chat with a given contact\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", context);\n\n// use the metadata of an app or app instance to describe the target app for the intent\nawait _desktopAgent.RaiseIntent(\"StartChat\", context, appIntent.Apps.First());\n\n//Raise an intent without a context by using the null context type\nawait _desktopAgent.RaiseIntent(\"StartChat\", ContextType.Nothing);\n\n//Raise an intent and retrieve a result from the IntentResolution\nIIntentResolution resolution = await _desktopAgent.RaiseIntent(\"intentName\", context);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResult`](Types#intentresult)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n- [`ResultError`](Errors#resulterror)\n\n### `raiseIntentForContext`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IIntentResolution> RaiseIntentForContext(IContext context, IAppIdentifier? app = null);\n```\n\n</TabItem>\n</Tabs>\n\nFinds and raises an intent against apps registered with the desktop agent based purely on the type of the context data.\n\nThe desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context.\nAlternatively, the specific app or app instance to target can also be provided, in which case any method of resolution SHOULD only consider intents supported by the specified application.\n\nUsing `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app.\n\nReturns an `IntentResolution` object, see [`raiseIntent()`](#raiseintent) for details.\n\nIf a target intent and app cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, the promise MUST be rejected with an `Error` object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration. If a specific target `app` parameter was set, but either the app or app instance is not available, the promise MUST be rejected with an `Error` object with either the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` string as its `message`. If an invalid context object is passed as an argument the promise MUST be rejected with an `Error` object with the [`ResolveError.MalformedContext`](Errors#resolveerror) string as its `message`.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```js\n// Display a resolver UI for the user to select an intent and application to resolve it\nconst intentResolution = await fdc3.raiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait fdc3.raiseIntentForContext(context, targetAppIdentifier);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Display a resolver UI for the user to select an intent and application to resolve it\nvar intentResolution = await _desktopAgent.RaiseIntentForContext(context);\n\n// Resolve against all intents registered by a specific target app for the specified context\nawait _desktopAgent.RaiseIntentForContext(context, targetAppIdentifier);\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Raising Intents](../spec#raising-intents)\n- [`raiseIntent()`](#raiseintent)\n- [`Context`](Types#context)\n- [`AppIdentifier`](Types#appidentifier)\n- [`IntentResolution`](Metadata#intentresolution)\n- [`ResolveError`](Errors#resolveerror)\n\n## Deprecated Functions\n\n### `addContextListener` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddContextListener(handler: ContextHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAdds a listener for incoming context broadcasts from the Desktop Agent. Provided for backwards compatibility with versions FDC3 standard &lt;2.0.\n\n**See also:**\n\n- [`addContextListener`](#addcontextlistener)\n\n### `getSystemChannels` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ngetSystemChannels() : Promise<Array<Channel>>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAlias to the [`getUserChannels`](#getuserchannels) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n**See also:**\n\n- [`getUserChannels`](#getuserchannels)\n\n### `joinChannel` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\njoinChannel(channelId: string) : Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nAlias to the [`joinUserChannel`](#joinuserchannel) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard.\n\n**See also:**\n\n- [`joinUserChannel`](#joinuserchannel)\n\n### `open` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nopen(name: string, context?: Context): Promise<AppIdentifier>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `open` that launches an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`open`](#open)\n\n### `raiseIntent` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntent(intent: string, context: Context, name: string): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `raiseIntent` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntent`](#raiseintent)\n\n### `raiseIntentForContext` (deprecated)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nraiseIntentForContext(context: Context, name: string): Promise<IntentResolution>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n</Tabs>\n\nVersion of `raiseIntentForContext` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard &lt;2.0.\n\n**See also:**\n\n- [`raiseIntentForContext`](#raiseintentforcontext)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/Errors.md",
    "content": "---\ntitle: Errors\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations may sometimes result in an error that is returned to the caller. Errors MUST be returned by rejecting the promise returned by the API with a JavaScript `Error` object (or equivalent for the language of the implementation). The `Error` Object's message should be chosen from the appropriate Error enumeration below.\n\n## `AgentError`\n\nContains constants representing the errors that can be encountered when calling the [`getAgent`](GetAgent) function to establish connectivity to a Desktop Agent. Primarily used with web applications, but may also be used in other language implementations.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum AgentError { \n    /** Returned if no Desktop Agent was found by any means available or \n     * if the Agent previously connected to is not contactable on a  \n     * subsequent connection attempt.*/\n    AgentNotFound = \"AgentNotFound\",\n\n    /** Returned if validation of the app identity by the Desktop Agent \n     * failed or the app is not being allowed to connect to the Desktop Agent \n     * for another reason. */ \n    AccessDenied = \"AccessDenied\",\n\n    /** Returned if an error or exception occurs while trying to set  \n     * up communication with a Desktop Agent. */ \n    ErrorOnConnect = \"ErrorOnConnect\",\n\n    /** Returned if the failover function is not a function, or it did not\n     * resolve to one of the allowed types.*/ \n    InvalidFailover = \"InvalidFailover\",\n\n    /** Returned if an API call rejects after a timeout. Used where an API call\n     * is not aligned to another error enumeration.\n     */\n    ApiTimeout = 'ApiTimeout'\n} \n```\n\n</TabItem>\n</Tabs>\n\n## `ChannelError`\n\nContains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum ChannelError {\n  /** Returned if the specified channel is not found when attempting to join a\n   *  channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).\n   */\n  NoChannelFound = \"NoChannelFound\",\n\n  /** SHOULD be returned when a request to join a user channel or to a retrieve\n   *  a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods\n   *  of the DesktopAgent (`fdc3`) object is denied. \n   */\n  AccessDenied = \"AccessDenied\",\n  \n  /** SHOULD be returned when a channel cannot be created or retrieved via the\n   *  `getOrCreateChannel` method of the DesktopAgent (`fdc3`).\n   */\n  CreationFailed = \"CreationFailed\",\n\n  /** Returned if a call to the `broadcast` functions is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** Returned if a timeout occurs before any Channel related API call is resolved.\n   */\n  ApiTimeout = 'ApiTimeout'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ChannelError\n{\n    /// <summary>\n    /// Returned if the specified channel is not found when attempting to join a\n    /// channel via the `JoinUserChannel` function of the DesktopAgent.\n    /// </summary>\n    public static readonly string NoChannelFound = nameof(NoChannelFound);\n\n    /// <summary>\n    /// SHOULD be returned when a request to join a user channel or to a retrieve\n    /// a Channel object via the `JoinUserChannel` or `GetOrCreateChannel` methods\n    /// of the DesktopAgent is denied.\n    /// </summary>\n    public static readonly string AccessDenied = nameof(AccessDenied);\n\n    /// <summary>\n    /// SHOULD be returned when a channel cannot be created or retrieved via the\n    /// `GetOrCreateChannel` method of the DesktopAgent.\n    /// </summary>\n    public static readonly string CreationFailed = nameof(CreationFailed);\n\n    /// <summary>\n    /// Returned if a call to the `Broadcast` functions is made with an invalid\n    /// context argument.Contexts should be Objects with at least a `Type` field\n    /// that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)\n- [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n\n## `OpenError`\n\nContains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum OpenError {\n  /** Returned if the specified application is not found.*/\n  AppNotFound = \"AppNotFound\",\n\n  /** Returned if the specified application fails to launch correctly.*/\n  ErrorOnLaunch = \"ErrorOnLaunch\",\n\n  /** Returned if the specified application launches but fails to add a context\n   *  listener in order to receive the context passed to the `fdc3.open` call.\n   */\n  AppTimeout = \"AppTimeout\",\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = \"ResolverUnavailable\",\n\n  /** Returned if a call to the `open` function is made with an invalid\n   *  context argument. Contexts should be Objects with at least a `type` field\n   *  that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a connected \n   *  Desktop Agent Bridge. \n   * */\n  DesktopAgentNotFound = \"DesktopAgentNotFound\",\n\n  /** Returned if a timeout occurs before a call to open is resolved for any\n   *  reason other than the not adding its context listener in time.  \n   */\n  ApiTimeout = 'ApiTimeout'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class OpenError\n{\n    /// <summary>\n    /// Returned if the specified application is not found.\n    /// </summary>\n    public static readonly string AppNotFound = nameof(AppNotFound);\n\n    /// <summary>\n    /// Returned if the specified application fails to launch correctly.\n    /// </summary>\n    public static readonly string ErrorOnLaunch = nameof(ErrorOnLaunch);\n\n    /// <summary>\n    /// Returned if the specified application launches but fails to add a context\n    /// listener in order to receive the context passed to the `Open` call.\n    /// </summary>\n    public static readonly string AppTimeout = nameof(AppTimeout);\n\n    /// <summary>\n    /// Returned if the FDC3 desktop agent implementation is not currently able\n    /// to handle the request.\n    /// </summary>\n    public static readonly string ResolverUnavailable = nameof(ResolverUnavailable);\n\n    /// <summary>\n    /// Returned if a call to the `Open` function is made with an invalid\n    /// context argument.Contexts should be Objects with at least a `Type` field\n    /// that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.open`](DesktopAgent#open)\n\n## `ResolveError`\n\nContains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent), [`findIntentsByContext`](DesktopAgent#findintentsbycontext), [`raiseIntent`](DesktopAgent#raiseintent) or [`raiseIntentForContext`](DesktopAgent#raiseintentforcontext) methods on the [DesktopAgent](DesktopAgent).\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nexport enum ResolveError {\n  /** SHOULD be returned if no apps are available that can resolve the intent\n   *  and context combination.\n   */\n  NoAppsFound = \"NoAppsFound\",\n\n  /** Returned if the FDC3 desktop agent implementation is not currently able\n   *  to handle the request.\n   */\n  ResolverUnavailable = \"ResolverUnavailable\",\n\n  /** Returned if the user cancelled the resolution request, for example by\n   *  closing or cancelling a resolver UI.\n   */\n  UserCancelled = \"UserCancelledResolution\",\n\n  /** SHOULD be returned if a timeout cancels an intent resolution that\n   *  required user interaction. Please use `ResolverUnavailable` instead for\n   *  situations where a resolver UI or similar fails.\n   */\n  ResolverTimeout = \"ResolverTimeout\",\n\n  /** Returned if a specified target application is not available or a new\n   *  instance of it cannot be opened. \n   */\n  TargetAppUnavailable = \"TargetAppUnavailable\",\n\n  /** Returned if a specified target application instance is not available,\n   *  for example because it has been closed. \n   */\n  TargetInstanceUnavailable = \"TargetInstanceUnavailable\",\n\n  /** Returned if the intent and context could not be delivered to the selected\n   *  application or instance, for example because it has not added an intent\n   *  handler within a timeout.\n   */\n  IntentDeliveryFailed = \"IntentDeliveryFailed\",\n\n  /** Returned if a call to one of the `raiseIntent` functions is made with an \n   *  invalid context argument. Contexts should be Objects with at least a `type`\n   *  field that has a `string` value.\n   */\n  MalformedContext = \"MalformedContext\",\n\n  /** @experimental Returned if the specified Desktop Agent is not found, via a\n   *  connected Desktop Agent Bridge.\n   */\n  DesktopAgentNotFound = \"DesktopAgentNotFound\",\n\n  /** Returned if a timeout occurs before the API call is resolved for any reason other \n   *  than the resolver timing out (use ResolverTimeout) or an app launched by a \n   *  raiseIntent function doesn't add its intent listener in time (use \n   *  IntentDeliveryFailed).\n   */\n  ApiTimeout = 'ApiTimeout'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ResolveError\n{\n    /// <summary>\n    /// SHOULD be returned if no apps are available that can resolve the intent\n    /// and context combination.\n    /// </summary>\n    public static readonly string NoAppsFound = nameof(NoAppsFound);\n\n    /// <summary>\n    /// Returned if the FDC3 desktop agent implementation is not currently able\n    /// to handle the request.\n    /// </summary>\n    public static readonly string ResolverUnavailable = nameof(ResolverUnavailable);\n\n    /// <summary>\n    /// SHOULD be returned if a timeout cancels an intent resolution that\n    /// required user interaction. Please use `ResolverUnavailable` instead for\n    /// situations where a resolver UI or similar fails.\n    /// </summary>\n    public static readonly string ResolverTimeout = nameof(ResolverTimeout);\n\n    /// <summary>\n    /// Returned if the user cancelled the resolution request, for example by\n    /// closing or cancelling a resolver UI.\n    /// </summary>\n    public static readonly string UserCancelledResolution = nameof(UserCancelledResolution);\n\n    /// <summary>\n    /// Returned if a specified target application is not available or a new\n    /// instance of it cannot be opened.\n    /// </summary>\n    public static readonly string TargetAppUnavailable = nameof(TargetAppUnavailable);\n\n    /// <summary>\n    /// Returned if a specified target application instance is not available,\n    /// for example because it has been closed.\n    /// </summary>\n    public static readonly string TargetInstanceUnavailable = nameof(TargetInstanceUnavailable);\n\n    /// <summary>\n    /// Returned if the intent and context could not be delivered to the selected\n    /// application or instance, for example because it has not added an intent\n    /// handler within a timeout.\n    /// </summary>\n    public static readonly string IntentDeliveryFailed = nameof(IntentDeliveryFailed);\n    \n    /// <summary>\n    /// Returned if a call to one of the `RaiseIntent` functions is made with an \n    /// invalid context argument. Contexts should be Objects with at least a `Type`\n    /// field that has a `String` value.\n    /// </summary>\n    public static readonly string MalformedContext = nameof(MalformedContext);\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n\n## `ResultError`\n\nContains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum ResultError {\n  /** Returned if the intent handler exited without returning a valid result \n   * (a promise resolving to a Context, Channel object or void).\n   */\n  NoResultReturned = \"NoResultReturned\",\n\n  /** Returned if the `IntentHandler` function processing the raised intent\n   *  throws an error or rejects the Promise it returned. \n   */\n  IntentHandlerRejected = \"IntentHandlerRejected\",\n\n  /** Returned if a timeout occurs before the getResult() API call is resolved.\n   */\n  ApiTimeout = 'ApiTimeout'\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class ResultError\n{\n    /// <summary>\n    /// Returned if the intent handler exited without returning a valid result \n    /// (a Task resolving to a Context, Channel object or void).\n    /// </summary>\n    public static readonly string NoResultReturned = nameof(NoResultReturned);\n\n    /// <summary>\n    /// Returned if the `IntentHandler` function processing the raised intent\n    /// throws an error.\n    /// </summary>\n    public static readonly string IntentHandlerRejected = nameof(IntentHandlerRejected);\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `BridgingError`\n\n[`@experimental`](../../fdc3-compliance#experimental-features)\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nenum BridgingError {\n  /** @experimental Returned if a Desktop Agent did not return a response, via \n   *  Desktop Agent Bridging, within the allotted timeout. */\n  ResponseTimedOut = \"ResponseToBridgeTimedOut\",\n\n  /** @experimental Returned if a Desktop Agent that has been targeted by a \n   *  particular request has been disconnected from the Bridge before a \n   *  response has been received from it. */\n  AgentDisconnected = \"AgentDisconnected\",\n\n  /** @experimental Returned for FDC3 API calls that are specified with\n   *  arguments indicating that a remote Desktop agent should be targeted\n   *  (e.g. raiseIntent with an app on a remote DesktopAgent targeted), \n   *  when the local Desktop Agent is not connected to a bridge. */\n  NotConnectedToBridge = \"NotConnectedToBridge\",\n\n  /** @experimental Returned if a message to a Bridge deviates from the schema\n   *  for that message sufficiently that it could not be processed.\n   */\n  MalformedMessage = \"MalformedMessage\",\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nNot implemented\n```\n\n</TabItem>\n\n</Tabs>\n\nContains constants representing the errors that can be encountered when queries are forwarded to a Desktop Agent Bridge, but one or more remote Desktop Agents connected to it disconnects, times-out or a malformed message is encountered while a particular request is in flight. These errors may be returned via the FDC3 API when a Desktop Agent is (or was) connected to a Desktop Agent Bridge.\n\n**See also:**\n\n- [Agent Bridging - Workflows broken by disconnects](../../agent-bridging/spec#workflows-broken-by-disconnects)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/Events.md",
    "content": "---\ntitle: Events\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nIn addition to intent and context events, the FDC3 API and PrivateChannel API may be used to listen for other types of events via their `addEventListener()` functions.\n\n## `ApiEvent`\n\nType defining a basic event object that may be emitted by an FDC3 API interface such as DesktopAgent or PrivateChannel. There are more specific event types defined for each interface.\n\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ApiEvent {\n  readonly type: string;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented, as ApiEvent and Fdc3Event definitions are the same, given .NET can not restrict on a string enum. Use IFdc3Event instead\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`FDC3Event`](#fdc3event)\n- [`PrivateChannelEvent`](#privatechannelevent)\n\n## `EventHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype EventHandler = (event: ApiEvent) => void;\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic delegate void Fdc3EventHandler(IFdc3Event fdc3Event);\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles non-context and non-intent events. Provides the details of the event.\n\nUsed when attaching listeners to events.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n- [`ApiEvent`](#apievent)\n\n## `FDC3EventTypes`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype FDC3EventTypes = \"userChannelChanged\";\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class Fdc3EventType\n{\n    public const string UserChannelChanged = \"userChannelChanged\";\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining valid type strings for DesktopAgent interface events.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n\n## `FDC3Event`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface FDC3Event extends ApiEvent{\n  readonly type: FDC3EventTypes;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3Event\n{\n    public string Type { get; }\n    public object? Details { get; }\n}\n\npublic class Fdc3Event : IFdc3Event\n{\n    public string Type { get; }\n    public object? Details { get; }\n\n    public Fdc3Event(string type, object? details = null)\n    {\n        this.Type = type ?? throw new ArgumentNullException(nameof(type));\n        this.Details = details;\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\nType representing the format of event objects that may be received via the FDC3 API's `addEventListener` function.\n\nEvents will always include both `type` and `details` properties, which describe the type of the event and any additional details respectively.\n\n**See also:**\n\n- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener)\n- [`FDC3EventTypes`](#fdc3eventtypes)\n\n### `FDC3ChannelChangedEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface FDC3ChannelChangedEvent extends FDC3Event {\n  readonly type: \"userChannelChanged\";\n  readonly details: {\n    currentChannelId: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3ChannelChangedEventDetails\n{\n    string? CurrentChannelId { get; }\n}\npublic class Fdc3ChannelChangedEventDetails : IFdc3ChannelChangedEventDetails\n{\n    public string? CurrentChannelId { get; }\n\n    public Fdc3ChannelChangedEventDetails(string? channelId)\n    {\n        this.CurrentChannelId = channelId;\n    }\n}\n\npublic class Fdc3ChannelChangedEvent : Fdc3Event\n{\n    public Fdc3ChannelChangedEvent(string? channelId)\n        : base(Fdc3EventType.UserChannelChanged, new Fdc3ChannelChangedEventDetails(channelId))\n    {\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\n\nType representing the format of `userChannelChanged`  events.\n\nThe identity of the channel joined is provided as `details.currentChannelId`, which will be `null` if the app is no longer joined to any channel.\n\n## `PrivateChannelEventTypes`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype PrivateChannelEventTypes = \"addContextListener\" | \"unsubscribe\" | \"disconnect\";\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic static class Fdc3PrivateChannelEventType\n{\n    public const string AddContextListener = \"addContextListener\";\n    public const string Unsubscribe = \"unsubscribe\";\n    public const string Disconnect = \"disconnect\";\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining valid type strings for Private Channel events.\n\n**See also:**\n\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n\n## `PrivateChannelEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelEvent extends ApiEvent {\n  readonly type: PrivateChannelEventTypes;\n  readonly details: any;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic interface IFdc3PrivateChannelEventDetails\n{\n    string? ContextType { get; }\n}\npublic class Fdc3PrivateChannelEventDetails : IFdc3PrivateChannelEventDetails\n{\n    public string? ContextType { get; }\n\n    public Fdc3PrivateChannelEventDetails(string? contextType)\n    {\n        this.ContextType = contextType;\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\n\nType defining the format of event objects that may be received via a PrivateChannel's `addEventListener` function.\n\n**See also:**\n\n- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener)\n- [`PrivateChannelEventTypes`](#privatechanneleventtypes)\n\n### `PrivateChannelAddContextListenerEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelAddContextListenerEvent extends PrivateChannelEvent {\n  readonly type: \"addContextListener\";\n  readonly details: {\n    contextType: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChannelAddContextListenerEvent : Fdc3Event\n{\n    public Fdc3PrivateChannelAddContextListenerEvent(string? contextType)\n        : base(Fdc3PrivateChannelEventType.AddContextListener, new Fdc3PrivateChannelEventDetails(contextType))\n  {\n  }\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a context listener being added to the channel (`addContextListener`). Desktop Agents MUST fire this event for each invocation of `addContextListener` on the channel, including those that occurred before this handler was registered (to prevent race conditions).\n\nThe context type of the listener added is provided as `details.contextType`, which will be `null` if all event types are being listened to.\n\n### `PrivateChannelUnsubscribeEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface PrivateChannelUnsubscribeEvent extends PrivateChannelEvent {\n  readonly type: \"unsubscribe\";\n  readonly details: {\n    contextType: string | null\n  };\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChannelUnsubscribeListenerEvent : Fdc3Event\n{\n    public Fdc3PrivateChannelUnsubscribeListenerEvent(string? contextType)\n            : base(Fdc3PrivateChannelEventType.Unsubscribe, new Fdc3PrivateChannelEventDetails(contextType))\n    {\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a context listener removed from the channel (`Listener.unsubscribe()`). Desktop Agents MUST call this when `disconnect()` is called by the other party, for each listener that they had added.\n\nThe context type of the  listener removed is provided as `details.contextType`, which will be `null` if all event types were being listened to.\n\n### `PrivateChannelDisconnectEvent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nexport interface PrivateChannelDisconnectEvent extends PrivateChannelEvent {\n  readonly type: \"disconnect\";\n  readonly details: null | undefined;\n}\n```\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\npublic class Fdc3PrivateChanneDisconnectEvent : Fdc3Event\n{\n    public Fdc3PrivateChanneDisconnectEvent()\n        : base(Fdc3PrivateChannelEventType.Disconnect)\n    {\n    }\n}\n```\n\n</TabItem>\n</Tabs>\n\nType defining the format of events representing a remote app being terminated or is otherwise disconnecting from the PrivateChannel. This event is fired in addition to unsubscribe events that will also be fired for any context listeners the disconnecting app had added.\n\nNo details are provided.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/GetAgent.md",
    "content": "---\nid: GetAgent\nsidebar_label: GetAgent\ntitle: GetAgent\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nThe `getAgent()` function is the recommended way for **web applications** to connect to an FDC3 Desktop Agent. The function is exported by the [`@finos/fdc3`](https://www.npmjs.com/package/@finos/fdc3) NPM module and returns a [Desktop Agent](./DesktopAgent) implementation:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript\">\n\n```ts\nimport { getAgent, DesktopAgent, AgentError } from \"@finos/fdc3\";\n\ntry {\n    const desktopAgent: DesktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e: AgentError) {\n    // Failed to connect\n}\n```\n\n</TabItem>\n<TabItem value=\"js\" label=\"JavaScript\">\n\n```js\nimport { getAgent } from \"@finos/fdc3\";\n\ntry {\n    const desktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e) {\n    // Failed to connect\n}\n```\n\n</TabItem>\n</Tabs>\n\nThe  `getAgent()` function allows web applications to retrieve an FDC3 Desktop Agent API interface to work with, whether they are running in an environment that supports a Desktop Agent Preload (a container-injected API implementation) or a Desktop Agent Proxy (a Browser-based Desktop Agent running in another window or frame). The behavior of `getAgent()` is defined by the [FDC3 Web Connection Protocol (WCP)](../specs/webConnectionProtocol) and communication with a Desktop Agent Proxy in a web-browser is defined by the [Desktop Agent Communication Protocol (DACP)](../specs/desktopAgentCommunicationProtocol). Hence, it allows applications to be written that will work in either scenario without modification or the inclusion of vendor-specific libraries.\n\nTo handle situations where no Desktop Agent is found, a failover function may be supplied by an app allowing it to start or otherwise connect to a Desktop Agent (e.g. by loading a proprietary adaptor that returns a `DesktopAgent` implementation or by creating a window or iframe of its own that will provide a Desktop Agent Proxy).\n\nThe definition of the `getAgent()` function is as follows:\n\n```ts\ntype GetAgentType = ( \n  params?: GetAgentParams,  \n) => Promise<DesktopAgent>; \n```\n\nA small number of arguments are accepted that can affect the behavior of `getAgent` and to provide a fallback in case a Desktop Agent is not found, allowing the application to start its own agent or use another mechanism (such as a proprietary adaptor) to connect to one.\n\n```ts\n/** \n * @typedef {Object} GetAgentParams Type representing parameters passed to the \n * getAgent function. \n * \n * @property {number} timeoutMs Number of milliseconds to allow for an FDC3\n * implementation to be found before calling the failover function or\n * rejecting (default 1000). Note that the timeout is cancelled as soon as a\n * Desktop Agent is detected. There may be additional set-up steps to perform\n * which will happen outside the timeout.\n * \n * @property {string} identityUrl The app's current URL is normally sent to\n * a web-based desktop agent to help establish its identity. This property\n * may be used to override the URL sent (to handle situations where an app's\n * URL is not sufficiently stable to use for identity purposes,  e.g. due to\n * client-side route changes when navigating within the app). The URL set MUST\n * match the origin of the application (scheme, hostname, and port) or it will\n * be ignored. If not specified, the app's current URL will be used.\n * \n * @property {boolean} channelSelector Flag indicating that the application\n * needs access to a channel selector UI (i.e. because it supports User Channels\n * and does not implement its own UI for selecting channels). Defaults to \n * `true`. MAY be ignored by Desktop Agent Preload (container) implementations.\n * \n * @property {boolean} intentResolver Flag indicating that the application\n * needs access to an intent resolver UI (i.e. because it supports raising one\n * or more intents and and does not implement its own UI for selecting target\n * apps). Defaults to `true`. MAY be ignored by Desktop Agent Preload (container)\n * implementations. \n * \n * @property {boolean} dontSetWindowFdc3 For backwards compatibility, `getAgent`\n * will set a reference to the Desktop Agent implementation at `window.fdc3`\n * if one does not already exist, and will fire the fdc3Ready event. Defaults to\n * `false`. Setting this flag to `true` will inhibit that behavior, leaving \n * `window.fdc3` unset.\n * \n * @property {function} failover An optional function that provides a\n * means of connecting to or starting a Desktop Agent, which will be called\n * if no Desktop Agent is detected. Must return either a Desktop Agent\n * implementation directly (e.g. by using a proprietary adaptor) or a\n * WindowProxy (e.g a reference to another window returned by `window.open`\n * or an iframe's `contentWindow`) for a window or frame in which it has loaded\n * a Desktop Agent or suitable proxy to one that works with FDC3 Web Connection\n * and Desktop Agent Communication Protocols.\n * \n * @property {GetAgentLogLevels} logLevels Settings that determine what should\n * will logged by the getAgent() implementation and DesktopAgentProxy to the \n * JavaScript console.\n */\ntype GetAgentParams = { \n    timeoutMs?: number, \n    identityUrl?: string, \n    channelSelector?: boolean, \n    intentResolver?: boolean,\n    dontSetWindowFdc3?: boolean,\n    failover?: (args: GetAgentParams) => Promise<WindowProxy | DesktopAgent>,\n    logLevels?: GetAgentLogLevels;\n};\n\n/** \n * The default timeout used by getAgent when discovering Desktop Agents.\n */\nconst DEFAULT_GETAGENT_TIMEOUT_MS = 1000;\n\n/**\n * @typedef {Object} GetAgentLogLevels Type representing log-level parameters \\\n * passed to the getAgent function that control what is logged to the JavaScript\n * console by the getAgent() implementation and any DesktopAgentProxy it creates.\n *\n * @property {boolean} connection Log-level for messages relating to establishing\n * a connection to the Desktop Agent (default INFO).\n * \n * @property {boolean} proxy Log-level for messages from a DesktopAgentProxy\n * created by getAgent. These include log of messages sent or received from the \n * DesktopAgent at the INFO level and heartbeat messages at the DEBUG level \n * (default WARN).\n * \n */\ntype GetAgentLogLevels = {\n  connection: LogLevel,\n  proxy: LogLevel\n};\n\n/**\n * Type representing the different log-levels that can be set.\n */\nenum LogLevel {\n  NONE = 0,\n  ERROR = 1,\n  WARN = 2,\n  INFO = 3,\n  DEBUG = 4,\n}\n```\n\n:::note\n\nAs web applications can navigate to or be navigated by users to different URLs and become different applications, validation of an app's identity is necessary. The web application's current URL is passed to web browser-based Desktop Agents to allow them to establish the app's identity - usually connecting it with an App Directory record already known to the Desktop Agent. For more details on identity validation see the identity validation section of the  [Web Connection Protocol (WCP)](../specs/webConnectionProtocol).\n\n:::\n\nFinally, if there is still no Desktop Agent available, or an issue prevents connection to it, the `getAgent()` function will reject its promise with a message from the [`AgentError`](./Errors#agenterror) enumeration.\n\n## Injected iframes for adaptors and user interfaces\n\nThe `getAgent()` function may try to create hidden iframes within an application window in order to load either an adaptor to a Desktop Agent, or Intent Resolver and Channel Selector user interfaces when needed. The iframes are used in order to sandbox the relevant software, and are communicated with securely via the HTML Standard's Channel Messaging API ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API), [HTML Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html)).\n\n:::warning\n\nThe [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Where these are used, please ensure that they allow the loading of content from the domains of Desktop Agents and UI implementations that you wish to work with (including [fdc3.finos.org](https://fdc3.finos.org/) where the reference Intent Resolver and Channel Selector UIs may be loaded from).\n\n:::\n\n## Failover function\n\nDesktop Agent retrieval can time out, for instance if the DA doesn't exist or is unresponsive. The default timeout of 750 milliseconds can be overridden by setting the `timeoutMs` parameter. An application may also provide a failover function which will be called if an interface cannot be retrieved or times out.\n\nExample: Decreasing the timeout and providing a failover function\n\n```js\n    const desktopAgent = await getAgent({\n        timeoutMs: 250,\n        failover: async (params: GetAgentParams) => {\n            // return WindowProxy | DesktopAgent\n        }\n    }); \n```\n\nThe failover function allows an application to provide a backup mechanism for connecting to a DA. It is called only when establishment through normal procedures fails or times out.\n\n:::note\n\nIf you wish to _completely override FDC3's standard discovery mechanisms_, then do not use a failover function. Instead, simply skip the `getAgent()` call and provide your own DesktopAgent object.\n\n:::\n\nFailover functions MUST be asynchronous and MUST resolve to one of the following types:\n\n1. [`DesktopAgent`](./DesktopAgent)\n  The application may choose to directly import or load code that provides a `DesktopAgent` implementation. `getAgent()` will then resolve to the provided `DesktopAgent`.\n2. [`WindowProxy`](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object) ([MDN](https://developer.mozilla.org/en-US/docs/Glossary/WindowProxy))\n  The application may open a window or create a hidden iframe which may then provide access to a compliant browser-resident DA. Ensure that the iframe has loaded (listen for the `load` event) or for separate windows allow a suitable timeout for the window load, then resolve to the `WindowProxy` object for the window or iframe. The `getAgent()` call will then use the supplied `WindowProxy` to establish a connection.\n\n## Persisted Connection Data\n\nThe `getAgent()` function uses [`SessionStorage`](https://html.spec.whatwg.org/multipage/webstorage.html) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)) to persist information on an instance of an app and how it connected to a Desktop Agent in order to ensure a consistent connection type and `instanceId` when reconnecting after navigation or refresh events.\n\n:::warning\nApps do not need to and SHOULD NOT interact with data persisted in SessionStorage by `getAgent` directly, rather it is set and used by the `getAgent()` implementation.\n:::\n\nSessionStorage is used as for persistence as it is scoped to a single browser window and the current origin, ensuring apps in different windows or on different origins access different storage. However, as multiple iframes from the same-domain embedded within a window can share a SessionStorage instance, and multiple applications can be hosted on the same origin and be navigated to and from within a window, additional scoping is applied.\n\nTo differentiate storage for multiple iframes the name of the browsing context (`window.name`) is used to generate the key used in SessionStorage by concatenating the string `\"FDC3-Desktop-Agent-Details-\"` with `window.name`. The `window.name` remains stable during same-origin navigation and is persisted by the browser in its [session history](https://html.spec.whatwg.org/multipage/nav-history-apis.html#nav-traversal-apis) and is appropriate for scoping to a particular browsing context (window or iframe). Desktop Agents should assign a unique name to each window and iframe when they are created to facilitate such scoping. If no name is assigned, then the `getAgent` will assign a UUID as a unique name for that browsing context.\n\nThe data persisted is structured as an object conforming to the `SessionStorageFormat` type below, with the `identityUrl` of the app used as the key (if no `identityUrl` is provided the `actualUrl` is used instead), with the value conforming to the `DesktopAgentDetails` type. Hence, the data might be retrieved as follows:\n\n```ts\nconst sessionData: SessionStorageFormat = sessionStorage.get(\"FDC3-Desktop-Agent-Details-myWindowName\");\nconst agentDetails: DesktopAgentDetails = sessionData[\"myApIdentityUrl\"];\n```\n\n### Type Definitions\n\n```ts\n/** Type representing the format of data stored by `getAgent`\n *  in Session Storage. The `identityUrl` of each app is used\n *  as the key. */\ntype SessionStorageFormat = {\n    /** */\n    [key: string]: DesktopAgentDetails\n}\n\n/** Type representing data on the Desktop Agent that an app \n *  connected to that is persisted by the getAgent function \n *  to be used when re-connecting (after a navigation or  \n *  refresh event) and to ensure a consistent instanceId.  \n */ \ntype DesktopAgentDetails = { \n    /** The type of Desktop Agent connected to. Used to  \n     *  prevent an inadvertent switch to a different agent.*/ \n    agentType: WebDesktopAgentType,\n\n    /** The URL that was previously sent to the Desktop Agent \n     * to establish the app's identity.*/ \n    identityUrl?: string,\n\n    /** The current URL at the time of the last connection to \n     * a Desktop Agent.*/ \n    actualUrl?: string,\n\n    /** Optional URL field that should be used to store any \n     *  URL that was used to connect to a Desktop Agent. URLs \n     *  may have been provided by a parent window that has since \n     *  gone away and persisting may allow re-connection in such \n     *  cases. */ \n    agentUrl?: string,\n\n    /** The appId that was identified for the application by the \n     * Desktop Agent.*/ \n    appId: string,\n\n    /** The instanceId that was issued to the app by the Desktop  \n     * Agent. */ \n    instanceId: string,\n\n    /** The instanceUuid that was issued to the app. This should be \n     *  passed when connecting to the Desktop Agent to help  \n     *  identify that this app has connected before and which  \n     *  instance it is, enabling the Desktop Agent to reissue \n     *  the same instanceId. The instanceUuid should never be shared \n     *  with other applications and is not available through the \n     *  FDC3 API, allowing it to be used as a shared secret with \n     *  the Desktop Agent that issued the associated instanceId.*/ \n    instanceUuid: string \n} \n \n/** Enumeration of values used to describe types of web-based \n *  Desktop Agent. Each 'type' refers to the means by which \n *  a connection to the agent is made and/or an interface to it \n *  received. */ \nenum WebDesktopAgentType { \n    /** Denotes Desktop Agents that inject the FDC3 interface  \n     *  at `window.fdc3`. */ \n    Preload = \"PRELOAD\",\n\n    /** Denotes Desktop Agents that run (or provide an interface) \n     *  within a parent window or frame, a reference to which  \n     *  will be found at `window.opener`, `window.parent`, \n     * `window.parent.opener` etc. */ \n    ProxyParent = \"PROXY_PARENT\",\n\n    /** Denotes Desktop Agents that are connected to by loading a URL \n     *  into a hidden iframe whose URL was returned by a parent window\n     * or frame. */ \n    ProxyUrl = \"PROXY_URL\",\n\n    /** Denotes a Desktop Agent that was returned by a failover \n     * function that was passed by the application. */ \n    Failover = \"FAILOVER\" \n}\n\nconst DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX = 'fdc3-desktop-agent-details';\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/Metadata.md",
    "content": "---\ntitle: Metadata\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations return various types of metadata.\n\n## `AppIntent`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppIntent {\n  /** Details of the intent whose relationship to resolving applications is\n   *  being described.\n   */\n  readonly intent: IntentMetadata;\n\n  /** Details of applications that can resolve the intent. */\n  readonly apps: Array<AppMetadata>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppIntent\n{\n  /// <summary>\n  /// Details of the intent whose relationship to resolving application is\n  /// being described.\n  /// </summary>\n  IIntentMetadata Intent { get; }\n\n  /// <summary>\n  /// Details of applications that can resolve the intent.\n  /// </summary>\n  IEnumerable<IAppMetadata> Apps { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nAn interface that represents the binding of an intent to apps, returned as part of intent discovery.\nFor each intent, it reference the applications that support that intent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`IntentMetadata`](#intentmetadata)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n\n## `AppMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppMetadata extends AppIdentifier {\n  /**\n   *  The 'friendly' app name. This field was used with the `open` and\n   *  `raiseIntent` calls in FDC3 <2.0, which now require an `AppIdentifier`\n   *  with `appId` set. \n   * \n   *  Note that for display purposes the `title` field should be used, if set,\n   *  in preference to this field.\n   */\n  readonly name?: string;\n\n  /** The version of the application. */\n  readonly version?: string;\n\n  /** An optional set of, implementation specific, metadata fields that can be\n   *  used to disambiguate instances, such as a window title or screen position.\n   *  Must only be set if `instanceId` is set. \n   */\n  readonly instanceMetadata?: Record<string, any>;\n\n  /** A more user-friendly application title that can be used to render UI\n   *  elements.\n   */\n  readonly title?: string;\n\n  /** A tooltip for the application that can be used to render UI elements. */\n  readonly tooltip?: string;\n\n  /** A longer, multi-paragraph description for the application that could\n   *  include mark-up.\n   */\n  readonly description?: string;\n\n  /** A list of icon URLs for the application that can be used to render UI \n   *  elements.\n   */\n  readonly icons?: Array<Icon>;\n\n  /** Images representing the app in common usage scenarios that can be used to render UI elements */\n  readonly screenshots?: Array<Image>;\n  \n  /** The type of result returned for any intent specified during resolution. \n   *  May express a particular context type (e.g. \"fdc3.instrument\"), channel \n   *  (e.g. \"channel\") or a channel that will receive a specified type \n   *  (e.g. \"channel<fdc3.instrument>\").\n   */\n  readonly resultType?: string | null;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppMetadata : IAppIdentifier\n{\n    /// <summary>\n    /// The unique app name that can be used with the open and raiseIntent calls.\n    /// </summary>\n    string? Name { get; }\n\n    /// <summary>\n    /// The Version of the application.\n    /// </summary>\n    string? Version { get; }\n\n    /// <summary>\n    /// A more user-friendly application title that can be used to render UI elements.\n    /// </summary>\n    string? Title { get; }\n\n    /// <summary>\n    /// A tooltip for the application that can be used to render UI elements.\n    /// </summary>\n    string? Tooltip { get; }\n\n    /// <summary>\n    /// A longer, multi-paragraph description for the application that could include markup.\n    /// </summary>\n    string? Description { get; }\n\n    /// <summary>\n    /// A list of icon URLs for the application that can be used to render UI elements.\n    /// </summary>\n    IEnumerable<IIcon> Icons { get; }\n\n    /// <summary>\n    /// A list of image URLs for the application that can be used to render UI elements.\n    /// </summary>\n    IEnumerable<IImage> Screenshots { get; }\n\n    /// <summary>\n    /// The type of output returned for any intent specified during resolution. May express a particular context type,\n    /// channel, or channel with specified type\n    /// </summary>\n    string? ResultType { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nExtends an AppIdentifier, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.\n\nThe additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs.\n\nNote that as `AppMetadata` instances are also `AppIdentifiers` they may be passed to the `app` argument of `fdc3.open`, `fdc3.raiseIntent` etc..\n\n**See also:**\n\n- [`AppIdentifier`](Types#appidentifier)\n- [`AppIntent.apps`](#appintent)\n- [`Icon`](#icon)\n- [`Image`](#image)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## `ContextMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ContextMetadata {\n  /** Identifier for the app instance that sent the context and/or intent. \n   *  @experimental \n   */\n  readonly source: AppIdentifier;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IContextMetadata\n{\n    /// <summary>\n    /// Identifier for the app instance that sent the context and/or intent.\n    /// </summary>\n    IAppIdentifier? Source { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a context or intent & context received through the `addContextListener` and `addIntentListener` functions. Currently identifies the app that originated the context or intent message.\n\n[`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`ContextHandler`](Types#contexthandler)\n- [`IntentHandler`](Types#intenthandler)\n- [`addIntentListener`](DesktopAgent#addintentlistener)\n- [`addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DisplayMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface DisplayMetadata {\n  /**\n   *  A user-readable name for this channel, e.g: `\"Red\"`. */\n  readonly name?: string;\n\n  /**\n   *  The color that should be associated within this channel when displaying\n   *  this channel in a UI, e.g: `#FF0000`. May be any color value supported by\n   *  CSS, e.g. name, hex, rgba, etc.. */\n  readonly color?: string;\n\n  /**\n   *  A URL of an image that can be used to display this channel. */\n  readonly glyph?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IDisplayMetadata\n{\n    /// <summary>\n    /// A user-readable name for this channel, e.g: Red.\n    /// </summary>\n    string? Name { get; }\n\n    /// <summary>\n    /// The color that should be associated within this channel when displaying this\n    /// channein in a UI, e.g: '0xFF0000'.\n    /// </summary>\n    string? Color { get; }\n\n    /// <summary>\n    /// A URL of an image that can be used to display this channel.\n    /// </summary>\n    string? Glyph { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nA desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking.\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`DesktopAgent.getUserChannels`](DesktopAgent#getuserchannels)\n\n## `Icon`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Icon {\n  src: string;\n  size?: string;\n  type?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIcon\n{\n    /// <summary>\n    /// The icon url\n    /// </summary>\n    string Src { get; }\n    \n    /// <summary>\n    /// The icon dimensions, formatted as '{height}x{width}'\n    /// </summary>\n    string? Size { get; }\n    \n    /// <summary>\n    /// Icon media type. If not present, the Desktop Agent may use the src file extension.\n    /// </summary>\n    string? Type { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a single icon image at a remote URL, used to represent an application in a user interface.\n\nAppMetadata includes an icons property allowing multiple icon types to be specified. Various properties may be used by the Desktop Agent to decide which icon is the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n\"icons\": [\n  {\n    \"src\": \"https://app.foo.icon/app_icons/lowres.webp\",\n    \"size\": \"48x48\",\n    \"type\": \"image/webp\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_icons/hd_hi.svg\",\n    \"size\": \"72x72\",\n    \"type\": \"image/svg+xml\"\n  }\n]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIIcon? icon = appMetadata?.Icons.Where(icon => icon.Size == \"48x48\").First();\n```\n\n</TabItem>\n</Tabs>\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the icon.\n- **`size`:** The dimensions of the Icon formatted as `<height>x<width>`.\n- **`type`:** The media type of the icon. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `Image`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Image {\n  src: string;\n  size?: string;\n  type?: string;\n  label?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IImage\n{\n    /// <summary>\n    /// The icon url\n    /// </summary>\n    string Src { get; }\n    \n    /// <summary>\n    /// The icon dimensions, formatted as '{height}x{width}'\n    /// </summary>\n    string? Size { get; }\n    \n    /// <summary>\n    /// Icon media type.  If not present, the Desktop Agent may use the src file extension.\n    /// </summary>\n    string? Type { get; }\n\n\n    /// <summary>\n    /// Caption for the image\n    /// </summary>\n    string? Label { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to a single image at a remote URL, used to represent screenshot images.\n\nAppMetadata includes a screenshots property allowing multiple images to be specified. Various properties may be used by the Desktop Agent to decide which image(s) are the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system.\n\n**Example:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n\"screenshots\": [\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/dashboard.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Example app dashboard\"\n  },\n  {\n    \"src\": \"https://app.foo.icon/app_screenshots/notifications.png\",\n    \"size\": \"800x600\",\n    \"type\": \"image/png\",\n    \"label\": \"Order notifications view\"\n  }\n]\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nforeach (IImage image in appMetadata.Screenshots)\n{\n    System.Diagnostics.Debug.WriteLine(image.Src);\n}\n```\n\n</TabItem>\n</Tabs>\n\n**Properties:**\n\n- **`src`:** The fully qualified url to the image.\n- **`size`:** The dimensions of the image formatted as `<height>x<width>`.\n- **`type`:** The media type of the image. If not provided the Desktop Agent may refer to the src file extension.\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n\n## `ImplementationMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface ImplementationMetadata {\n  /** The version number of the FDC3 specification that the implementation\n   *  provides. The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n   */\n  readonly fdc3Version: string;\n\n  /** The name of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. io.Connect, OpenFin etc.).\n   */\n  readonly provider: string;\n\n  /** The version of the provider of the FDC3 Desktop Agent Implementation\n   *  (e.g. 5.3.0).\n   */\n  readonly providerVersion?: string;\n\n  /** Metadata indicating whether the Desktop Agent implements optional features of\n   *  the Desktop Agent API.\n   */\n  readonly optionalFeatures: {\n    /** Used to indicate whether the exposure of 'originating app metadata' for\n     *  context and intent messages is supported by the Desktop Agent.*/\n    readonly OriginatingAppMetadata: boolean;\n    /** Used to indicate whether the optional `fdc3.joinUserChannel`,\n     *  `fdc3.getCurrentChannel` and `fdc3.leaveCurrentChannel` are implemented by\n     *  the Desktop Agent.*/\n    readonly UserChannelMembershipAPIs: boolean;\n    /** Used to indicate whether the experimental Desktop Agent Bridging\n     *  feature is implemented by the Desktop Agent.*/\n    readonly DesktopAgentBridging: boolean;\n  };\n\n  /** The calling application instance's own metadata, according to the \n   *  Desktop Agent (MUST include at least the `appId` and `instanceId`).\n   */\n  readonly appMetadata: AppMetadata;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IImplementationMetadata\n{\n    /// <summary>\n    ///  The version number of the FDC3 specification that the implementation provides.\n    ///  The string must be a numeric semver version, e.g. 1.2 or 1.2.1.\n    /// </summary>\n    string Fdc3Version { get; }\n\n    /// <summary>\n    /// The name of the provider of the FDC3 Desktop Agent Implementation (e.g. Finsemble, Glue42, OpenFin etc.).\n    /// </summary>\n    string Provider { get; }\n\n    /// <summary>\n    /// The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0).\n    /// </summary>\n    string ProviderVersion { get; }\n\n    /// <summary>\n    /// Metadata indicating whether the Desktop Agent implements optional features of the Desktop Agent API.\n    /// </summary>\n    OptionalDesktopAgentFeatures OptionalFeatures { get; }\n\n    /// <summary>\n    /// The calling application instance's own metadata according to the Desktop Agent\n    /// </summary>\n    IAppMetadata AppMetadata { get; }\n}\n\nclass OptionalDesktopAgentFeatures\n{\n    /// <summary>\n    /// Used to indicate whether the exposure of 'originating app metadata' for context and intent\n    /// messages is supported by the Desktop Agent.\n    /// </summary>\n    public bool OriginatingAppMetadata { get; set; }\n    \n    /// <summary>\n    /// Used to indicate whether the optional 'JoinUserChannel', 'GetCurrentChannel', and 'LeaveCurrentChannel'\n    /// are implemented by the Desktop Agent.\n    /// </summary>\n    public bool UserChannelMembershipAPIs { get; set; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nMetadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number and the metadata of the calling application according to the desktop agent.\n\n**See also:**\n\n- [`AppMetadata`](#appmetadata)\n- [`DesktopAgent.getInfo`](DesktopAgent#getinfo)\n\n## `IntentMetadata`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface IntentMetadata {\n  /** The unique name of the intent that can be invoked by the raiseIntent call. */\n  readonly name: string;\n\n  /** Display name for the intent.\n   * @deprecated Use the intent name for display as display name may vary for\n   * each application as it is defined in the app's AppD record.\n   */\n  readonly displayName?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentMetadata\n{\n    /// <summary>\n    /// The unique name of the intent that can be invoked by the raiseIntent call.\n    /// </summary>\n    string Name { get; }\n\n    /// <summary>\n    /// A friendly display name for the intent that should be used to render UI elements.\n    /// </summary>\n    string DisplayName { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nThe interface used to describe an intent within the platform.\n\n**See also:**\n\n- [`AppIntent.intent`](#appintent)\n\n## `IntentResolution`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface IntentResolution {\n\n  /** Identifier for the app instance that was selected (or started) to resolve\n   *  the intent. `source.instanceId` MUST be set, indicating the specific app \n   *  instance that received the intent.\n   */\n  readonly source: AppIdentifier;\n\n  /** The intent that was raised. May be used to determine which intent the user\n   *  chose in response to `fdc3.raiseIntentForContext()`.\n   */\n  readonly intent: string;\n  \n  /** Retrieves a promise that will resolve to `Context` data returned \n   *  by the application that resolves the raised intent, a `Channel` \n   *  established and returned by the app resolving the intent or void. \n   * \n   *  A `Channel` returned MAY be of the `PrivateChannel` type. The \n   *  client can then `addContextListener()` on that channel to, for example, \n   *  receive a stream of data.\n   * \n   *  If an error occurs (i.e. an error is thrown by the handler function,\n   *  the promise it returns is rejected, or the promise resolved to an invalid \n   *  type) then the Desktop Agent MUST reject the promise returned by the \n   *  `getResult()` function of the `IntentResolution` with a string from\n   *  the `ResultError` enumeration.\n   */\n   getResult(): Promise<IntentResult>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentResolution\n{\n    /// <summary>\n    /// The application that resolved the intent.\n    /// </summary>\n    IAppIdentifier Source { get; }\n\n    /// <summary>\n    /// The intent that was raised.\n    /// </summary>\n    string Intent { get; }\n\n    /// <summary>\n    /// The version number of the Intents schema being used.\n    /// </summary>\n    string? Version { get; }\n\n    Task<IIntentResult> GetResult();\n}\n```\n\n</TabItem>\n</Tabs>\n\nIntentResolution provides a standard format for data returned upon resolving an intent.\n\n**Examples:**\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// Resolve a \"Chain\" type intent\nlet resolution = await agent.raiseIntent(\"intentName\", context);\n\n// Use metadata about the resolving app instance to target a further intent\ntry {\n  const resolution = await fdc3.raiseIntent('StageOrder', context);\n  ...\n\n  //Some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err: ResolveError) { ... }                                    \n                                               \n//Resolve a \"Client-Service\" type intent with a data or channel response\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n    const result = await resolution.getResult();\n    if (result && result.broadcast) { //detect whether the result is Context or a Channel\n        console.log(`${resolution.source} returned a channel with id ${result.id}`);\n    } else if (result){\n        console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n    } else {\n        console.error(`${resolution.source} didn't return anything`);\n    }\n} catch(error: ResultError) {\n    console.error(`${resolution.source} returned an error: ${error}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        var listener = await channel.AddContextListener<IContext>(\"price\", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote));\n\n        //if it's a PrivateChannel\n        if (channel is IPrivateChannel privateChannel)\n        {\n            privateChannel.OnDisconnect(() => {\n                System.Diagnostics.Debug.WriteLine(\"Quote feed went down\");\n            });\n\n            // Sometime later...\n            listener.Unsubscribe();\n        }\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\" {resolution.Source} did not return a channel\");\n    }\n}\ncatch (Exception ex)\n{\n    // Handle exception\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`IntentResult`](Types#intentresult)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`AppIdentifier`](Types#appidentifier)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/PrivateChannel.md",
    "content": "---\nid: PrivateChannel\nsidebar_label: PrivateChannel\ntitle: PrivateChannel\nhide_title: true\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# `PrivateChannel`\n\nObject representing a private context channel, which is intended to support secure communication between applications, and extends the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface  PrivateChannel extends Channel {\n  // functions\n  addEventListener(type: PrivateChannelEventTypes  | null, handler: EventHandler): Promise<Listener>;\n  disconnect(): Promise<void>;\n\n  //deprecated functions\n  onAddContextListener(handler: (contextType?: string) => void): Listener;\n  onUnsubscribe(handler: (contextType?: string) => void): Listener;\n  onDisconnect(handler: () => void): Listener;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IPrivateChannel : IChannel, IIntentResult\n{\n    //functions\n    Task<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n\n    //deprecated functions\n    IListener OnAddContextListener(Action<string?> handler);\n    IListener OnUnsubscribe(Action<string?> handler);\n    IListener OnDisconnect(Action handler);\n    void Disconnect();\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`Channel`](Channel)\n- [`Listener`](Types#listener)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n\n## Examples\n\n### 'Server-side' example\n\nThe intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextListener()` on that channel, the intent app receives notice via the handler added with `addEventListener()` and knows that the client is ready to start receiving quotes.\n\nThe Desktop Agent knows that a channel is being returned by inspecting the object returned from the handler (e.g. check constructor or look for private member).\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfdc3.addIntentListener(\"QuoteStream\", async (context) => {\n    const channel: PrivateChannel = await fdc3.createPrivateChannel();\n    const symbol = context.id.ticker;\n\n    // This gets called when the remote side adds a context listener\n    const addContextListener = channel.addEventListener(\"addContextListener\",\n        (event: PrivateChannelAddContextListenerEvent) => {\n            console.log(`remote side added a listener for ${event.contextType}`);\n            // broadcast price quotes as they come in from our quote feed\n            feed.onQuote(symbol, (price) => {\n                channel.broadcast({ type: \"price\", price});\n            });\n        }\n    );\n\n    // This gets called when the remote side calls Listener.unsubscribe()\n    const unsubscribeListener = channel.addEventListener(\"unsubscribe\",\n        (event: PrivateChannelUnsubscribeEvent) => {\n            console.log(`remote side unsubscribed a listener for ${event.contextType}`);\n            feed.stop(symbol);\n        }\n    );\n\n    // This gets called if the remote side closes\n    const disconnectListener = channel.addEventListener(\"disconnect\", \n        () => {\n            console.log(`remote side disconnected`);\n            feed.stop(symbol);\n        }\n    );\n\n    return channel;\n});\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n_desktopAgent.AddIntentListener<Instrument>(\"QuoteStream\", async (context, metadata) => {\n  var channel = await _desktopAgent.CreatePrivateChannel();\n  var symbol = context?.ID?.Ticker;\n\n  // This gets called when the remote side adds a context listener\n  var addContextListener = channel.OnAddContextListener((contextType) => {\n      // broadcast price quotes as they come in from our quote feed\n      _feed.OnQuote(symbol, (price) => {\n          channel.Broadcast(new Price(price));\n      });\n  });\n\n  // This gets called when the remote side calls Listener.unsubscribe()\n  var unsubscribeListener = channel.OnUnsubscribe((contextType) => {\n      _feed.Stop(symbol);\n  });\n\n  // This gets called if the remote side closes\n  var disconnectListener = channel.OnDisconnect(() => {\n      _feed.stop(symbol);\n  });\n  \n  return channel;\n});\n```\n\n</TabItem>\n</Tabs>\n\n### 'Client-side' example\n\nThe 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. The `onDisconnect()` listener may also be used to clean up when the 'server-side' disconnects the stream.\n\nAlthough this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n    const resolution3 = await fdc3.raiseIntent(\"QuoteStream\", { type: \"fdc3.instrument\", id : { ticker: \"AAPL\" } });\n    try {\n        const result = await resolution3.getResult();\n        //check that we got a result and that it's a channel\n        if (result && result.addContextListener) {\n            const listener = result.addContextListener(\"price\", (quote) => console.log(quote));\n                //if it's a PrivateChannel\n                if (result.type == \"private\") {\n                    result.addEventListener(\"disconnect\", () => {\n                        console.warn(\"Quote feed went down\");\n                    });\n\n                   // Sometime later...\n                   await listener.unsubscribe();\n                }\n        } else {\n            console.warn(`${resolution3.source} did not return a channel`);\n        }\n    } catch(channelError) {\n        console.log(`Error: ${resolution3.source} returned an error: ${channelError}`);\n    } catch(resultError: ResultError) {\n          console.log(`Error: ${resolution3.source} returned an error: ${resultError}`);\n    }\n} catch (resolverError: ResolveError) {\n    console.error(`Error: Intent was not resolved: ${resolverError}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        var listener = await channel.AddContextListener<IContext>(\"price\", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote));\n\n        //if it's a PrivateChannel\n        if (channel is IPrivateChannel privateChannel)\n        {\n            privateChannel.OnDisconnect(() => {\n                System.Diagnostics.Debug.WriteLine(\"Quote feed went down\");\n            });\n\n            // Sometime later...\n            listener.Unsubscribe();\n        }\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\" {resolution.Source} did not return a channel\");\n    }\n}\ncatch (Exception ex)\n{\n    // Handle exception\n}\n```\n\n</TabItem>\n</Tabs>\n\n## Functions\n\n### `addEventListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\naddEventListener(type: PrivateChannelEventTypes  | null, handler: EventHandler): Promise<Listener>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask<IListener> AddEventListener(string? eventType, Fdc3EventHandler handler);\n```\n\n</TabItem>\n</Tabs>\n\nRegister a handler for events from the PrivateChannel. Whenever the handler function is called it will be passed an event object with details related to the event.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// any event type\nconst listener: Listener = await myPrivateChannel.addEventListener(null, \n    (event: PrivateChannelEvent) => {\n        console.log(`Received event ${event.type}\\n\\tDetails: ${event.details}`);\n    }\n);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIChannel myPrivateChannel;\nvar listener = await myPrivateChannel.AddEventListener(null, (event) => {\n    System.Diagnostics.Debug.WriteLine($\"Received event ${event.Type}\\n\\tDetails: ${event.Details}\");\n});\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [Events](./Events)\n- [EventHandler](./Events#eventhandler)\n- [PrivateChannelEvent](./Events#privatechannelevent)\n- [PrivateChannelAddContextListenerEvent](./Events#privatechanneladdcontextlistenerevent)\n- [PrivateChannelUnsubscribeEvent](./Events#privatechannelunsubscribeevent)\n- [PrivateChannelDisconnectEvent](./Events#privatechanneldisconnectevent)\n  \n### `disconnect`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ndisconnect(): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvoid Disconnect();\n```\n\n</TabItem>\n</Tabs>\n  \nMay be called to indicate that a participant will no longer interact with this channel.\n\n## Deprecated Functions\n\n### `onAddContextListener`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonAddContextListener(handler: (contextType?: string) => void): Listener;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnAddContextListener(Action<string?> handler);\n```\n\n</TabItem>\n</Tabs>\n  \nDeprecated in favour of the async `addEventListener(\"addContextListener\", handler)` function.\n\nAdds a listener that will be called each time that the remote app invokes addContextListener on this channel.\n\n### `onUnsubscribe`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonUnsubscribe(handler: (contextType?: string) => void): Listener;\n```\n  \n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnUnsubscribe(Action<string?> handler);\n```\n\n</TabItem>\n</Tabs>\n\nDeprecated in favour of the async `addEventListener(\"unsubscribe\", handler)` function.\n\nAdds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added.\n\n### `onDisconnect`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nonDisconnect(handler: () => void): Listener;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nIListener OnDisconnect(Action handler);\n```\n\n</TabItem>\n</Tabs>\n\nDeprecated in favour of the async `addEventListener(\"disconnect\", handler)` function.\n\nAdds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/ref/Types.md",
    "content": "---\ntitle: Types\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nFDC3 API operations make use of several type declarations.\n\n## `AppIdentifier`\n\nIdentifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.\nWill always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc..\nIf the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface AppIdentifier {\n  /** The unique application identifier located within a specific application\n   *  directory instance. An example of an appId might be 'app@sub.root'.\n   */\n  readonly appId: string;\n  \n  /** An optional instance identifier, indicating that this object represents a\n   *  specific instance of the application described.\n   */\n  readonly instanceId?: string;\n\n  /** The Desktop Agent that the app is available on. Used in Desktop Agent \n   *  Bridging to identify the Desktop Agent to target.\n   *  @experimental\n   **/\n  readonly desktopAgent?: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IAppIdentifier\n{\n    /// <summary>\n    /// The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'.\n    /// </summary>\n    string AppId { get; }\n\n    /// <summary>\n    /// An optional instance identifier, indicating that this object represents a specific instance of the application described.\n    /// </summary>\n    string? InstanceId { get; }\n}\n```\n\n</TabItem>\n</Tabs>\n\n**See also:**\n\n- [`AppMetadata`](Metadata#appmetadata)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Context`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Context {\n  id?: { [key: string]: string };\n  name?: string;\n  type: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IContext<out T>: IIntentResult, IDynamicContext where T : class\n{\n    T? ID { get; }\n    string? Name { get; }\n    string Type { get; }\n}\n\ninterface IContext : IContext<object>\n{\n}\n\ninterface IDynamicContext\n{\n    /// <summary>\n    /// Underlying message as a dynamic type for accessing all properties without deserialization\n    /// </summary>\n    dynamic? Native { get; set; }\n}\n```\n\n</TabItem>\n</Tabs>\n\nThe base interface that all contexts should extend: a context data object adhering to the [FDC3 Context Data specification](../../context/spec).\n\nThis means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getcurrentcontext) and [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener), which allows you to filter contexts by their type.\n\n**See also:**\n\n- [`ContextHandler`](#contexthandler)\n- [`DesktopAgent.open`](DesktopAgent#open)\n- [`DesktopAgent.broadcast`](DesktopAgent#broadcast)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`DesktopAgent.findIntent`](DesktopAgent#findintent)\n- [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext)\n- [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)\n- [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext)\n- [`Channel.broadcast`](Channel#broadcast)\n- [`Channel.getCurrentContext`](Channel#getcurrentcontext)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `ContextHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype ContextHandler = (context: Context, metadata?: ContextMetadata) => void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ndelegate void ContextHandler<T>(T context, IContextMetadata? metadata = null) where T : IContext;\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles a context event. Optional metadata about the context message, including the app that originated the message, may be provided.\n\nUsed when attaching listeners for context broadcasts.\n\nOptional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `DesktopAgentIdentifier`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n/** @experimental */\ninterface DesktopAgentIdentifier {\n  /** Used in Desktop Agent Bridging to attribute or target a message to a \n   *  particular Desktop Agent.**/\n  readonly desktopAgent: string;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```\nNot implemented\n```\n\n</TabItem>\n\n</Tabs>\n\n(Experimental) Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no app details are available or are appropriate.\n\n**See also:**\n\n* [Agent Bridging - Identifying Desktop Agents Identity and Message Sources](../../agent-bridging/spec#identifying-desktop-agents-identity-and-message-sources)\n\n## `IntentHandler`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise<IntentResult> | void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ndelegate Task<IIntentResult> IntentHandler<T>(T context, IContextMetadata? metadata = null) where T : IContext;\n```\n\n</TabItem>\n</Tabs>\n\nDescribes a callback that handles a context event and may return a promise of a Context, Channel object or `void` to be returned to the application that raised the intent.\n\nUsed when attaching listeners for raised intents.\n\nOptional metadata about the intent & context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.\n\n**See also:**\n\n- [`Context`](#context)\n- [`ContextMetadata`](Metadata#contextmetadata)\n- [`PrivateChannel`](PrivateChannel)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n\n## `IntentResult`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntype IntentResult = Context | Channel | void;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IIntentResult { /* Marker interface implemented by IContext and Channel */ }\n```\n\n</TabItem>\n</Tabs>\n\nDescribes results that an Intent handler may return that should be communicated back to the app that raised the intent, via the [`IntentResolution`](Metadata#intentresolution).\n\nRepresented as a union type in TypeScript, however, this type may be rendered as an interface in other languages that both the `Context` and `Channel` types implement, allowing either to be returned by an `IntentHandler`.\n\n**See also:**\n\n- [`Context`](#context)\n- [`Channel`](Channel)\n- [`PrivateChannel`](PrivateChannel)\n- [`IntentHandler`](#intenthandler)\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`IntentResolution`](Metadata#intentresolution)\n\n## `Listener`\n\nA Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener), [`addContextListener`](DesktopAgent#addcontextlistener) or [`addEventListener`](DesktopAgent#addeventlistener) on the [DesktopAgent](DesktopAgent) object or (PrivateChannel#addeventlistener) on the [PrivateChannel](PrivateChannel) object.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ninterface Listener {\n  unsubscribe(): Promise<void>;\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ninterface IListener\n{\n    Task Unsubscribe();\n}\n```\n\n</TabItem>\n</Tabs>\n\n### `unsubscribe`\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nunsubscribe(): Promise<void>;\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nTask Unsubscribe();\n```\n\n</TabItem>\n</Tabs>\n\nAllows an application to unsubscribe from listening to intents or context broadcasts.\n\n**See also:**\n\n- [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)\n- [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener)\n- [`Channel.addContextListener`](Channel#addcontextlistener)\n- [`ContextHandler`](Types#contexthandler)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: API Overview (2.2)\n---\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\nThe role of FDC3 API is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications, standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance.\n\nThe following sections examine the API's use-cases and core concepts. The API is fully defined in both subsequent pages of this Part and a full set of TypeScript definitions in the [src](https://github.com/finos/FDC3/tree/main/src/api) directory of the [FDC3 GitHub repository](https://github.com/finos/FDC3/).\n\n## Components\n\n### Desktop Agent\n\nA Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.  A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary.\n\nExamples of Desktop Agents include:\n\n- Autobahn\n- io.Connect\n- OpenFin\n- Refinitiv Eikon\n\nAn FDC3-compliant Desktop Agent exposes an FDC3 Standard API to applications they have launched.  When an App is launched by a Desktop Agent and is given access to the Agent's API to interoperate, it is running in that Desktop Agent's *context*.\n\n### Application\n\nAn application is any endpoint on the desktop that is:\n\n- Registered with/known by a Desktop Agent\n- Launchable by a Desktop Agent\n- Addressable by a Desktop Agent\n\nExamples of endpoints include:\n\n- Native Applications\n- Web Applications\n- Headless “services” running on the desktop\n\n## Desktop Agent Implementation\n\nThe FDC3 API specification consists of interfaces.  It is expected that each Desktop Agent will implement these interfaces.  A Desktop Agent MUST provide implementations for the following interfaces:\n\n- [`DesktopAgent`](ref/DesktopAgent)\n- [`Channel`](ref/Channel)\n- [`PrivateChannel`](ref/PrivateChannel)\n- [`Listener`](ref/Types#listener)\n- [Utility types](ref/Types) and [Metadata Objects](ref/Metadata).\n\nThe means to access the main FDC3 API interface (a `DesktopAgent` implementation) is defined separately for each language in which FDC3 is implemented. These definitions are important as they affect whether applications can be written in a vendor agnostic format so that they run under any Standards-conformant implementation.\n\n### Implementation language\n\nFDC3 and the Desktop Agent API it defines are intended to be independent of particular programming languages and platforms and hence the original definitions, produced in TypeScript, may be translated into other languages. However, this also places limitations on the API definitions as they need to be widely implementable in other languages.\n\nSpecifically, the use of ['unions'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of primitive values in API type and metadata objects, or function parameters SHOULD be avoided as they often cannot be replicated in other languages. Unions of more complex types (such as specific [Context](../context/spec#the-context-interface) Types) may be used where a suitable interface is available or can be created to allow the required polymorphism in languages other than TypeScript.\n\nFor implementation details relating to particular languages, and how to access the API in those languages, please see [Supported Platforms](./supported-platforms).\n\n### Standards vs. Implementation\n\n![Desktop Agent - Standards Schematic](/assets/api-1.png)\n\nThe surface area of FDC3 standardization (shown in *white* above) itself is quite small in comparison to the extent of a typical desktop agent implementation (in *grey*).\n\nFor example:\n\n- Workspace management\n- User identity and SSO\n- Entitlements\n- UX of application resolution\n\nAre all areas of functionality that any feature-complete desktop agent would implement, but are not currently areas considered for standardization under FDC3.\n\n### Inter-Agent Communication\n\nA goal of the FDC3 Standard is that applications running in different Desktop Agent contexts on the same desktop, or operated by the same user, would be able to interoperate and that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context. As Desktop Agent interop is supported by common standards for APIs an app in one Desktop Agent context would not need to know a different syntax to launch or interact with an app in another Desktop Agent context.\n\nInter-agent communication at the API layer may be achieved via the [Desktop Agent Bridging Part of the FDC3 Standard](../agent-bridging/spec) ([@experimental](../fdc3-compliance#experimental-features)), which defines an independent service that Desktop Agents may connect to (via the Bridge Connection Protocol or BCP), and a protocol for the exchange of messages relating to FDC3 API calls (the Bridge Messaging Protocol or BMP). Hence, by implementing support for Desktop Agent Bridging, a platform may extend interop across applications running in multiple Desktop Agent contexts.\n\nDesktop Agent Bridging provides message exchanges and a workflow for performing intent resolution across multiple agents. Hence, app discovery is supported across the agents connected to the bridge for intent-based workflows. Further, as channels are also supported by bridging, context sharing also works across multiple agents.\n\nThere is currently no method of discovering all the apps supported by a Desktop Agent in the FDC3 API nor bridging. Hence, to support launching, via `fdc3.open` across the connected Desktop Agents, application details must be known in advance. This may be achieved by connecting Desktop Agents to the same App Directories.\n\n![Desktop Agent - Interop](/assets/api-2.png)\n\n### Desktop Agent API Standard Compliance\n\nAn FDC3 Standard compliant Desktop Agent implementation **MUST**:\n\n- Be able to provide the FDC3 API to applications in accordance with with any requirements defined for that platform, as defined in [Supported Platforms](supported-platforms) and linked specifications:\n  - For web applications this includes:\n    - Implementing the [Browser-Resident Desktop Agent spec](specs/browserResidentDesktopAgents) if it is intended to support apps running in a standard web browser.\n    - Implementing the [Preload Desktop Agent spec](specs/preloadDesktopAgents) if it is intended to support apps running in a container or other environment that supports injecting a global `fdc3` object.\n- Accept as input and return as output data structures that are compatible with the interfaces defined in this Standard.\n- Include implementations of the following [Desktop Agent](ref/DesktopAgent) API functions, as defined in this Standard:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener)\n  - [`addIntentListener`](ref/DesktopAgent#addintentlistener)\n  - [`addEventListener`](ref/DesktopAgent#addeventlistener)\n  - [`broadcast`](ref/DesktopAgent#broadcast)\n  - [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel)\n  - [`findInstances`](ref/DesktopAgent#findinstances)\n  - [`findIntent`](ref/DesktopAgent#findintent)\n  - [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n  - [`getInfo`](ref/DesktopAgent#getinfo)\n  - [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel)\n  - [`getUserChannels`](ref/DesktopAgent#getuserchannels)\n  - [`open`](ref/DesktopAgent#open)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext)\n- Provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to `raiseIntentForContext` that return multiple options), such as a resolver UI.\n  - Intent resolution MUST take into account any specified input or return context types\n  - Requests for resolution to apps returning a channel MUST include any apps that are registered as returning a channel with a specific type.\n- Return (JavaScript or platform appropriate) Error Objects with messages from the [`ChannelError`](ref/Errors#channelerror), [`OpenError`](ref/Errors#openerror), [`ResolveError`](ref/Errors#resolveerror) and [`ResultError`](ref/Errors#resulterror) enumerations as appropriate.\n- Provide an ID for each [`PrivateChannel`](ref/PrivateChannel) created via [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel) and prevent them from being retrieved via [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) by ID.\n- Only require app directories that they connect to to have implemented only the minimum requirements specified in the [App Directory API Part](../app-directory/spec) of this Standard.\n- Provide details of whether they implement optional features of the Desktop Agent API in the `optionalFeatures` property of the [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned by the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function.\n- Allow, by default, at least a 15 second timeout for an application, launched via [`fdc3.open`](../api/ref/DesktopAgent#open), [`fdc3.raiseIntent`](../api/ref/DesktopAgent#raiseintent) or [`fdc3.raiseIntentForContext`](../api/ref/DesktopAgent#raiseintentforcontext) to add any context listener (via [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener)) or intent listener (via [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener)) necessary to deliver context or intent and context to it on launch. This timeout only applies to listeners needed to receive context on launch; further intent and context listeners not required on launch MAY be added later.\n\nAn FDC3 Standard compliant Desktop Agent implementation **SHOULD**:\n\n- Support connection to one or more App Directories meeting the [FDC3 App Directory Standard](../app-directory/overview).\n- Qualify `appId` values received from an app directory with the hostname of the app directory server (e.g. `myAppId@name.domain.com`) [as defined in the app directory standard](../app-directory/overview#application-identifiers).\n- Allow applications to register an [`IntentHandler`](ref/Types#intenthandler) for particular Intent and Context type pairs by providing `interop.intents.listensFor` metadata in their AppD record.\n- Adopt the [recommended set of User channel definitions](#recommended-user-channel-set).\n- Ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.\n- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.\n- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.\n\nAn FDC3 Standard compliant Desktop Agent implementation **MAY**:\n\n- Make the Desktop Agent API available through modules, imports, or other means.\n- Support multiple routes for registration of an [`IntentHandler`](ref/Types#intenthandler) by an app to be considered during Intent resolution, including dynamic registration of apps at runtime.\n- Implement the following OPTIONAL [Desktop Agent](ref/DesktopAgent) API functions:\n  - [`joinUserChannel`](ref/DesktopAgent#joinuserchannel)\n  - [`leaveCurrentChannel`](ref/DesktopAgent#leavecurrentchannel)\n  - [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)\n- Implement the following deprecated API functions:\n  - [`addContextListener`](ref/DesktopAgent#addcontextlistener-deprecated) (without a contextType argument)\n  - [`getSystemChannels`](ref/DesktopAgent#getsystemchannels-deprecated) (renamed getUserChannels)\n  - [`joinChannel`](ref/DesktopAgent#joinchannel-deprecated) (renamed joinUserChannel)\n  - [`open`](ref/DesktopAgent#open-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntent`](ref/DesktopAgent#raiseintent-deprecated) (deprecated version that addresses apps via `name` field)\n  - [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext-deprecated) (deprecated version that addresses apps via `name` field)\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Functional Use Cases\n\n### Open an Application\n\nLinking from one application to another is a critical basic workflow that the web revolutionized via the hyperlink.  Supporting semantic addressing of applications across different technologies and platform domains greatly reduces friction in linking different applications into a single workflow.\n\n### Requesting Functionality From Another App\n\nOften, we want to link from one app to another to dynamically create a workflow.  Enabling this without requiring prior knowledge between apps is a key goal of FDC3 and is implemented via the raising of [intents](../intents/spec), which represent a desired action, to be performed with a [context](../context/spec) supplied as input.\n\nIntents provide a way for an app to request functionality from another app and defer the discovery and launching of the destination app to the Desktop Agent.  There are multiple models for interop that intents can support.\n\n- **Chain**:  In this case the workflow is completely handed off from one app to another (similar to linking).  Currently, this is the primary focus in FDC3.\n- **Client-Service**: A Client invokes a Service via the Intent, the Service performs some function, then passes the workflow back to the Client. Typically, there is a data payload type associated with this intent that is published as the standard contract for the intent.\n- **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.\n\n### Send/broadcast Context\n\nOn the financial desktop, applications often want to broadcast [context](../context/spec) to any number of applications.  Context sharing needs to support different groupings of applications, which is supported via the concept of 'channels', over which context is broadcast and received by other applications listening to the channel.  \n\nIn some cases, an application may want to communicate with a single application or service and to prevent other applications from participating in the communication. For single transactions, this can instead be implemented via a raised intent, which will be delivered to a single application that can, optionally, respond with data. Alternatively, it may instead respond with a [`Channel`](ref/Channel) or [`PrivateChannel`](ref/PrivateChannel) over which a stream of responses or a dialog can be supported.\n\n### Retrieve Metadata about the Desktop Agent implementation\n\nAn application may wish to retrieve information about the version of the FDC3 Standard supported by a Desktop Agent implementation and the name of the implementation provider.\n\nSince version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nimport { compareVersionNumbers, versionIsAtLeast } from \"@finos/fdc3\";\n\nif (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), \"1.2\")) {\n  await fdc3.raiseIntentForContext(context);\n} else {\n  await fdc3.raiseIntent(\"ViewChart\", context);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar version = (await _desktopAgent.GetInfo()).Fdc3Version;\n```\n\n</TabItem>\n</Tabs>\n\nThe [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst implementationMetadata = await fdc3.getInfo();\nconst { appId, instanceId } = implementationMetadata.appMetadata;\n\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar implementationMetadata = await _desktopAgent.GetInfo();\nvar appId = implementationMetadata.AppMetadata.AppId;\nvar instanceId = implementationMetadata.AppMetadata.InstanceId;\n```\n\n</TabItem>\n</Tabs>\n\n### Reference apps or app instance(s) and retrieve their metadata\n\nTo construct workflows between applications, you need to be able to reference specific applications and instances of those applications.\n\nFrom version 2.0 of the FDC3 Standard, Desktop Agent functions that reference or return information about other applications do so via an [`AppIdentifier`](ref/Types#appidentifier) type. [`AppIdentifier`](ref/Types#appidentifier) references specific applications via an `appId` from an [App Directory](../app-directory/overview) record and instances of that application via an `instanceId` assigned by the Desktop Agent.\n\nAdditional metadata for an application can be retrieved via the [`fdc3.getAppMetadata(appIdentifier)`](ref/DesktopAgent#getappmetadata) function, which returns an [`AppMetadata`](ref/Metadata#appmetadata) object. The additional metadata may include a title, description, icons, etc., which may be used for display purposes.\n\nIdentifiers for instances of an application may be retrieved via the [`fdc3.findInstances(appIdentifier)`](ref/DesktopAgent#findinstances) function.\n\n## Raising Intents\n\nRaising an Intent is a method for an application to request functionality from another application and, if desired, defer the discovery and launching of the destination app to the Desktop Agent.\n\n### Intents and Context\n\nWhen raising an intent a specific context is provided as input. The type of the provided context may determine which applications can resolve the intent.\n\nA context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents.\n\nTo raise an intent without a context, use the [`fdc3.nothing`](../context/ref/Nothing) context type. This type exists so that applications can explicitly declare that they support raising an intent without a context (when registering an `IntentHandler` or in an App Directory).\n\nAs an alternative to raising a specific intent, you may also raise an unspecified intent with a known context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent and then to raise it with the specified context for resolution.\n\n### Intent Results\n\nAn optional [`IntentResult`](ref/Types#intentresult) may also be returned as output by an application handling an intent. Results may be a single `Context` object, a `Channel` that may be used to send a stream of responses, or `void` (no result). The [`PrivateChannel`](ref/PrivateChannel) type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via [raising an intent](ref/DesktopAgent#raiseintent).\n\nFor example, an application handling a `CreateOrder` intent might return a context representing the order and including an ID, allowing the application that raised the intent to make further calls using that ID.\n\nAn optional result type is also supported when programmatically resolving an intent via [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext).\n\n### Resolvers\n\nSuccessful delivery of an intent depends first upon the Desktop Agent's ability to \"resolve the intent\" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext) and then raise the intent with a specific target application, e.g.:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// Find apps to resolve an intent to start a chat with a given contact\nconst appIntent = await fdc3.findIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait fdc3.raiseIntent(\"StartChat\", context, appIntent.apps[0]);\n\n//Find apps to resolve an intent and return a specified context type\nconst appIntent = await fdc3.findIntent(\"ViewContact\", context, \"fdc3.contact\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  try {\n    const result = await resolution.getResult();\n    console.log(`${resolution.source} returned ${JSON.stringify(result)}`);\n  } catch(resultError: ResultError) {\n    console.error(`${resolution.source} returned an error: ${resultError.message}`);\n  }\n} catch(resolveError: ResolveError) {\n  console.error(`${JSON.stringify(appIntent.apps[0])} returned an error: ${resolveError.message}`);\n}\n\n//Find apps to resolve an intent and return a channel\nconst appIntent = await fdc3.findIntent(\"QuoteStream\", context, \"channel\");\ntry {\n  const resolution = await fdc3.raiseIntent(appIntent.intent, context, appIntent.apps[0].name);\n  try {\n    const result = await resolution.getResult();\n    if (result && result.addContextListener) {\n      result.addContextListener(null, (context) => { \n        console.log(`received context: ${JSON.stringify(context)}`); \n      });\n    } else {\n      console.log(`${resolution.source} didn't return a channel! Result: ${JSON.stringify(result)}`);\n    }\n  } catch(resultError: ResultError) {\n    console.error(`${resolution.source} returned an error: ${resultError.message}`);\n  }\n} catch (resolveError: ResolveError) {\n  console.error(`${JSON.stringify(appIntent.apps[0])} returned an error: ${resolveError.message}`);\n}\n\n//Find apps that can perform any intent with the specified context\nconst appIntents = await fdc3.findIntentsByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\n// Find apps to resolve an intent to start a chat with a given contact\nvar appIntent = await _desktopAgent.FindIntent(\"StartChat\", context);\n// use the returned AppIntent object to target one of the returned \n// chat apps or app instances using the AppMetadata object\nawait _desktopAgent.RaiseIntent(\"StartChat\", context, appIntent.Apps.First());\n\n//Find apps to resolve an intent and return a specified context type\nvar appIntent = await _desktopAgent.FindIntent(\"ViewContact\", context, \"fdc3.contact\");\nvar resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\ntry\n{\n  var result = await resolution.GetResult();\n  System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned ${result}\");\n}\ncatch (Exception ex)\n{\n  System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned an error\");\n}\n\n//Find apps to resolve an intent and return a channel\nvar appIntent = await _desktopAgent.FindIntent(\"QuoteStream\", context, \"channel\");\ntry\n{\n  var resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First());\n  var result = await resolution.GetResult();\n  if (result is IChannel resolvedChannel)\n  {\n      await resolvedChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n  }\n  else\n  {\n      System.Diagnostics.Debug.WriteLine(\"Did not return a channel\");\n  }\n}\ncatch (Exception ex)\n{\n}\n\n//Find apps that can perform any intent with the specified context\nvar appIntents = await _desktopAgent.FindIntentsByContext(context);\n//use the returned AppIntent array to target one of the returned apps\nawait _desktopAgent.RaiseIntent(appIntents.First().Intent.Name, context, appIntents.First().Apps.First());\n```\n\n</TabItem>\n</Tabs>\n\nResult context types requested are represented by their type name. A channel may be requested by passing the string `\"channel\"` or a channel that returns a specific type via the syntax `\"channel<contextType>\"`, e.g. `\"channel<fdc3.instrument>\"`. Requesting intent resolution to an app returning a channel MUST include apps that are registered as returning a channel with a specific type.\n\n### Intent Resolution\n\nRaising an intent will return a Promise-type object that will resolve/reject based on a number of factors.\n\n#### Resolve\n\n- Intent was resolved unambiguously and the receiving app was launched successfully (if necessary).\n- Intent was ambiguous, a resolution was chosen by the end user, and the chosen application was launched successfully.\n\n#### Reject\n\n- No app matching the intent and context (if specified) was found.\n- A match was found, but the receiving app failed to launch.\n- The intent was ambiguous and the resolver experienced an error.\n\n#### Resolution Object\n\nIf the raising of the intent resolves (or rejects), a standard [`IntentResolution`](ref/Metadata#intentresolution) object will be passed into the resolver function with details of the application that resolved the intent and the means to access any results subsequently returned.\n\nFor example, to raise a specific intent:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntent(\"StageOrder\", context);\n}\ncatch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntent(\"StageOrder\", context);\n}\ncatch (Exception ex) { }\n```\n\n</TabItem>\n</Tabs>\n\nor to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntentForContext(context);\n  if (resolution.data) {\n    const orderId = resolution.data.id;\n  }\n} catch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntentForContext(context);\n    if (resolution is IContext resolvedContext)\n    {\n        var orderId = resolvedContext.ID;\n    }\n}\ncatch (Exception ex) { }\n```\n\n</TabItem>\n</Tabs>\n\nUse metadata about the resolving app instance to target a further intent\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\ntry {\n  const resolution = await fdc3.raiseIntent(\"StageOrder\", context);\n  ...\n\n  //some time later\n  await agent.raiseIntent(\"UpdateOrder\", context, resolution.source);\n}\ncatch (err: ResolveError) { ... }\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\ntry\n{\n    var resolution = await _desktopAgent.RaiseIntent(\"StageOrder\", context);\n\n    //some time later\n    await _desktopAgent.RaiseIntent(\"UpdateOrder\", context, resolution.Source);\n}\ncatch (Exception ex) {  }\n```\n\n</TabItem>\n</Tabs>\n\nRaise an intent and retrieve either data or a channel from the IntentResolution:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nlet resolution = await agent.raiseIntent(\"intentName\", context);\ntry {\n  const result = await resolution.getResult();\n  /* Detect whether the result is Context or a Channel by checking for properties unique to Channels. */\n  if (result && result.broadcast) { \n    console.log(`${resolution.source} returned a channel with id ${result.id}`);\n  } else if (result) {\n    console.log(`${resolution.source} returned data: ${JSON.stringify(result)}`);\n  } else {\n    console.error(`${resolution.source} didn't return anything`);\n  }\n} catch(err: ResultError) {\n  console.error(`${resolution.source} returned a data error: ${err.message}`);\n}\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar resolution = await _desktopAgent.RaiseIntent(\"QuoteStream\", new Instrument(new InstrumentID() { Ticker = \"AAPL\" }));\ntry\n{\n    var result = await resolution.GetResult();\n\n    //check that we got a result and that it's a channel\n    if (result is IChannel channel)\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned a channel with id {channel.Id}\");\n    }\n    else if (result is IContext context)\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned data {context}\");\n    }\n    else\n    {\n        System.Diagnostics.Debug.WriteLine($\"{resolution.Source} didn't return anything\");\n    }\n}\ncatch (Exception ex)\n{\n    System.Diagnostics.Debug.WriteLine($\"{resolution.Source} returned an error\");\n}\n```\n\n</TabItem>\n</Tabs>\n\n### Register an Intent Handler\n\nApplications need to let the system know the intents they can support.  Typically, this SHOULD be done via registration with an [App Directory](../app-directory/spec) by providing `interop.intents.listensFor` metadata. However, Desktop Agent implementations MAY support dynamic registration of an [`IntentHandler`](ref/Types#intenthandler) by an app at runtime (for example, when they add an `IntentListener` via the API) to allow for ad-hoc registration which may be helpful at development time.  Although dynamic registration is not part of this specification, a Desktop Agent agent MAY choose to support any number of registration paths.\n\nWhen an instance of an application is launched, it is expected to add an [`IntentHandler`](ref/Types#intenthandler) function to the Desktop Agent for each intent it has registered by calling the [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) function of the Desktop Agent. Doing so allows the Desktop Agent to pass incoming intents and contexts to that instance of the application. Hence, if the application instance was spawned in response to the raised intent, then the Desktop Agent must wait for the relevant intent listener to be added by that instance before it can deliver the intent and context to it. In order to facilitate accurate error responses, calls to `fdc3.raiseIntent` should not return an `IntentResolution` until the intent handler has been added and the intent delivered to the target app.\n\nIntent handlers SHOULD be registered via [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations. Individual Desktop Agent implementations MAY support longer timeouts or configuration to control or extend timeouts.\n\n### Originating App Metadata\n\nOptional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered intent handlers. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n\n### Compliance with Intent Standards\n\nIntents 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.\n\nIt is expected that App Directories SHOULD also curate listed apps and ensure that they are complying with declared intents.\n\n## Context Channels\n\nContext channels allows a set of apps to share a stateful piece of data between them, and be alerted when it changes.  Use cases for channels include color linking between applications to automate the sharing of context and topic based pub/sub such as theme.\n\n### Types of Channel\n\nThere are three types of channels, which have different visibility and discoverability semantics:\n\n1. ***User channels***, which:\n\n    - facilitate the creation of user-controlled context links between applications (often via the selection of a color channel),\n    - are created and named by the desktop agent,\n    - are discoverable (via the [`getUserChannels()`](ref/DesktopAgent#getuserchannels) API call),\n    - can be 'joined' (via the [`joinUserChannel()`](ref/DesktopAgent#joinuserchannel) API call).\n\n    :::note\n\n    Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels).\n\n    :::\n\n    :::note\n\n    Earlier versions of FDC3 included the concept of a 'global' system channel\n    which was deprecated in FDC3 1.2 and removed in FDC3 2.0.\n\n    :::\n\n2. ***App channels***, which:\n\n    - facilitate developer controlled messaging between applications,\n    - are created and named by applications (via the [`getOrCreateChannel()`](ref/DesktopAgent#getorcreatechannel) API call),\n    - are not discoverable,\n    - are interacted with via the [Channel API](ref/Channel) (accessed via the desktop agent [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API call)\n\n3. ***Private*** channels, which:\n\n    - facilitate private communication between two parties,\n    - have an auto-generated identity and can only be retrieved via a raised intent.\n\nChannels are interacted with via `broadcast` and `addContextListener` functions, allowing an application to send and receive Context objects via the channel. For User channels, these functions are provided on the Desktop Agent, e.g. [`fdc3.broadcast(context)`](ref/DesktopAgent#broadcast), and apply to channels joined via [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel). For App channels, a channel object must be retrieved, via [`fdc3.getOrCreateChannel(channelName)`](ref/DesktopAgent#getorcreatechannel), which provides the functions, i.e. [`myChannel.broadcast(context)`](ref/Channel#broadcast) and [`myChannel.addContextListener(context)`](ref/Channel#addcontextlistener). For `PrivateChannels`, a channel object must also be retrieved, but via an intent raised with [`fdc3.raiseIntent(intent, context)`](ref/DesktopAgent#raiseintent) and returned as an [`IntentResult`](ref/Types#intentresult).\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are also listening on the channel.\n\n### Joining User Channels\n\nApps can join *User channels*.  An app can only be joined to one User channel at a time.  \n\nWhen an app is joined to a User channel, calls to [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be routed to that channel and listeners added through [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will receive context broadcasts from other apps also joined to that channel. If an app is not joined to a User channel [`fdc3.broadcast`](ref/DesktopAgent#broadcast) will be a no-op and handler functions added with  [`fdc3.addContextListener`](ref/DesktopAgent#addcontextlistener) will not receive any broadcasts. However, apps can still choose to listen and broadcast to specific channels (both User and App channels) via the methods on the [`Channel`](ref/Channel) class.\n\nWhen an app joins a User channel, or adds a context listener when already joined to a channel, it will automatically receive the current context for that channel.\n\nIt is possible that a call to join a User channel could be rejected.  If for example, the desktop agent wanted to implement controls around what data apps can access.\n\nJoining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace.  Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinUserChannel()`](ref/DesktopAgent#joinuserchannel), [`fdc3.getCurrentChannel()`](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).\n\nThere SHOULD always be a clear UX indicator of what channel an app is joined to.\n\n#### Examples\n\nTo find a User channel, one calls:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// returns an array of channels\nconst allChannels = await fdc3.getUserChannels();\nconst redChannel = allChannels.find(c => c.id === \"red\");\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar allChannels = await _desktopAgent.GetUserChannels();\nvar redChannel = allChannels.Single(c => c.Id == \"red\");\n```\n\n</TabItem>\n</Tabs>\n\nTo join a User channel, one calls:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nfdc3.joinUserChannel(redChannel.id);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nawait _desktopAgent.JoinUserChannel(redChannel.Id);\n```\n\n</TabItem>\n</Tabs>\n\nCalling `fdc3.broadcast` will now route context to the joined channel.\n\nChannel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.\n\n  > Prior to FDC3 2.0, 'user' channels were known as 'system' channels. They were renamed in FDC3 2.0 to reflect their intended usage, rather than the fact that they are created by system (which could also create 'app' channels). The `joinChannel` function was also renamed to `joinUserChannel` to clarify that it is only intended to be used to join 'user', rather than 'app', channels.\n\n### Recommended User Channel Set\n\nDesktop Agent implementations SHOULD use the following set of channels, to enable a consistent user experience across different implementations. Desktop Agent implementation MAY support configuration of the user channels.\n\n:::note\nFuture versions of the FDC3 Standard may support connections between desktop agents, where differing user channel sets may cause user experience issues.\n:::\n\n```ts\nconst recommendedChannels = [\n  {\n    id: \"fdc3.channel.1\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 1\",\n      color: \"red\",\n      glyph: \"1\",\n    },\n  },\n  {\n    id: \"fdc3.channel.2\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 2\",\n      color: \"orange\",\n      glyph: \"2\",\n    },\n  },\n  {\n    id: \"fdc3.channel.3\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 3\",\n      color: \"yellow\",\n      glyph: \"3\",\n    },\n  },\n  {\n    id: \"fdc3.channel.4\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 4\",\n      color: \"green\",\n      glyph: \"4\",\n    },\n  },\n  {\n    id: \"fdc3.channel.5\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 5\",\n      color: \"cyan\",\n      glyph: \"5\",\n    },\n  },\n  {\n    id: \"fdc3.channel.6\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 6\",\n      color: \"blue\",\n      glyph: \"6\",\n    },\n  },\n  {\n    id: \"fdc3.channel.7\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 7\",\n      color: \"magenta\",\n      glyph: \"7\",\n    },\n  },\n  {\n    id: \"fdc3.channel.8\",\n    type: \"user\",\n    displayMetadata: {\n      name: \"Channel 8\",\n      color: \"purple\",\n      glyph: \"8\",\n    },\n  },\n];\n```\n\n### Direct Listening and Broadcast on Channels\n\nWhile joining User channels (using [`fdc3.joinUserChannel`](ref/DesktopAgent#joinuserchannel)) automates a lot of the channel behavior for an app, it has the limitation that an app can only be 'joined' to one channel at a time.  However, an app may instead retrieve an App [`Channel`](ref/Channel) Object via the [`fdc3.getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) API, create a [`PrivateChannel`](ref/PrivateChannel) via the [`fdc3.createPrivateChannel`](ref/DesktopAgent#createprivatechannel) API, or by raising an intent that returns a channel created by another app. The `Channel` object may then be used to listen to and broadcast on that channel directly using the [`Channel.addContextListener`](ref/Channel#addcontextlistener) and the [`Channel.broadcast`](ref/Channel#broadcast) APIs. FDC3 imposes no restriction on adding context listeners or broadcasting to multiple channels.\n\n### App Channels\n\nApp Channels are topics dynamically created by applications connected via FDC3. For example, an app may create a named App Channel to broadcast data or status that is specific to that app to other apps that know to connect to the channel with that name.\n\nTo get (or create) a [`Channel`](ref/Channel) reference, then interact with it:\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\nconst appChannel = await fdc3.getOrCreateChannel(\"my_custom_channel\");\n// get the current context of the channel\nconst current = await appChannel.getCurrentContext();\n// add a listener\nawait appChannel.addContextListener(null, context => {...});\n// broadcast to the channel\nawait appChannel.broadcast(context);\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar appChannel = await _desktopAgent.GetOrCreateChannel(\"my_custom_channel\");\n// get the current context of the channel\nvar current = await appChannel.GetCurrentContext(null);\n// add a listener\nawait appChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n// broadcast to the channel\nawait appChannel.Broadcast(context);\n```\n\n</TabItem>\n</Tabs>\n\nAn app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to.\n\n<Tabs groupId=\"lang\">\n<TabItem value=\"ts\" label=\"TypeScript/JavaScript\">\n\n```ts\n// check for current fdc3 channel\nlet joinedChannel = await fdc3.getCurrentChannel()\n//current channel is null, as the app is not currently joined to a channel\n\n//add a context listener for channels we join\nconst listener = await fdc3.addContextListener(null, context => { ... });\n\n//retrieve an App channel and add a listener that is specific to that channel\nconst myChannel = await fdc3.getOrCreateChannel(\"my_custom_channel\");\nconst myChannelListener = await myChannel.addContextListener(null, context => { ... });\n\nfdc3.joinUserChannel('blue')\njoinedChannel = await fdc3.getCurrentChannel()\n//current channel is now the 'blue' channel\n```\n\n</TabItem>\n<TabItem value=\"dotnet\" label=\".NET\">\n\n```csharp\nvar joinedChannel = await _desktopAgent.GetCurrentChannel();\n// current channel is null, as the app is not currently joined to a channel\n\n// add a context listener for channels we join\nvar listener = await _desktopAgent.AddContextListener<IContext>(null, (context, metadata) => { });\n\n// retrieve an App Channel and add a listener that is specific to that channel\nvar myChannel = await _desktopAgent.GetOrCreateChannel(\"my_custom_channel\");\nvar myChannelListener = await myChannel.AddContextListener<IContext>(null, (context, metadata) => { });\n\nawait _desktopAgent.JoinUserChannel(\"blue\");\njoinedChannel = await _desktopAgent.GetCurrentChannel();\n// current channel is now the \"blue\" channel\n```\n\n</TabItem>\n</Tabs>\n\nif another application broadcasts to \"my_custom_channel\" (by retrieving it and broadcasting to it via `myChannel.broadcast()`) then the broadcast will be received by the specific listener (`myChannelListener`) but NOT by the listener for joined channels (`listener`).\n\n### Private Channels\n\nA [`PrivateChannel`](ref/PrivateChannel) is created to support the return of a stream of responses from a raised intent, or private dialog between two applications.\n\nIt is intended that Desktop Agent implementations:\n\n- SHOULD restrict external apps from listening or publishing on this channel.\n- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`.\n- MUST provide the `id` value for the channel as required by the `Channel` interface.\n\nThe `PrivateChannel` type also supports synchronization of data transmitted over returned channels. They do so by extending the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected.\n\n### Broadcasting and listening for multiple context types\n\nThe [Context specification](../context/spec#assumptions) recommends that complex context objects are defined using simpler context types for particular fields. For example, a `Position` is composed of an `Instrument` and a holding amount. This leads to situations where an application may be able to receive or respond to context objects that are embedded in a more complex type, but not the more complex type itself. For example, a pricing chart might respond to an `Instrument` but doesn't know how to handle a `Position`.\n\nTo facilitate context linking in such situations it is recommended that applications `broadcast` each context type that other apps (listening on a User Channel or App Channel) may wish to process, starting with the simpler types, followed by the complex type. Doing so allows applications to filter the context types they receive by adding listeners for specific context types - but requires that the application broadcasting context make multiple broadcast calls in quick succession when sharing its context.\n\n### Originating App Metadata\n\nOptional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered context handlers on all types of channel. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/specs/browserResidentDesktopAgents.md",
    "content": "---\nid: browserResidentDesktopAgents\nsidebar_label: Browser Desktop Agents\ntitle: Browser-Resident Desktop Agents (2.2)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nBrowser Resident Desktop Agents (DAs) are an experimental feature added to FDC3 in 2.2. Limited aspects of their design may change in future versions and they are exempted from the FDC3 Standard's normal versioning and deprecation policies in order to facilitate any necessary change.\n\n:::\n\nThis document specifies the required behavior for Browser-Resident Desktop Agents (DA). Such agents allow FDC3 applications running directly in a browser to participate in FDC3 interop by way of a `getAgent()` function that is provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) and a standardized communication protocol. This approach is in contrast to \"Preload DAs\" which run on technology that allows the FDC3 interface to be injected (such as Electron, WebView2 or a browser-extension based implementation).\n\nThis specification only applies to apps running in a browser and therefore assumes use of JavaScript/TypeScript and HTML APIs. Implementations in other languages such as .NET are not covered.\n\nAlong with this specification, a new general connection strategy has been established for FDC3 compliant web-applications: FDC3 compliant apps SHOULD make use of `getAgent()` function provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) to retrieve their FDC3 interface (an instance of an implementation of the [`DesktopAgent`](../ref/DesktopAgent) interface). Apps that follow these guidelines will be able to interop through either Browser-Resident DAs or [Preload DAs](./preloadDesktopAgents) without the inclusion of code or libraries specific to a particular Desktop Agent vendor or implementation. We refer to this concept as Write Once Run Anywhere (WORA).\n\n:::info\n\nPrior to FDC3 2.2, only [Preload Desktop Agents](./preloadDesktopAgents) were supported.  \n\n:::\n\n:::note\n\nThis document covers the requirements for _implementors of Browser-Resident Desktop Agents_. The `getAgent()` function that applications use to gain access to an FDC3 interface is provided by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3). Many behavioral details of `getAgent()` are purposefully omitted from this document in order to reduce the required scope of understanding. Please refer to the [getAgent() specification in the FDC3 Web Connection Protocol](webConnectionProtocol.md) for information on how the client side operates or [supported platforms](../supported-platforms) for details of how to access the Desktop Agent API in an application.\n\n:::\n\n:::tip\n\nWhen referencing \"DA\" in the subsequent sections of this document we will hereafter always mean a \"Browser-Resident Desktop Agent\" - code that runs in a browser page (iframe or window) and which conforms to this specification.\n\n:::\n\n## Launching apps\n\nAs a prerequisite for launching an app via FDC3 in the browser, a DA must first exist as running code in a browser window (See failover functions for an exception to this rule), although that code MAY also connect to or rely on remotely hosted services. We will refer to this window as the \"DA Window\".\n\nAs the DA typically acts as a launcher for applications, it will often be the case that the DA window is related to the application window(s) in that it may have created the application window with `window.open()` or have created an iframe and loaded the application URL into it. Hence, the DA window may be referred to as a 'parent' (window or frame) of the application frame and the relationship may be used to implement communication between the frames.\n\n:::note\n\nIt is possible to have multiple DA Windows. For instance, a DA may propagate itself into new windows. Communication and coordination between DA Windows is an implementation detail and is not covered by this specification.\n\n:::\n\nWhen an app runs `getAgent()`, it checks for the existence of `window.parent`, `window.opener` and `window.parent.opener` (and will continue up the chain of parent frames, e.g. `window.parent.parent`, `window.parent.parent.opener` until the reference to the next parent is equal to the current one (e.g. `window.parent.parent === window.parent` indicating that the frame does not have a parent). `getAgent()` will then send a standardized `WCP1Hello` message to each parent window or frame reference via [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) in order to discover a DA.\n\nHence, apps may be launched:\n\n1. By creating iframes in a DA Window\n2. By calling `window.open` from a DA Window\n3. By creating iframes in a window that was opened from a DA Window\n\nand the Desktop Agent application will be found in a 'parent' of the application frame.\n\n## Responding to app instance connections - Web Connection Protocol (WCP)\n\nBrowser Resident DAs MUST call `window.addEventListener(\"message\", ...)` to receive incoming connection requests from apps, in the form of [`\"WCP1Hello\"`](pathname:///schemas/2.2/api/WCP1Hello.schema.json) messages defined in the [Web Connection Protocol](./webConnectionProtocol).\n\nUpon receiving an incoming [`\"WCP1Hello\"`](pathname:///schemas/2.2/api/WCP1Hello.schema.json) the Desktop Agent MUST either:\n\n1. Respond with a [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json) message (as defined in the [Web Connection Protocol](./webConnectionProtocol)).\n    - This message indicates that `getAgent()` should create an iframe, load the provided URL (for an adaptor to the Desktop Agent) into it and then restart the connection process by sending [`\"WCP1Hello\"`](pathname:///schemas/2.2/api/WCP1Hello.schema.json) to the iframe.\n\n    :::warning\n\n    The [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Wherever these are used in app implementations, please advise app implementors to include domains from which the adaptor content is served.\n\n    :::\n2. Create a [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) with two entangled `MessagePort` instances that will be used for further communication with the application.\n    - Before returning one of `MessagePort` instances, the DA MUST set up event listeners to receive and process a [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message from the application.\n    - To deliver the `MessagePort`, the DA MUST respond to the event's `source` window by responding with a [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json) message (as defined in the [Web Connection Protocol](./webConnectionProtocol)) and append `port2` from the `MessageChannel` to the message.\n\nAll further communication is conducted over the `MessageChannel`. The Desktop Agent should consider the newly created port to be inactive until a [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message is received via the `MessagePort` and successfully processed.\n\n### Validating app identity\n\nThe first message received by the Desktop Agent on `MessagePort` `port1` from an application via a `MessageChannel` it created MUST be [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json). Once received and successfully processed, the Desktop Agent should respond with a [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json) message containing an `appId`, `instanceId` and `instanceUuid` to identify the app and this specific instance and then enable processing of [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol.md) messages for this application. If validation fails, it should instead respond with [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityFailedResponse.schema.json) and close the `MessageChannel`.\n\nApp identity is validated and an `appId` assigned by matching the application to an AppD record already known to the Desktop Agent. This is achieved by matching  `identityUrl` (supplied by the application via the `getAgent()` implementation) to the `details.url` field of the known App Directory records.\n\nAs web applications may vary their URL during use, or serve multiple applications from the same origin (differentiated by path, search params and/or hash), care must be taken in matching URLs to AppD records. Two URLs are sent to the Desktop Agent in the [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message:\n\n- `identityUrl`: the URL to match to the App Directory record.\n- `actualUrl`: the current URL of the application, which MUST be captured automatically by the `getAgent()` implementation.\n\nApplications _may_ specify the `identityUrl` value as an argument to `getAgent()`. If not specified, the `getAgent()` implementation MUST use the current URL of the application. The Desktop Agent MUST validate that the origin of the `identityUrl` is the same as the origin of _both_ the `actualUrl` and the `WCPValidateAppIdentity` message sent over the `MessagePort`. The Desktop Agent MUST then match the URL to that of applications known to the Desktop Agent.\n\nThe `actualUrl` field may be used for logging and debug purposes by the Desktop Agent and it differing from the `identityUrl` indicates that the application provided an override via `getAgent()`.\n\nOwing to the fact that the different parts of a URL (origin, path, search parameters, anchor) are used differently by web applications, matching of the `identityUrl` to known application URLs can be more complex than a simple string match. To allow application developers control the requirements of matching, Desktop Agents SHOULD consider a URL to match if all elements (origin, path, search parameters, anchor) present in the App Directory record's URL are present in the `identityUrl`. As multiple App Directory records may match a given identity URL, Desktop Agents SHOULD look for the best match that meets the requirements.\n\nFor example, given an identity URL `url`, and an array of App Directory records `appDRecords`, a Desktop Agent MAY implement matching as follows:\n\n```js\n/** Return the AppD record whose URL best matches the input URL or `null` if no\n *  match is found. To be considered a match all elements of the AppD URL \n *  (origin, path, searchParams and hash) MUST be found in the input URL.\n *  The best match is the AppD URL that contains the most elements from the\n *  input URL.\n */  \nlet matchUrlToAppD = (url, appDRecords) => {\n    //parse the URL\n    const inputUrl = new URL(url);\n\n    //fn to trim trailing / from paths\n    const trimTrailingSlash = (path) => {\n        if (path.endsWith(\"/\")) {\n            const out = path.slice(0, -1);\n            //return null if it was just a /\n            return out === \"\" ? null : out;\n        } else {\n            return path;\n        }\n    };\n                               \n    const matchScores = [];\n\n    //score AppD records based on the match of their URL to the input URL\n    // if any component of the AppD record URL is missing from input URL score 0, \n    // otherwise count the number of input elements matched.\n    appDRecords.map((record) => {\n        //record must contain a URL\n        if (!record.details?.url) { return; }\n        \n        //parse record URL\n        const parsedUrl = new URL(record.details.url);\n        \n        //origin of URL must match record\n        if (parsedUrl.origin !== inputUrl.origin) { return; }\n        let score = 1;\n        \n        //path must match if present in AppD record - Path of \"/\" is ignored\n        const appDPath = trimTrailingSlash(parsedUrl.pathname);\n        if (appDPath) {\n            if (trimTrailingSlash(inputUrl.pathname) != appDPath) {\n                return;\n            } else {\n                score++;\n            }\n        }\n        \n        //hash must match if present in AppD record\n        if (parsedUrl.hash) {\n            if (inputUrl.hash != parsedUrl.hash) {\n                return; \n            } else {\n                score++;\n            }\n        }\n        \n        if (!!parsedUrl.search) {\n            //search params present in AppD record must be present in URL\n            const recordSearchKeys = parsedUrl.searchParams.keys().toArray();\n            for (let i=0; i<recordSearchKeys.length; i++) {\n                const key = recordSearchKeys[i];\n                if (inputUrl.searchParams.get(key) !== parsedUrl.searchParams.get(key)) {\n                    return;\n                }\n            }\n            //count matched input URL search params for scoring\n            inputUrl.searchParams.keys().forEach((key) => {\n                if (parsedUrl.searchParams.get(key) === inputUrl.searchParams.get(key)) {\n                    score++;\n                } \n            });\n        }\n        \n        //everything present in the record was found in the inputUrl\n        matchScores.push([score, record]);\n    });\n    \n    //return the best scoring match (ignore ties)\n    matchScores.sort((a,b) => b[0]-a[0]);\n    return matchScores[0][1] ?? null;\n};\n```\n\n### Validating instance identity\n\nIf the [`\"WCP4ValidateAppIdentity\"`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) request message contains `instanceId` and `instanceUuid` fields then the window may represent an app instance that has navigated or refreshed and requires reconnecting with the previously assigned `instanceId`. The DA SHOULD reissue the same instanceId if the `instanceUuid`, `appId`, `WindowProxy` object and origin provided **all** match what is already on record and return details via the [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json) message.\n\nIf an `instanceId` and `instanceUuid` are not provided or do not pass the checks defined above, a new `instanceId` and `instanceUuid` should be generated by the Desktop Agent and returned in the [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json) message. All generated `instanceId` and `instanceUuid` values should be retained by the DA (for the session or other appropriate period of time), along with a reference to the `WindowProxy` (`event.source` from the initial message received), as these can later be used for comparison to help determine if a new connection request is coming from a previously connected window which may or may not represent an existing app instance. If a previously connected window is reconnecting, any existing `MessageChannel` instance created for it can be cleaned up.  \n\nDetails of the received `instanceId` and `instanceUuid` are stored by the `getAgent()` implementation in [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) within the application window and are automatically reused when reconnecting to the Desktop Agent. SessionStorage is used as it is scoped to a particular window (rather than origin, as is the case with LocalStorage), allowing separate storage for each app instance.\n\n:::warning\n\nApps launched via a call to `window.open()` from a window or app instance on the same origin can appear to be the original window. This is because browsers may clone SessionStorage for newly opened windows. When a child window calls `getAgent()` with the same `appId`, `instanceId` and `instanceUuid` as the parent window, it will appear to the DA that a navigation event occurred on the parent window. DAs therefore MUST also compare the `WindowProxy` object that is used to establish each connection to differentiate such cloned instances. If the WindowProxy objects do not match, then a new `instanceId` and `instanceUuid` MUST be assigned.\n\n:::\n\nFor more details on the connection process, please see the documentation for the [Web Connection Protocol](./webConnectionProtocol).\n\n### Disconnects\n\nDAs are responsible for tracking when app windows close or navigate, which is necessary to provide accurate responses to the `findIntent`, `findIntentsByContext` & `findInstances` API calls, and to correctly resolve raised intents.\n\n:::info\n\nThe HTML Standard specifies an [onclose event handler on `MessagePort`](https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageport-onclose) which would provide an ideal event-based solution for tracking the closing of app windows. However, this event is not currently implemented in Chrome/Chromium due to security concerns (it reveals the garbage collection activity of the process holding the other end of the pipe, see comment on [whatwg/html/issues/1766](https://github.com/whatwg/html/issues/1766#issuecomment-1958782062), see also proposals to [restrict when MessagePort's onclose event can fire](https://github.com/whatwg/html/issues/10201)).\n\n:::\n\nChecking whether an application has closed may be achieved by a number of approaches:\n\n- By checking the `closed` property of WindowProxy objects that were received via the `source` property of the original `WCP1Hello` message, or any subsequent message over the `MessageChannel`. `closed` will be true if the window or frame was closed or destroyed, or the window or frame has navigated cross-domain.\n  - However, it should be noted that the `closed` will be `false` if the window has navigated same-domain, but is no longer an FDC3 app or has become a different FDC3 app. Hence, checking the `closed` property will not catch all cases.\n  - If an equivalent `WindowProxy` object (`WindowProxy` objects can be compared with `==` and will be equivalent if they represent the same window) is received from a different application the DA should consider the original application using that `WindowProxy` to have closed.\n- By receiving a `WCP6Goodbye` message from the application when it is closing. The `getAgent()` implementation automates the sending of this message via the HTML Standard's [Page Life Cycle API](https://wicg.github.io/page-lifecycle/spec.html). Specifically, the `getAgent()` implementation MUST attempt to detect windows closing by listening for the `pagehide` event and considering a window to be closed if the event's `persisted` property is `false`.\n  - Note that the `pagehide` event may not fire if the window's render thread crashes or is closed while 'frozen'.\n- By polling the application for responses via the `heartbeatEvent` and `heartbeatAcknowledgement` messages provided in the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol#checking-apps-are-alive). These message may be used for both periodic and on-demand polling by DA implementations. On-demand polling could, for example, be used to check that all instances returned in a findIntent response or displayed in an intent resolver are still alive.\n  - Desktop Agents MAY determine their own timeout, or support configuration, to be used for considering an application to have closed as this may be affected by the implementation details of app and DAs.\n\nFinally, Desktop Agents SHOULD retain instance details for applications that have closed as they may appear to close during navigation events, or may navigate away and then navigate back. By retaining the instance data (`instanceId`, `instanceUuid` and `WindowProxy`) the same instance identity can be maintained or reissued. There is no standard length of time that such details should be retained, hence, Desktop Agents MAY determine for themselves how long to retain instance details for closed instances.\n\n## Responding to app communications with Desktop Agent Communication Protocol (DACP)\n\nAfter validating an application's identity and any instance identity to be reused, the Desktop Agent is ready to support communication with the application. This is achieved via the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol) (DACP) over the `MessageChannel` established in the previous steps.\n\n## Implementing DAs in hidden iframes\n\nAs described above, DA providers can leverage hidden iframes to establish a communication mechanism that is independent of a parent window or frame. This approach allows apps to reconnect to a DA even when the parent window or frame has closed, or to connect a DA they've started themselves via a `failover` function.\n\nThe hidden iframe URL can be provided in two ways:\n\n1. By a parent window or frame - This allows DAs to handle communication via a hidden iframe that loads a known URL. The main benefit of this approach is that it can allow a system to continue to operate even if the parent window or frame is closed.\n2. By a `failover` function - When no parent DA can be found (such as when a tab is opened directly by an end user) then a failover function can create a hidden iframe and return a reference to it (a `WindowProxy`) that is used to initiate communication via the WCP in the same way as we do with a parent window or frame. Alternatively, a `DesktopAgent` implementation may be loaded directly and returned from the `failover` function, which `getAgent()` will pass-through.\n\n## Channel Selector and Intent Resolver User Interfaces\n\nChannel Selector and Intent Resolver user-interfaces are normally provided by Desktop Agents to applications. However, when running in a web browser, a DA may not have the ability to present a channel selector in a window that has been opened with `window.open()`, and it may be challenging to display a secondary window over the application when needed (due to pop-up blocking and user preferences).\n\nThe `getAgent()` implementation can facilitate the injection and management of iframes in an application window. An app may provide the optional `channelSelector` and `intentResolver` parameters to the `getAgent()` to indicate whether or not they need these interfaces. For example, the apps may not raise intents. Some apps may also resolve intents internally by leveraging the Desktop Agent's `findIntent` or `findIntentsForContext` API functions. In these situations, the apps won't need a DA-provided interface. Once an app calls `getAgent()`, the parameters that the app provides are forwarded onto the Desktop Agent in the `WCP1Hello` connection message.\n\nDesktop Agents MAY implement their own user interfaces for channel selection and intent resolution. The URL for each interface may be returned in the `channelSelectorUrl` and `intentResolverUrl` properties of the payload of the `WCP3Handshake` message sent by the DA during the connection sequence. Alternatively, if the Desktop Agent is able to provide these user interfaces by other means (for example DAs that render applications in iframes within a window they control may use other iframes to render these UIs) or if they app indicated that it did not need them then `channelSelectorUrl` and `intentResolverUrl` MAY be set to `false`. Finally, `channelSelectorUrl` and `intentResolverUrl` MAY be set to `true` to indicate that `getAgent()` should use the default reference implementations of these UIs provided via the [https://fdc3.finos.org](https://fdc3.finos.org) website.\n\n:::warning\n\nThe [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) directives [frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src), [child-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src) and [default-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src) can prevent iframes injected into an application from loading content. Where these are used in app implementations, please advise app implementors to include domains from which the UI implementations are served (including [fdc3.finos.org](https://fdc3.finos.org/) if you are working with the reference Intent Resolver and Channel Selector UIs).\n\n:::\n\nUser interface iframes are initially injected into the application window with CSS that prevents their display:\n\n```css\n{\n    width: \"0\";\n    height: \"0\";\n    position: \"fixed\";\n}\n```\n\nand are always displayed with `position: \"fixed\"` so that they are not part of the document flow.\n\nImplementations of the UIs may then indicate a limited set of CSS to apply to their frame in the initial `Fdc3UserInterfaceHello` message (when the width and height will be removed if not explicitly set in that message), and later adjust that via `Fdc3UserInterfaceRestyle`. See the [Controlling injected User Interfaces section](./desktopAgentCommunicationProtocol#controlling-injected-user-interfaces) in the DACP specification for more details.\n\nCommunication between the `DesktopAgentProxy` and the iframes it injects is achieved via a similar mechanism to that used for communication between an app and the Desktop Agent: a `MessageChannel` is established between the app and iframe, via a `postMessage` sent from the iframe (`Fdc3UserInterfaceHello`) and responded to by the `DesktopAgentProxy` in the app's window (`Fdc3UserInterfaceHandshake`), with a `MessagePort` from a `MessageChannel` appended.\n\nA further set of messages are provided for working with the injected user interfaces over their `MessageChannel` as part of the DACP, these are: `Fdc3UserInterfaceRestyle`, `Fdc3UserInterfaceDrag`, `Fdc3UserInterfaceChannels`, `Fdc3UserInterfaceChannelSelected`, `Fdc3UserInterfaceResolve` and `Fdc3UserInterfaceResolveAction`.\n\nSee the [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol) (DACP) for more details.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/specs/desktopAgentCommunicationProtocol.md",
    "content": "---\nid: desktopAgentCommunicationProtocol\nsidebar_label: Desktop Agent Communication Protocol \ntitle: Desktop Agent Communication Protocol (2.2)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nFDC3's Desktop Agent Communication Protocol (DACP) is an experimental feature added to FDC3 in 2.2. Limited aspects of its design may change in future versions and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\nThe Desktop Agent Communication Protocol (DACP) constitutes a set of standardized JSON messages or 'wire protocol' that can be used to implement an interface to a Desktop Agent, encompassing all API calls events defined in the [Desktop Agent API](../ref/DesktopAgent.md). For example, the DACP is used by the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) to communicate with Browser-Resident Desktop Agents or a connection setup via the [FDC3 Web Connection Protocol](./webConnectionProtocol).\n\n## Protocol conventions\n\nDACP messages are defined in [JSON Schema](https://json-schema.org/) in the [FDC3 github repository](https://github.com/finos/FDC3/tree/fdc3-for-web/schemas/api).\n\n:::tip\n\nTypeScript types representing all DACP and WCP messages are generated from the JSON Schema source and can be imported from the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3):\n\n```ts\nimport { BrowserTypes } from \"@finos/fdc3\";\n```\n\n:::\n\nThe protocol is composed of several different classes of message, each governed by a message schema:\n\n1. **App Request Messages** ([`AppRequest` schema](pathname:///schemas/2.2/api/appRequest.schema.json)):\n    - Messages sent by an application representing an API call, such as [`DesktopAgent.broadcast`](../ref/DesktopAgent#broadcast), [`Channel.addContextListener`](../ref/Channel#addcontextlistener), or [`Listener.unsubscribe`](../ref/Types#listener).\n    - Message names all end in 'Request'.\n    - Each instance of a request message sent is uniquely identified by a `meta.requestUuid` field.\n\n2. **Agent Response Messages** ([`AgentResponse` schema](pathname:///schemas/2.2/api/agentResponse.schema.json)):\n    - Response messages sent from the DA to the application, each relating to a corresponding _App Request Message_.\n    - Message names all end in 'Response'.\n    - Each instance of an Agent Response Message is uniquely identified by a `meta.responseUuid` field.\n    - Each instance of an Agent Response Message quotes the `meta.requestUuid` value of the message it is responding to.\n\n3. **Agent Event Messages** ([`AgentEvent` schema](pathname:///schemas/2.2/api/agentEvent.schema.json)):\n    - Messages sent from the DA to the application that are due to actions in other applications, such as an inbound context resulting from another app's broadcast.\n    - Message names all end in 'Event'.\n    - Each instance of an Agent Response Message is uniquely identified by a `meta.eventUuid` field.\n\nEach individual message is also governed by a message schema, which is composed with the schema for the message type.\n\n:::info\n\nIn rare cases, the payload of a request or event message may quote the `requestUuid` or `eventUuid` of another message that it represents a response to, e.g. `intentResultRequest` quotes the `eventUuid` of the `intentEvent` that delivered the intent and context to the app, as well as the `requestUuid` of the `raiseIntentRequest` message that originally raised the intent.\n\n:::\n\nAll messages defined in the DACP follow a common structure:\n\n```json\n{\n    \"type\": \"string\", // string identifying the message type\n    \"payload\": {\n        //message payload fields defined for each message type \n    },\n    \"meta\": {\n        \"timestamp\": \"2024-09-17T10:15:39+00:00\"\n        //other meta fields determined by each 'class' of message\n        //  these include requestUuid, responseUuid and eventUuid\n        //  and a source field identifying an app where appropriate\n    }\n}\n```\n\n`meta.timestamp` fields are formatted as strings, according to the format defined by [ISO 8601-1:2019](https://www.iso.org/standard/70907.html), which is produced in JavaScript via the `Date` class's `toISOString()` function, e.g. `(new Date()).toISOString()`.\n\n### Routing, Registering Listeners & Multiplexing\n\nThe design of the Desktop Agent Communication Protocol is guided by the following sentence from the introduction to the Desktop Agent overview:\n\n> A Desktop Agent is a desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain.\n\nHence, that design is based on the assumption that all messaging between applications passes through an entity that acts as the 'Desktop Agent' and routes those messages on to the appropriate recipients (for example, a context message broadcast by an app to a channel is routed onto other apps that have added a listener to that channel, or an intent and context pair raised by an application is routed to another app chosen to resolve that intent). While implementations based on a shared bus are possible, they have not been specifically considered in the design of the DACP messages.\n\nFurther, the design of the DACP is based on the assumption that applications will interact with an implementation of the [`DesktopAgent`](../ref/DesktopAgent) interface, with the DACP used behind the scenes to support communication between the implementation of that interface and an entity acting as the Desktop Agent which is running in another process or location, necessitating the use of a 'wire protocol' for communication. For example, [Browser-Resident Desktop Agent](./browserResidentDesktopAgents) implementations use the [FDC3 Web Communication Protocol (WCP)](./webConnectionProtocol.md) to connect a 'Desktop Agent Proxy', provided by the `getAgent()` implementation in the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), and a Desktop Agent running in another frame or window which is communicated with via the DACP.\n\nAs a Desktop Agent is expected to act as a router for messages sent through the Desktop Agent API, the DACP provides message exchanges for the registration and un-registration of listeners for particular message types (e.g. events, contexts broadcast on user channels, contexts broadcast on other channel types, raised intents etc.). In most cases, apps can register multiple listeners for the same messages (often filtered for different context or event types). However, where multiple listeners are present, only a single DACP message should be sent representing the action taken in the FDC3 API (e.g. broadcasting a message to a channel) and any multiplexing to multiple listeners should be applied at the receiving end. For example, when working with the WCP, this should be handled by the Desktop Agent Proxy implementation provided by the `getAgent()` implementation.\n\n### Timeouts for Message Exchanges\n\nAs the DACP is used to communicate with a different browsing context, timeouts are applied to message exchanges allowing them to fail and for the Desktop Agent Proxy to return an error to the caller. A default timeout of 10 seconds is applied to all message exchanges, with the exception of those that may involve the launch of an application (`open()`, `raiseIntent()` and `raiseIntentForContext()`). Implementations of the FDC3 Desktop Agent API are required to allow a minimum timeout of 15 seconds for an application to launch and add any necessary context or intent listeners (see [Desktop Agent API Compliance](../spec#desktop-agent-api-standard-compliance) for further details). However, no upper bound for the timeout is currently specified. Message exchanges that involve the launch of an application use a default timeout of 100 seconds.\n\nDesktop Agents may specify custom values for both the default message exchange timeout and the timeout used for exchanges that may involve the launch of an application. Custom values are passed to the Desktop Agent proxy by setting the optional `payload.messageExchangeTimeout` and `payload.appLaunchTimeout` fields in the `WCP3Handshake` Response sent by the Desktop Agent to an application connecting to it. `payload.messageExchangeTimeout` MUST be set to a value greater than or equal to 100 ms, and `payload.appLaunchTimeout`  MUST be set to a value greater than or equal to 15,000 ms.\n\n```ts\n/** Default timeout used by a DesktopAgentProxy for all message exchanges\n * with a DesktopAgent, except those that involve the launch of an application.\n * May be overridden by a DesktopAgent by passing a value in the\n * payload.messageExchangeTimeout of a WCP3Handshake message.\n */\nexport const DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS = 10000;\n\n/** Default timeout used by a DesktopAgentProxy for message exchanges with a\n * DesktopAgent that involve launching applications. May be overridden by a \n * DesktopAgent by passing a value in the payload.appLaunchTimeout of a \n * WCP3Handshake message.\n * */\nexport const DEFAULT_APP_LAUNCH_TIMEOUT_MS = 100000;\n```\n\n:::info\n\nThe message exchange timeouts are used to detect a lack of response from the Desktop Agent, which will be reported via the `ApiTimeout` error message. However, there are also defined error messages for apps failing to add an expected context listener (`OpenError.AppTimeout`) or intent listener (`ResolveError.IntentDeliveryFailed`) after launch. To return these errors, the Desktop Agent should set a longer timeout via the `payload.appLaunchTimeout` field in its `WCP3Handshake` message than it uses internally to detect such failures. Doing so will ensure that timeouts can be separately attributed to the App or to the Desktop Agent.\n\n:::\n\n## Message Definitions Supporting FDC3 API calls\n\nThis section provides details of the messages defined in the DACP, grouped according to the FDC3 API functions that they support, and defined by JSON Schema files. Many of these message definitions make use of JSON versions of [metadata](../ref/Metadata) and other [types](../ref/Types) defined by the Desktop Agent API, the JSON versions of which can be found in [api.schema.json](pathname:///schemas/2.2/api/api.schema.json), while a number of DACP specific object definitions that are reused through the messages can be found in [common.schema.json](pathname:///schemas/2.2/api/common.schema.json).\n\n### `DesktopAgent`\n\n#### `addContextListener()`\n\nRequest and response used to implement the [`DesktopAgent.addContextListener()`](../ref/DesktopAgent#addcontextlistener) and [`Channel.addContextListener()`](../ref/Channel#addcontextlistener) API calls:\n\n- [`addContextListenerRequest`](pathname:///schemas/2.2/api/addContextListenerRequest.schema.json)\n- [`addContextListenerResponse`](pathname:///schemas/2.2/api/addContextListenerResponse.schema.json)\n\nEvent message used to deliver context objects that have been broadcast to listeners:\n\n- [`broadcastEvent`](pathname:///schemas/2.2/api/broadcastEvent.schema.json)\n\nRequest and response for removing the context listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`contextListenerUnsubscribeRequest`](pathname:///schemas/2.2/api/contextListenerUnsubscribeRequest.schema.json)\n- [`contextListenerUnsubscribeResponse`](pathname:///schemas/2.2/api/contextListenerUnsubscribeResponse.schema.json)\n\n#### `addEventListener()`\n\nRequest and response used to implement the [`addEventListener()`](../ref/DesktopAgent#addeventlistener) API call:\n\n- [`addEventListenerRequest`](pathname:///schemas/2.2/api/addEventListenerRequest.schema.json)\n- [`addEventListenerResponse`](pathname:///schemas/2.2/api/addEventListenerResponse.schema.json)\n\nEvent messages used to deliver events that have occurred:\n\n- [`channelChangedEvent`](pathname:///schemas/2.2/api/channelChangedEvent.schema.json)\n\nRequest and response for removing the event listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`eventListenerUnsubscribeRequest`](pathname:///schemas/2.2/api/eventListenerUnsubscribeRequest.schema.json)\n- [`eventListenerUnsubscribeResponse`](pathname:///schemas/2.2/api/eventListenerUnsubscribeResponse.schema.json)\n\n#### `addIntentListener()`\n\nRequest and response used to implement the [`addIntentListener()`](../ref/DesktopAgent#addintentlistener) API call:\n\n- [`addIntentListenerRequest`](pathname:///schemas/2.2/api/addIntentListenerRequest.schema.json)\n- [`addIntentListenerResponse`](pathname:///schemas/2.2/api/addIntentListenerResponse.schema.json)\n\nEvent message used to a raised intent and context object from another app to the listener:\n\n- [`intentEvent`](pathname:///schemas/2.2/api/intentEvent.schema.json)\n\nAn additional request and response used to deliver an [`IntentResult`](../ref/Types#intentresult) from the intent handler to the Desktop Agent, so that it can convey it back to the raising application:\n\n- [`intentResultRequest`](pathname:///schemas/2.2/api/intentResultRequest.schema.json)\n- [`intentResultResponse`](pathname:///schemas/2.2/api/intentResultResponse.schema.json)\n\nPlease note this exchange (and the `IntentResolution.getResult()` API call) support `void` results from a raised intent and hence this message exchange should occur for all raised intents, including those that do not return a result. In such cases, the void intent result allows resolution of the `IntentResolution.getResult()` API call and indicates that the intent handler has finished running.\n\nRequest and response for removing the intent listener ([`Listener.unsubscribe()`](../ref/Types#listener)):\n\n- [`intentListenerUnsubscribeRequest`](pathname:///schemas/2.2/api/intentListenerUnsubscribeRequest.schema.json)\n- [`intentListenerUnsubscribeResponse`](pathname:///schemas/2.2/api/intentListenerUnsubscribeResponse.schema.json)\n\nA typical exchange of messages between an app raising an intent, a Desktop agent and an app resolving an intent is:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\nThe above flow assumes that AppB has already been launched and added an intent listener. As apps can be launched to resolve an intent a typical message exchange (that includes registration of the intent listener) is:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    break intent resolution determines a new instance of AppB should be launched\n        DesktopAgent -->> AppB: Launch\n        AppB -->> DesktopAgent: Connect via WCP\n    end\n    AppB ->> DesktopAgent: addIntentListenerRequest\n    DesktopAgent ->> AppB: addIntentListenerResponse\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\n:::tip\n\nSee [`raiseIntent`](#raiseintent) below for further examples of message exchanges involved in raising intents and intent resolution.\n\n:::\n\n#### `broadcast()`\n\nRequest and response used to implement the [`DesktopAgent.broadcast()`](../ref/DesktopAgent#broadcast) and [`Channel.broadcast()`](../ref/Channel#broadcast) API calls:\n\n- [`broadcastRequest`](pathname:///schemas/2.2/api/broadcastRequest.schema.json)\n- [`broadcastResponse`](pathname:///schemas/2.2/api/broadcastResponse.schema.json)\n\nSee [`addContextListener()`](#addcontextlistener) above for the `broadcastEvent` used to deliver the broadcast to other apps.\n\n#### `createPrivateChannel()`\n\nRequest and response used to implement the [`createPrivateChannel()`](../ref/DesktopAgent#createprivatechannel) API call:\n\n- [`createPrivateChannelRequest`](pathname:///schemas/2.2/api/createPrivateChannelRequest.schema.json)\n- [`createPrivateChannelResponse`](pathname:///schemas/2.2/api/createPrivateChannelResponse.schema.json)\n\n#### `findInstances()`\n\nRequest and response used to implement the [`findInstances()`](../ref/DesktopAgent#findinstances) API call:\n\n- [`findInstancesRequest`](pathname:///schemas/2.2/api/findInstancesRequest.schema.json)\n- [`findInstancesResponse`](pathname:///schemas/2.2/api/findInstancesResponse.schema.json)\n\n#### `findIntent()`\n\nRequest and response used to implement the [`findIntent()`](../ref/DesktopAgent#findintent) API call:\n\n- [`findIntentRequest`](pathname:///schemas/2.2/api/findIntentRequest.schema.json)\n- [`findIntentResponse`](pathname:///schemas/2.2/api/findIntentResponse.schema.json)\n\n#### `findIntentsByContext()`\n\nRequest and response used to implement the [`findIntentsByContext()`](../ref/DesktopAgent#findintentsbycontext) API call:\n\n- [`findIntentsByContextRequest`](pathname:///schemas/2.2/api/findIntentsByContextRequest.schema.json)\n- [`findIntentsByContextResponse`](pathname:///schemas/2.2/api/findIntentsByContextResponse.schema.json)\n\n#### `getAppMetadata()`\n\nRequest and response used to implement the [`getAppMetadata()`](../ref/DesktopAgent#getappmetadata) API call:\n\n- [`getAppMetadataRequest`](pathname:///schemas/2.2/api/getAppMetadataRequest.schema.json)\n- [`getAppMetadataResponse`](pathname:///schemas/2.2/api/getAppMetadataResponse.schema.json)\n\n#### `getCurrentChannel()`\n\nRequest and response used to implement the [`getCurrentChannel()`](../ref/DesktopAgent#getcurrentchannel) API call:\n\n- [`getCurrentChannelRequest`](pathname:///schemas/2.2/api/getCurrentChannelRequest.schema.json)\n- [`getCurrentChannelResponse`](pathname:///schemas/2.2/api/getCurrentChannelResponse.schema.json)\n\n#### `getInfo()`\n\nRequest and response used to implement the [`getInfo()`](../ref/DesktopAgent#getinfo) API call:\n\n- [`getInfoRequest`](pathname:///schemas/2.2/api/getInfoRequest.schema.json)\n- [`getInfoResponse`](pathname:///schemas/2.2/api/getInfoResponse.schema.json)\n\n#### `getOrCreateChannel()`\n\nRequest and response used to implement the [`getOrCreateChannel()`](../ref/DesktopAgent#getorcreatechannel) API call:\n\n- [`getOrCreateChannelRequest`](pathname:///schemas/2.2/api/getOrCreateChannelRequest.schema.json)\n- [`getOrCreateChannelResponse`](pathname:///schemas/2.2/api/getOrCreateChannelResponse.schema.json)\n\n#### `getUserChannels()`\n\nRequest and response used to implement the [`getUserChannels()`](../ref/DesktopAgent#getuserchannels) API call:\n\n- [`getUserChannelsRequest`](pathname:///schemas/2.2/api/getUserChannelsRequest.schema.json)\n- [`getUserChannelsResponse`](pathname:///schemas/2.2/api/getUserChannelsResponse.schema.json)\n\n#### `joinUserChannel()`\n\nRequest and response used to implement the [`joinUserChannel()`](../ref/DesktopAgent#joinuserchannel) API call:\n\n- [`joinUserChannelRequest`](pathname:///schemas/2.2/api/joinUserChannelRequest.schema.json)\n- [`joinUserChannelResponse`](pathname:///schemas/2.2/api/joinUserChannelResponse.schema.json)\n\n#### `leaveCurrentChannel()`\n\nRequest and response used to implement the [`leaveCurrentChannel()`](../ref/DesktopAgent#leavecurrentchannel) API call:\n\n- [`leaveCurrentChannelRequest`](pathname:///schemas/2.2/api/leaveCurrentChannelRequest.schema.json)\n- [`leaveCurrentChannelResponse`](pathname:///schemas/2.2/api/leaveCurrentChannelResponse.schema.json)\n\n#### `open()`\n\nRequest and response used to implement the [`open()`](../ref/DesktopAgent#open) API call:\n\n- [`openRequest`](pathname:///schemas/2.2/api/openRequest.schema.json)\n- [`openResponse`](pathname:///schemas/2.2/api/openResponse.schema.json)\n\nWhere a context object is passed (e.g. `fdc3.open(app, context)`) the `broadcastEvent` message described above in [`addContextListener`](#addcontextlistener) should be used to deliver it after the context listener has been added:\n\n```mermaid\nsequenceDiagram\n    AppA ->> DesktopAgent: openRequest<br>(with context)\n    break Desktop Agent launches AppB\n        DesktopAgent -->> AppB: Launch\n        AppB -->> DesktopAgent: Connect via WCP\n    end\n    AppB ->> DesktopAgent: addContextListenerRequest\n    DesktopAgent ->> AppB: addContextListenerResponse\n    DesktopAgent ->> AppB: broadcastEvent\n    DesktopAgent ->> AppA: openResponse<br/>(with AppIdentifier)\n```\n\nHowever, if the app opened doesn't add a context listener within a timeout (defined by the Desktop Agent) then the `openResponse` should be sent with `AppTimeout` error from the [`OpenError`](../ref/Errors#openerror) enumeration.\n\n:::tip\n\nDesktop Agents MUST allow at least 15 seconds for an app to add a context listener before timing out (see [Desktop Agent API Standard Compliance](https://fdc3.finos.org/docs/next/api/spec#desktop-agent-api-standard-compliance) for more detail) and applications SHOULD add their listeners as soon as possible to keep the delay short (see the [addContextListener reference doc](https://fdc3.finos.org/docs/next/api/ref/DesktopAgent#addcontextlistener)).\n\n:::\n\n#### `raiseIntent()`\n\nRequest and response used to implement the [`raiseIntent()`](../ref/DesktopAgent#raiseintent) API call:\n\n- [`raiseIntentRequest`](pathname:///schemas/2.2/api/raiseIntentRequest.schema.json)\n- [`raiseIntentResponse`](pathname:///schemas/2.2/api/raiseIntentResponse.schema.json)\n\nAn additional response message is provided for the delivery of an `IntentResult` from the resolving application to the raising application (which is collected via the [`IntentResolution.getResult()`](../ref/Metadata#intentresolution) API call), which should quote the `requestUuid` from the original `raiseIntentRequest`:\n\n- [`raiseIntentResultResponse`](pathname:///schemas/2.2/api/raiseIntentResultResponse.schema.json)\n\nThere is no request message to indicate a call to the `resolution.getResult()` function of `IntentResolution`. Hence, Desktop Agents MUST send this additional response message to indicate the status of the intent handling function and to deliver its result (or void if none was returned).\n\n:::tip\n\nSee [`addIntentListener`](#addintentlistener) above for details of the messages used for the resolving app to deliver the result to the Desktop Agent.\n\n:::\n\nWhere there are multiple options for resolving a raised intent, there are two possible versions of the resulting message exchanges. Which to use depends on whether the Desktop Agent uses an intent resolver user interface (or other suitable mechanism) that it controls, or one injected into the application (for example an iframe injected by a `getAgent()` implementation into an application window) to perform resolution.\n\nWhen working with an injected interface, the Desktop Agent should respond with a `raiseIntentResponse` containing a `RaiseIntentNeedsResolutionResponsePayload`:\n\n```mermaid\n---\ntitle: Intent resolution with injected Intent Resolver iframe\n---\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    DesktopAgent ->> AppA: raiseIntentResponse\n    Note left of DesktopAgent: raiseIntentResponse includes a<br/> RaiseIntentNeedsResolutionResponsePayload<br/>containing an AppIntent\n    break when AppIntent return with multiple options\n        DesktopAgent --> AppA: getAgent displays IntentResolver\n        AppA --> DesktopAgent: User picks an option\n    end\n    AppA ->> DesktopAgent: raiseIntentRequest\n    Note left of DesktopAgent: New request includes a<br/>specific 'app' target<br/>and new requestUuid\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\nAlternatively, if the Desktop Agent is able to provide its own user interface or another suitable means of resolving the intent, then it may do so and respond with a `raiseIntentResponse` containing a `RaiseIntentSuccessResponsePayload`:\n\n```mermaid\n---\ntitle: Intent resolution with Desktop Agent provided Intent Resolver\n---\nsequenceDiagram\n    AppA ->> DesktopAgent: raiseIntentRequest\n    break DA determines there are multiple options\n        DesktopAgent-->AppA: Desktop Agent displays an<br/>IntentResolver UI\n        AppA-->DesktopAgent: User picks an option\n    end\n    DesktopAgent ->> AppB: intentEvent\n    DesktopAgent ->> AppA: raiseIntentResponse\n    Note left of DesktopAgent: DesktopAgent responds<br/>to the original<br/>raiseIntentRequest message with<br/>a RaiseIntentSuccessResponsePayload\n    AppB ->> DesktopAgent: intentResultRequest\n    DesktopAgent ->> AppB: intentResultResponse\n    DesktopAgent ->> AppA: raiseIntentResultResponse\n```\n\n#### `raiseIntentForContext()`\n\nRequest and response used to implement the [`raiseIntentForContext()`](../ref/DesktopAgent#raiseintentforcontext) API call:\n\n- [`raiseIntentForContextRequest`](pathname:///schemas/2.2/api/raiseIntentForContextRequest.schema.json)\n- [`raiseIntentForContextResponse`](pathname:///schemas/2.2/api/raiseIntentForContextResponse.schema.json)\n\nMessage exchanges for handling `raiseIntentForContext()` are the same as for `raiseIntent`, except for the substitution of `raiseIntentForContextRequest` for `raiseIntentRequest` and `raiseIntentForContextResponse` for `raiseIntentResponse`. Hence, please see [`raiseIntent`](#raiseintent) and [`addIntentListener`](#addintentlistener) for further details.\n\n### `Channel`\n\nOwing to the significant overlap between the FDC3 [`DesktopAgent`](../ref/DesktopAgent) and [`Channel`](../ref/Channel) interfaces, which includes the ability to retrieve and work with User channels as App Channels, most of the messaging for the `Channel` API is shared with `DesktopAgent`. Specifically, all messages defined in the the [`broadcast`](#broadcast) and [`addContextListener`](#addcontextlistener) sections above are reused, with a few minor differences to note:\n\n- When working with a specific channel, the `channelId` property in `addContextListenerRequest` should be set to the ID of the channel, where it is set to `null` to work with the current user channel.\n- When receiving a `broadcastEvent` a `channelId` that is `null` indicates that the context was sent via a call to `fdc3.open` and does not relate to a channel.\n\nThe following additional function is unique to the `Channel` interface:\n\n#### `getCurrentContext()`\n\nRequest and response used to implement the [`Channel.getCurrentContext()`](../ref/Channel#getcurrentcontext) API call:\n\n- [`getCurrentContextRequest`](pathname:///schemas/2.2/api/getCurrentContextRequest.schema.json)\n- [`getCurrentContextResponse`](pathname:///schemas/2.2/api/getCurrentContextResponse.schema.json)\n\n### `PrivateChannel`\n\nThe [`PrivateChannel`](../ref/PrivateChannel) interface extends [`Channel`](../ref/Channel) with a number of additional functions that are supported by the following messages:\n\n#### `addEventListener()`\n\nRequest and response used to implement the [`PrivateChannel.addEventListener`](../ref/PrivateChannel#addeventlistener) API call:\n\n- [`privateChanneladdEventListenerRequest`](pathname:///schemas/2.2/api/privateChanneladdEventListenerRequest.schema.json)\n- [`privateChanneladdEventListenerResponse`](pathname:///schemas/2.2/api/privateChanneladdEventListenerResponse.schema.json)\n\nEvent messages used to deliver events that have occurred:\n\n- [`privateChannelOnAddContextListenerEvent`](pathname:///schemas/2.2/api/privateChannelOnAddContextListenerEvent.schema.json)\n- [`privateChannelOnDisconnectEvent`](pathname:///schemas/2.2/api/privateChannelOnDisconnectEvent.schema.json)\n- [`privateChannelOnUnsubscribeEvent`](pathname:///schemas/2.2/api/privateChannelOnUnsubscribeEvent.schema.json)\n\n:::tip\n\nThe above messages may also be used to implement the deprecated [`onAddContextListener()`](../ref/PrivateChannel#onaddcontextlistener), [`onUnsubscribe`](../ref/PrivateChannel#onunsubscribe) and [`onDisconnect`](../ref/PrivateChannel#ondisconnect) functions of the `PrivateChannel` interface.\n\n:::\n\nMessage exchange for removing the event listener [`Listener.unsubscribe`](../ref/Types#listener):\n\n- [`privateChannelUnsubscribeEventListenerRequest`](pathname:///schemas/2.2/api/privateChannelUnsubscribeEventListenerRequest.schema.json)\n- [`privateChannelUnsubscribeEventListenerResponse`](pathname:///schemas/2.2/api/privateChannelUnsubscribeEventListenerResponse.schema.json)\n\n#### `disconnect()`\n\nRequest and response used to implement the [`PrivateChannel.disconnect()`](../ref/PrivateChannel#disconnect) API call:\n\n- [`privateChannelDisconnectRequest`](pathname:///schemas/2.2/api/privateChannelDisconnectRequest.schema.json)\n- [`privateChannelDisconnectResponse`](pathname:///schemas/2.2/api/privateChannelDisconnectResponse.schema.json)\n\n### Checking apps are alive\n\nDepending on the connection over which the Desktop Agent and app are connected, it may be necessary for the Desktop Agent to check whether the application is still alive. This can be done, either periodically or on demand (for example to validate options that will be provided in an [`AppIntent`](../ref/Metadata#appintent) as part of a `findIntentResponse` or `raiseIntentResponse` and displayed in an intent resolver interface), using the following message exchange:\n\n- [`heartbeatEvent`](pathname:///schemas/2.2/api/heartbeatEvent.schema.json)\n- [`heartbeatAcknowledgment`](pathname:///schemas/2.2/api/heartbeatAcknowledgment.schema.json)\n\nAs a Desktop Agent initiated exchange, it is initiated with an `AgentEvent` message and completed via an `AppRequest` message as an acknowledgement.\n\n:::tip\n\nAdditional procedures are defined in the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents#disconnects) and [Web Connection Protocol](./webConnectionProtocol#step-5-disconnection) for the detection of app disconnection or closure. Implementations will often need to make use of multiple procedures to catch all forms of disconnection in a web browser.\n\n:::\n\n### Controlling Injected User Interfaces\n\nDesktop Agent implementations, such as those based on the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents) and [Web Connection Protocol](./webConnectionProtocol), may either provide their own user interfaces (or other appropriate mechanisms) for the selection of User Channels or Intent Resolution, or they may work with implementations injected into the application (for example, as described in the [Web Connection Protocol](./webConnectionProtocol#providing-channel-selector-and-intent-resolver-uis) and implemented in [`getAgent()`](../ref/GetAgent)).\n\nWhere injected user interfaces are used, standardized messaging is needed to communicate with those interfaces. This is provided in the DACP via the following 'iframe' messages, which are governed by the [`Fdc3UserInterfaceMessage`](pathname:///schemas/2.2/api/fdc3UserInterface.schema.json) schema. The following messages are provided:\n\n- [`Fdc3UserInterfaceHello`](pathname:///schemas/2.2/api/fdc3UserInterfaceHello.schema.json): Sent by the iframe to its `window.parent` frame to initiate communication and to provide initial CSS to apply to the frame. This message should have a `MessagePort` appended over which further communication will be conducted.\n- [`Fdc3UserInterfaceHandshake`](pathname:///schemas/2.2/api/fdc3UserInterfaceHandshake.schema.json):  Response to the `Fdc3UserInterfaceHello` message sent by the application frame, which should be sent over the `MessagePort`. Includes details of the FDC3 version that the application is using.\n- [`Fdc3UserInterfaceDrag`](pathname:///schemas/2.2/api/fdc3UserInterfaceDrag.schema.json): Message sent by the iframe to indicate that it is being dragged to a new position and including offsets to indicate direction and distance.\n- [`Fdc3UserInterfaceRestyle`](pathname:///schemas/2.2/api/fdc3UserInterfaceRestyle.schema.json): Message sent by the iframe to indicate that its frame should have updated CSS applied to it, for example to support a channel selector interface that can be 'popped open' or an intent resolver that wishes to resize itself to show additional content.\n\nMessages are also provided that are specific to each user interface type provided by a Desktop Agent. The following messages are specific to Channel Selector user interfaces:\n\n- [`Fdc3UserInterfaceChannels`](pathname:///schemas/2.2/api/fdc3UserInterfaceChannels.schema.json): Sent by the parent frame to initialize a Channel Selector user interface by providing metadata for the Desktop Agent's user channels and details of any channel that is already selected. This message will typically be sent by a `getAgent()` implementation immediately after the `fdc3UserInterfaceHandshake` and before making the injected iframe visible.\n- [`Fdc3UserInterfaceChannelSelected`](pathname:///schemas/2.2/api/fdc3UserInterfaceChannelSelected.schema.json): Sent by the Channel Selector to indicate that a channel has been selected or deselected.\n\nMessages specific to Intent Resolver user interfaces:\n\n- [`Fdc3UserInterfaceResolve`](pathname:///schemas/2.2/api/fdc3UserInterfaceResolve.schema.json): Sent by the parent frame to initialize an Intent Resolver user interface to resolve a raised intent, before making the iframe visible. The message includes the context object sent with the intent and an array of one or more [`AppIntent`](../ref/Metadata#appintent) objects representing the resolution options for the intent ([`raiseIntent`](../ref/DesktopAgent#raiseintent)) or context ([`raiseIntentForContext`](../ref/DesktopAgent#raiseintentforcontext)) that was raised.\n- [`Fdc3UserInterfaceResolveAction`](pathname:///schemas/2.2/api/fdc3UserInterfaceResolveAction.schema.json): Sent by the Intent Resolver to indicate actions taken by the user in the interface, including hovering over an option, clicking a cancel button, or selecting a resolution option. The Intent Resolver should be hidden by the `getAgent()` implementation after a resolution option is selected to ensure that it does not interfere with user's ongoing interaction with the app's user interface.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/specs/preloadDesktopAgents.md",
    "content": "---\nid: preloadDesktopAgents\nsidebar_label: Preload Desktop Agents\ntitle: Preload Desktop Agents (2.2)\n---\n\n\nA Preload Desktop Agent is an FDC3 Desktop Agent (DA) supporting web applications that 'inject' or 'preload' scripts into web windows which provide access to an FDC3 Desktop Agent API implementation. This document specifies the required behavior for a Preload Desktop Agent (DA).\n\n:::info\n\n> The [getAgent() specification in the FDC3 Web Connection Protocol](webConnectionProtocol.md) relies on Preload DAs behaving as specified in this document.\n\n:::\n\n## Injecting the global FDC3 object\n\nSince FDC3 is typically available to the whole web application, Desktop Agents are expected to make the [`DesktopAgent`](../ref/DesktopAgent) interface available at a global level. Hence, a Preload Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means.\n\nThe global `window.fdc3` MUST only be available after the API is ready to use. Implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use.\n\nHowever, implementors SHOULD also ensure that the global is made available as soon as possible after the window is created to ensure that it can be detected by `getAgent()`. Queuing of requests to the API MAY be used to make the API available, while initialization is underway.\n\n:::note\n\nPrior to FDC3 2.2, apps were advised to check for the existence of the FDC3 API at `window.fdc3` and then add a listener for the `fdc3Ready` event if it was not found. This has since been superseded by the recommendation to use `getAgent()`, which handles those steps internally, alongside supporting FDC3 in web browsers ( via the [Browser Resident Desktop Agent spec](./browserResidentDesktopAgents)).\n\n:::\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/specs/webConnectionProtocol.md",
    "content": "---\nid: webConnectionProtocol\nsidebar_label: Web Connection Protocol\ntitle: Web Connection Protocol (2.2)\n---\n\n:::info _[@experimental](../../fdc3-compliance#experimental-features)_\n\nFDC3's Web Connection Protocol (WCP) is an experimental feature added to FDC3 in 2.2. Limited aspects of its design may change in future versions and it is exempted from the FDC3 Standard's normal versioning and deprecation polices in order to facilitate any necessary change.\n\n:::\n\nThe FDC3 Web Connection Protocol (WCP) defines the procedure for a web-application to connect to an FDC3 Desktop Agent. The WCP is used to implement a [`getAgent()`](../ref/GetAgent) function in the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), which is the recommended way for web applications to connect to a Desktop Agent. This specification details how it retrieves and provides the FDC3 [`DesktopAgent`](../ref/DesktopAgent) interface object and requirements that Desktop Agents MUST implement in order to support discovery and connection via `getAgent()`. Please see the [`getAgent` reference document](../ref/GetAgent.md) for its TypeScript definition and related types.\n\n:::tip\n\nThe [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3) provides a `getAgent()` implementation which app can use to connect to a Desktop Agent without having to interact with or understand the WCP directly. See [Supported Platforms](../supported-platforms) and the [`getAgent()`](../ref/GetAgent) reference page for more details on using `getAgent()` in an application.\n\n:::\n\nThe WCP supports both interfaces to web-based Desktop Agents defined in the FDC3 Standard:\n\n- **Desktop Agent Preload**: An 'injected' or 'preloaded' Desktop Agent API implementation, typically provided by an [Electron](https://www.electronjs.org/) (or similar) container or browser extension, which is made available to web applications at `window.fdc3`.\n- **Desktop Agent Proxy**: An interface to a web-based Desktop Agent (implementation of the Desktop Agent API) that uses the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) to communicate with a Desktop Agent implementation running in another frame or window, via the HTML Standard's Channel Messaging API ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API), [HTML Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html)).\n\nThe WCP allows FDC3-enabled applications to detect which FDC3 web-interface is present at runtime and returns a `DesktopAgent` interface implementation that the application can use to communicate, without the import of proprietary libraries or code. Hence, the WCP enables FDC3-enabled applications to be run within the scope of any standards compliant Desktop Agent without modification, enabling their developers to Write Once Run Anywhere (WORA).\n\n:::tip\n\nSee the FDC3 [Glossary](../../fdc3-glossary) and [References](../../references.md) pages for definitions of terms and links to external APIs used throughout this document.\n\n:::\n\n:::tip\n\nFurther details for implementing Preload Desktop Agents (which use a Desktop Agent Preload interface) or a Browser Resident Desktop Agent (which use a Desktop Agent Proxy interface) are available in the [Preload Desktop Agent](./preloadDesktopAgents) or [Browser Resident Desktop Agent Specification](./browserResidentDesktopAgents), respectively.\n\n:::\n\n## WCP Message Schemas\n\nThere are a number of messages defined as part of the Web Connection Protocol. Definitions are provided in [JSON Schema](https://json-schema.org/) in the [FDC3 github repository](https://github.com/finos/FDC3/tree/fdc3-for-web/schemas/api).\n\n:::tip\n\nTypeScript types representing all DACP and WCP messages are generated from the JSON Schema source and can be imported from the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3):\n\n```ts\nimport { BrowserTypes } from \"@finos/fdc3\";\n```\n\n:::\n\nWCP messages are derived from a base schema, [`WCPConnectionStep`](pathname:///schemas/2.2/api/.schema.json), which defines a common structure for the messages:\n\n```json\n{\n    \"type\": \"string\", // string identifying the message type\n    \"payload\": {\n        //message payload fields defined for each message type \n    },\n    \"meta\": {\n        \"connectionAttemptUuid\": \"79be3ff9-7c05-4371-842a-cf08427c174d\",\n        \"timestamp\": \"2024-09-17T10:15:39+00:00\"\n    }\n}\n```\n\nA value for `meta.connectionAttemptUuid` should be generated as a version 4 UUID according to [IETF RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) at the start for the connection process and quoted in all subsequent messages, as described later in this document.\n\n`meta.timestamp` fields are formatted as strings, according to the format defined by [ISO 8601-1:2019](https://www.iso.org/standard/70907.html), which is produced in JavaScript via the `Date` class's `toISOString()` function, e.g. `(new Date()).toISOString()`.\n\nMessages defined as part of the Web Connection Protocol, which will be referenced later in this document, these are:\n\n- [`WCP1Hello`](pathname:///schemas/2.2/api/WCP1Hello.schema.json)\n- [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json)\n- [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json)\n- [`WCP4ValidateAppIdentity`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json)\n- [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityFailedResponse.schema.json)\n- [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json)\n- [`WCP6Goodbye`](pathname:///schemas/2.2/api/WCP6Goodbye.schema.json)\n\n## Establishing Connectivity Using the Web Connection Protocol (WCP)\n\nThe WCP algorithm (coordinated between the `getAgent()` implementation and Desktop Agent implementations) has four steps, followed by an optional disconnection step. Each step may contain sub-steps.\n\n1. Locate a Desktop Agent interface\n2. Validate app & instance identity\n3. Persist connection details to SessionStorage\n4. Return Desktop Agent interface\n5. Disconnect\n\n### Step 1: Locate a Desktop Agent interface\n\n#### 1.1 Check for a possible navigation or refresh event\n\nCheck the SessionStorage key `FDC3-Desktop-Agent-Details` for a `DesktopAgentDetails` record. If it exists, then a navigation or refresh event may have occurred and the stored data MUST be sent when attempting to establish a connection to the DA. This ensures that the window can maintain a consistent `instanceId` between navigation or refresh events within an app. If it doesn't exist then proceed to step (2).\n\nAny data stored under the `FDC3-Desktop-Agent-Details` MUST conform to the [DesktopAgentDetails](../ref/GetAgent#persisted-connection-data) type.\n\nExisting `DesktopAgentDetails` records MUST be used to limit discovery actions (in the next step) to the same mechanism as previously used or to skip the discovery step entirely if an `agentUrl` exists, indicating that the connection should be established by loading the URL into a hidden iframe and initiating communication with that instead.\n\nIf use of the persisted data fails to establish a connection to the DA then `getAgent()` should reject its promise with `AgentNotFound` error from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\n#### 1.2 Desktop Agent Discovery\n\nNext, attempt to discover whether Desktop Agent Preload or Desktop Agent Proxy interfaces are available, within a specified timeout. The optional `params.timeoutMs` argument to `getAgent()` allows an application to specify the timeout that should be used, with a default value of 750ms. Discovery of Desktop Agent Preload or Desktop Agent Proxy interfaces should be conducted in parallel where possible and the timeout cancelled as soon as an interface is discovered. If a `DesktopAgentDetails` record was found in the previous step, limit discovery to the interface specified, or, if an `agentUrl` property was specified in the `DesktopAgentDetails` record, skip the discovery step entirely and proceed to the next step.\n\nTo discover a Desktop Agent Preload interface, check for the presence of an `fdc3` object in the global scope (i.e. `window.fdc3`). If it exists return it immediately. If it does not exist then add a listener for the global `fdc3Ready` event with the the specified timeout, e.g.:\n\n```ts\nconst discoverPreloadDA = async (timeoutMs: number): Promise<DesktopAgent> => {\n  return new Promise((resolve, reject) => {\n    // if the global is already available resolve immediately\n    if (window.fdc3) {\n      resolve(window.fdc3);\n    } else {\n      // Setup a timeout to return a rejected promise\n      const timeoutId = setTimeout(\n        () => {\n          //clear the event listener to ignore a late event\n          window.removeEventListener(\"fdc3Ready\", listener);\n          if (window.fdc3){ \n            resolve(window.fdc3);\n          } else {\n            reject(\"Desktop Agent Preload not found!\");\n          }\n        }, \n        timeoutMs\n      );\n      //`fdc3Ready` event listener function\n      const listener = () => {\n        clearTimeout(timeoutId);\n        if (window.fdc3) {\n          resolve(window.fdc3);\n        } else {\n          reject(\"The `fdc3Ready` event fired, but `window.fdc3` Was not set!\");\n        }\n      };\n      \n      // listen for the fdc3Ready event\n      window.addEventListener(\"fdc3Ready\", listener, { once: true });\n    }\n  });\n};\n```\n\nTo discover a Desktop Agent Proxy interface, locate all candidates for a `parent` window or frame by first checking the values of `window.opener` and `window.parent`. If `window.opener !== null` or `window.parent !== window` then they are candidates for a parent window or frame. As iframes can be nested we can also search for candidates that are parents of a parent frame, e.g.:\n\n```ts\n/**\n * Recursive search for all possible parent frames (windows) that we may\n * target with the WCP.\n * @param startWindow window object to search\n * @param found window objects found so far\n * @return An array of Window Objects representing 'parent' frames of the\n * specified window.\n */\nfunction discoverProxyCandidates(startWindow: Window, found: Window[]) {\n  _recursePossibleTargets(startWindow, startWindow, found);\n  Logger.debug(`Possible parent windows/frames found: ${found.length}`);\n  return found;\n}\n\nfunction _recursePossibleTargets(startWindow: Window, w: Window, found: Window[]) {\n  if (w) {\n    if (found.indexOf(w) == -1 && w != startWindow) {\n      found.push(w);\n    }\n\n    if (!!w.opener) {\n      _recursePossibleTargets(startWindow, w.opener, found);\n    }\n\n    if (w.parent != w) {\n      _recursePossibleTargets(startWindow, w.parent, found);\n    }\n  }\n}\n```\n\nSetup a timer for specified timeout, and then for each `candidate` found, attempt to establish communication with it as follows:\n\n  1. Add a listener (`candidate.addEventListener(\"message\", (event) => {})`) to receive response messages from the `candidate`.\n  2. Send a [`WCP1Hello`](pathname:///schemas/2.2/api/WCP1Hello.schema.json) message to it via `postMessage`.\n\n  ```ts\n  const hello = {\n    type: \"WCP1Hello\",\n    payload: {\n      identityUrl: identityUrl,\n      actualUrl: actualUrl,\n      fdc3Version: \"2.2\",\n      intentResolver: true,\n      channelSelector: true\n    },\n    meta: {\n      connectionAttemptUuid: \"bc96f1db-9b2b-465f-aab3-3870dc07b072\",\n      timestamp: \"2024-09-09T11:44:39+00:00\"\n    }\n  };\n  candidate.postMessage(hello, { targetOrigin: \"*\" });\n  ```\n\n  Note that the `targetOrigin` is set to `*` as the origin of the Desktop Agent is not known at this point.\n  3. Accept the first correct response received from a candidate. Correct responses MUST correspond to either the [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json) or [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json) message schemas and MUST quote the same `meta.connectionAttemptUuid` value provided in the original `WCP1Hello` message. Stop the timeout when a correct response is received. If no response is received from any candidate, the `getAgent()` implementation MAY retry sending the `WCP1Hello` message periodically until the timeout is reached.\n  4. If a [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json) was received in the previous step, skip this step and move on to step 5. However, If a [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json) was received in the previous step:\n      - Create a hidden iframe within the page, set its URL to the URL provided by the `payload.iframeUrl` field of the message and add a handler to run when the iframe has loaded:\n          ```ts\n          const loadIframe = (url: string, loadedHandler: () => void): WindowProxy => {\n            const ifrm = document.createElement(\"iframe\");\n            iframe.onload = loadedHandler;\n            ifrm.src = url;\n            ifrm.style.width = \"0\";\n            ifrm.style.height = \"0\";\n            ifrm.style.visibility = \"0\";\n            ifrm.ariaHidden = \"true\";\n            document.body.appendChild(ifrm);\n            return ifrm.contentWindow;\n          };\n          ```\n      - Once the frame has loaded (i.e. when the `loadedHandler` in the above example runs), repeat steps 1-3 above substituting the  iframe's `contentWindow` for the candidate window objects before proceeding to step 5. A new timeout should be used to limit the amount of time that the `getAgent()` implementation waits for a response. If the event that this subsequent timeout is exceeded, reject Error with the `ErrorOnConnect` message from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\n        :::tip\n\n        To ensure that the iframe is ready to receive the `WCP1Hello` message when the `load` event fires, implementations should call `window.addEventListener` for the `message` event synchronously and as early as possible.\n\n        :::\n\n  5. At this stage, a [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json) message should have been received from either a candidate parent or a hidden iframe created in step 4 above. This message MUST have a `MessagePort` appended to it, which is used for further communication with the Desktop Agent. It MUST also contain URLs for any Intent Resolver or Channel Selector UIs to be injected into the page (or `false` to indicate that they are not in use) and MAY contain custom timeout settings to use for API message exchanges.\n\n  Add a listener (`port.addEventListener(\"message\", (event) => {})`) to receive messages from the selected `candidate`, before moving on to the next stage.\n  6. If no candidates were found or no [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json) has been received by the time that the timeout expires, then neither a Desktop Agent Preload or Desktop Agent Proxy interface has been discovered. If this occurs, the `getAgent()` implementation will run any `failover` function provided as a parameter to `getAgent()`, allowing the application to provide an alternative means of connecting to or starting up a Desktop Agent.\n  \n  An async failover function may resolve to either a `DesktopAgent` implementation or the application may create either an iframe or open a new window, load an appropriate URL for a Desktop Agent implementation and resolve to its `WindowProxy` reference (e.g. `iframe.contentWindow` or the result of a call to `window.open(...)`).\n  \n  If the failover function resolves to a `DesktopAgent` implementation it should be immediately returned in the same way as a `window.fdc3` reference was and handled as if it represents a Desktop Agent Preload interface.\n\n  If the failover function resolves to a `WindowProxy` object, repeat steps 1-3 & 5 above substituting the `WindowProxy` for the candidate window objects before proceeding to the next step.\n\n  :::tip\n\n  Where possible, iframe failover functions should wait for the iframe or window represented by a `WindowProxy` object to be ready to receive messages before resolving. For an iframe this is a case of waiting for the `load` event to fire.\n\n  :::\n\n### Step 2: Validate app & instance identity\n\nApps and instances of them identify themselves so that DAs can positively associate them with their corresponding AppD records and any existing instance identity.\n\nIn the current FDC3 version, no identity validation procedures are provided for Desktop Agent Preload interfaces. Hence, it is the responsibility of such implementations to validate the identity of apps within their scope and to ensure that they update their own record of the identity if it changes during the life of the window hosting the application (i.e. due to a navigation event). It is expected that FDC3 will adopt identity validation procedures for Desktop Agent Preload interfaces in future.\n\n#### 2.1 Determine App Identity\n\nIn Desktop Agent Proxy interfaces, identity is ascertained via the [`WCP4ValidateAppIdentity`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message, which should be the first message sent on the `MessagePort` received by the `getAgent()` implementation after receiving it via [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json). Any other messages sent via the `MessagePort` prior to successful validation of a [`WCP4ValidateAppIdentity`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message should be ignored.\n\nAn app identity is determined and an `appId` assigned by matching the application to an AppD record already known to the Desktop Agent, based on the `identityUrl` provided in the [`WCP4ValidateAppIdentity`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message. An additional `actualUrl` field MUST also be provided to indicate whether the app overrode its `identityUrl` and to allow for logging. The origin (protocol, domain and port) of the `identityUrl`, `actualUrl` and the `MessageEvent.origin` field of the original `WCP1Hello` message that started the connection flow MUST all match. See the [Browser-Resident Desktop Agent Specification](./browserResidentDesktopAgents#validating-app-identity) for details of how to match an `identityUrl` to the `details.url` field of an AppD record.\n\nIf the app identity is not recognized, the Desktop Agent MUST respond with a [`WCP5ValidateAppIdentityFailedResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityFailedResponse.schema.json) message and stop handling further messages on the `MessagePort`. On receiving this message, the `getAgent()` implementation should reject with an Error object with the `AccessDenied` message from the [`AgentError`](../ref/Errors#agenterror) enumeration.\n\nIf the app identity is recognized the Desktop Agent will assign the appropriate appId and move on to determining the instance identity.\n\n#### 2.2 Determine Instance Identity\n\nIf this instance of the application has connected to a Desktop Agent before and is reconnecting (due to a navigation or refresh event) then the optional `instanceId` and `instanceUuid` should be set in the [`WCP4ValidateAppIdentity`](pathname:///schemas/2.2/api/WCP4ValidateAppIdentity.schema.json) message. The Desktop Agent MUST use these values to determine if it recognizes the app instance identity and that it was previously applied to application with the same `appId`.\n\nAn `instanceUuid` is used to validate instance identity because `instanceId` of an application is available to other apps through the FDC3 API and might be used to 'spoof' an identity. On the other hand, `instanceUuid` is only issued through the WCP to the specific app instance and is used as a shared secret to enable identity validation. However, as `SessionStorage` data may be cloned when new windows on the same origin are opened via `window.open()`, Desktop Agents MUST also compare the `WindowProxy` object (via the `==` operator) that the original `WCP1Hello` messages were received on to determine if they represent the same window.\n\nSee the [Browser-Resident Desktop Agent Specification](./browserResidentDesktopAgents#validating-instance-identity) for further details of how instance identity is assigned.\n\nIf no existing instance identity (`instanceId` and `instanceUuid`) is provided, or instance identity validation fails (as the `instanceUuid` is not known, or either the `appId` or `WindowProxy` objects don't match the previous connection), then the Desktop Agent MUST assign new `instanceId` and `instanceUuid` values.\n\nThe Desktop Agent MUST then respond with a [`WCP5ValidateAppIdentityResponse`](pathname:///schemas/2.2/api/WCP5ValidateAppIdentityResponse.schema.json) message containing the assigned `appId`, `instanceId` and `instanceUuid` values and the [`ImplementationMetadata`](../ref/Metadata#implementationmetadata) object for the Desktop Agent. This message indicates that the Desktop Agent will accept the application and we can begin processing [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) messages relating to FDC3 API calls over the `MessagePort`.\n\n### Step 3: Persist DesktopAgentDetails to SessionStorage\n\nOnce a connection is established, and the app and instance identity determined, a `DesktopAgentDetails` record MUST be stored in SessionStorage under the `FDC3-Desktop-Agent-Details` key by the `getAgent()` implementation. This record includes:\n\n- The `identityUrl` and `actualUrl` passed to `getAgent()`.\n- The `appId`, `instanceId`, and `instanceUuid` assigned by the DA.\n- An `agentUrl` field with the URL provided in any [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json) message that was received\n  - Used to skip sub-steps 1-3 in the discovery process described in Step 1.2.\n  - If no [`WCP2LoadUrl`](pathname:///schemas/2.2/api/WCP2LoadUrl.schema.json) message was received, omit this field.\n- An `agentType` field which indicates what type of connection to the DA was established\n  - Used to limit the discovery process in Step 1.2 above to only allow agents of the same type.\n  - the `getAgent()` implementation should determine what value to set, from the `WebDesktopAgentType` enumeration for this field based on what happened during the discovery process.\n\nSee the [reference documentation for getAgent()](../ref/GetAgent#persisted-connection-data) for further details of the `DesktopAgentDetails` record that should be saved to SessionStorage.\n\n:::tip\n\nSessionStorage is ephemeral, only existing for the duration of the window's life. Hence, there is no concern with the key being overwritten or conflicting with other DAs.\n\n:::\n\n### Step 4: Resolve promise with DesktopAgent interface (step 4)\n\nResolve the `getAgent()` promise with an object containing either a `DesktopAgent` implementation (that was found at `window.fdc3` or returned by a `failover` function) or a 'Desktop Agent Proxy' implementation (a class implementing the `DesktopAgent` interface that uses the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol) to communicate with a Desktop Agent over the `MessagePort`).\n\nWhere a `DesktopAgent` or 'Desktop Agent Proxy' implementation was successfully returned, any subsequent calls to `getAgent()` that are not preceded by a navigation or refresh event, should resolve to the same instance.\n\n### Step 5: Disconnection\n\nDesktop Agent Preload interfaces, as used in container-based Desktop Agent implementations, are usually able to track the lifecycle and current URL of windows that host web apps in their scope. Hence, there is currently no requirement nor means for an app to indicate that it is closing, rather it is the responsibility of the Desktop Agent to update its internal state when an app closes or changes identity.\n\nHowever, Browser Resident Desktop Agents working with a Desktop Agent Proxy interface may have more trouble tracking child windows and frames. Hence, a specific WCP message ([`WCP6Goodbye`](pathname:///schemas/2.2/api/WCP6Goodbye.schema.json)) is provided for the `getAgent()` implementation to indicate that an app is disconnecting from the Desktop Agent and will not communicate further unless and until it reconnects via the WCP. The `getAgent()` implementation MUST listen for the `pagehide` event from the HTML Standard's [Page Life Cycle API](https://html.spec.whatwg.org/multipage/document-lifecycle.html#document-lifecycle) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event), [Chrome for Developers](https://developer.chrome.com/docs/web-platform/page-lifecycle-api#developer-recommendations-for-each-state)) and send [`WCP6Goodbye`](pathname:///schemas/2.2/api/WCP6Goodbye.schema.json) if it receives an event where the `persisted` property is `false`.\n\nAs it is possible for a page to close without firing this event in some circumstances (e.g. where a browser render thread crashes), other procedures for detecting disconnection may also be used, these are described in the [Browser Resident Desktop Agents specification](./browserResidentDesktopAgents#disconnects) and [Desktop Agent Communication Protocol](./desktopAgentCommunicationProtocol#checking-apps-are-alive).\n\n### `getAgent()` Workflow Diagram\n\nThe workflow defined in the Web Connection protocol for `getAgent()` is summarized in the below diagram:\n\n```mermaid\n---\ntitle: \"Web Connection Protocol Flowchart\" \n---\nflowchart TB\n    A1([DesktopAgent launches app]) --> A2[\"App calls getAgent()\"]\n    A2 --> A3\n\n    subgraph getAgent [\"getAgent()\"]\n      A3[\"Check for DesktopAgentDetails in SessionStorage\"] --> P1{\"Does window.fdc3 exist?\"}\n      P1 -->|yes|P2[\"Stop timeout\"]\n      P2 --> P21[\"Save DesktopAgentDetails to SessionStorage\"]\n      P1 -->|No|P3[\"Listen for fdc3Ready\"]\n      P3 --> P31[\"fdc3Ready event fires\"]\n      P31 --> P32[\"Stop timeout\"]\n      P32 --> P33[\"Save DesktopAgentDetails to SessionStorage\"]\n      \n      A3 --> B1{\"Do parent refs exist?\"}\n      B1 -->|yes|B11[\"Send WCP1Hello to all candidates\"]\n      B11 --> B2[\"Receive WCP2LoadUrl\"]\n      B2 --> B21[\"Stop timeout\"]\n      B21 --> B22[\"Create hidden iframe with URL\"]\n      B22 --> B23[\"Await iframe's load event\"]\n      B23 --> B24[\"Send WCP1Hello to iframe\"]\n      B24 --> B3[\"Receive WCP3Handshake with MessagePort\"]\n      B3 --> B31[\"Stop timeout\"]\n      B11 --> B3\n      B31 --> B32[\"Send WCP4ValidateIdentity on MessagePort\"]\n      B32 --> B321[\"Receive WCP5ValidateIdentityResponse\"]\n      B321 --> B3211[\"Create DesktopAgentProxy to process DACP messages\"]\n      B3211 --> B3212[\"Save DesktopAgentDetails to SessionStorage\"]\n      B32 --> B322[\"Receive WCP5ValidateIdentityFailedResponse\"]\n      \n      A3 --> T1[\"Set timeout\"]\n      T1 --> T2[\"Timeout expires\"]\n      T2 --> T3{\"Was a failover fn provided\"}\n      T3 -->|yes|T31[\"Run failover\"]\n      T31 --> T311{\"Check failover return type\"}\n      T311 -->|WindowProxy|T3111[\"Send WCP1Hello via WindowProxy\"]\n      T311 -->|DesktopAgent|T3112[\"Save DesktopAgentDetails to SessionStorage\"]\n      T3111 --> B3\n    end\n    P21 -->P22([\"Resolve with window.fdc3\"])\n    P33 -->P34([\"Resolve with window.fdc3\"])\n    B3212 --> B3213([\"Resolve with DesktopAgentProxy\"])\n    B322 --> B3221([\"Reject with AgentError.AccessDenied\"])\n    T3112 --> T31121([\"Resolve with DesktopAgent\"])\n    T3 -->|no|T32([\"Reject with AgentError.AgentNotFound\"])\n    T311 -->|other|T3113[\"Reject with AgentError.InvalidFailover\"]\n```\n\n## Providing Channel Selector and Intent Resolver UIs\n\nUsers of FDC3 Desktop Agents often need access to UI controls that allow them to select user channels or to resolve intents that have multiple resolution options. Whilst apps can implement these UIs on their own via data and API calls provided by the `DesktopAgent` API, Desktop Agents typically provide these interfaces themselves.\n\nHowever, Browser Resident Desktop Agents may have difficulty displaying user interfaces over applications for a variety of reasons (inability to inject code, lack of permissions to display popups, user gestures not following cross-origin comms, etc.), or may not (e.g. because they render applications in iframes within windows they control and can therefore display content over the iframe). The Web Connection Protocol and the `getAgent()` implementation based on it and incorporated into apps via the [`@finos/fdc3` npm module](https://www.npmjs.com/package/@finos/fdc3), is intended to help Desktop Agents deliver these UIs where necessary.\n\n```mermaid\nflowchart LR\n  subgraph DA [Desktop Agent Window]\n    A[(Desktop Agent)]\n  end\n  A-->B[\"getAgent()\"]\n  subgraph App [App Window]\n    B\n    subgraph iframe1 [iframe 1]\n      cs[Channel Selector]\n    end\n    subgraph iframe2 [iframe 2]\n      ir[Intent Resolver]\n    end\n  end\n  B-->cs\n  B-->ir\n```\n\nThe WCP allows applications to indicate to the `getAgent()` implementation whether they need the UIs (they may not need one or the other based on their usage of the FDC3 API, or because they implement UIs themselves) and for Desktop Agents to provide custom implementations of them, or defer to reference implementations provided by the FDC3 Standard. This is achieved via the following messages:\n\n- [`WCP1Hello`](pathname:///schemas/2.2/api/WCP1Hello.schema.json): Sent by an application and incorporating boolean `payload.intentResolver` and `payload.channelSelector` fields, which are set to `false` if either UI is not needed (defaults to `true`).\n- [`WCP3Handshake`](pathname:///schemas/2.2/api/WCP3Handshake.schema.json): Response sent by the Desktop Agent and incorporating `payload.intentResolverUrl` and `payload.channelSelectorUrl` fields, which should be set to the URL for each UI implementation that should be loaded into an iframe to provide the UI (defaults to URLs for reference UI implementations provided by the FDC3 project), or set to `false` to indicate that the respective UI is not needed. Setting these fields to `true` will cause the `getAgent()` implementation to use its default URLs representing a reference implementation of each UI.\n\nWhen UI iframes are created, the user interfaces may use the `Fdc3UserInterface` messages incorporated into the [Desktop Agent Communication Protocol (DACP)](./desktopAgentCommunicationProtocol#controlling-injected-user-interfaces) to communicate with the `getAgent()` implementation and through it the Desktop Agent.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/api/supported-platforms.md",
    "content": "---\nid: supported-platforms\ntitle: Supported Platforms\n---\n\nFDC3 is platform- and programming language-independent. An FDC3-capable platform requires a Desktop Agent that supports the FDC3 standard, and that agent is responsible for coordinating application interactions.\n\nThere are two main categories of platform: web and native, both of which are described below. There exists a third category, hybrid, where a web application runs within the context of a standalone native application via a web view.\n\n## Web\n\n:::tip\n\nThe recommended way to get access to the FDC3 Desktop Agent API in an application is to to import and call the `getAgent` function from the FDC3 NPM module, which supports all FDC3 Standard conformant Desktop Agents for web applications:\n\n```ts\nimport { DesktopAgent, getAgent, AgentError } from \"@finos/fdc3\";\n\n//...\n\ntry {\n    const desktopAgent: DesktopAgent = await getAgent();\n    //do FDC3 things here\n} catch (e: AgentError) {\n    //connection failed\n}\n\n//OR\n\ngetAgent().then((desktopAgent: DesktopAgent) => {\n    //do FDC3 things here\n}).catch((e: AgentError) => {\n    //connection failed\n});\n```\n\n[For more details on the getAgent() function and arguments you can pass to it, see its reference page.](ref/GetAgent)\n\n:::\n\nFor a web application to use the FDC3 API it needs to retrieve a copy of the `DesktopAgent` API interface, which it will use to communicate with the Desktop Agent (this interface is often referred to as the `fdc3` object or the \"FDC3 API\"). FDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can be used by web applications to retrieve a `DesktopAgent` interface and to provide typing. Each FDC3-compliant Desktop Agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\nimport Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n<Tabs>\n<TabItem value=\"npm\" label=\"npm\">\n\n```bash\nnpm install @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"yarn\" label=\"yarn\">\n\n```bash\nyarn add @finos/fdc3\n```\n\n</TabItem>\n<TabItem value=\"pnpm\" label=\"pnpm\">\n\n```bash\npnpm install @finos/fdc3\n```\n\n</TabItem>\n</Tabs>\n\nThere are two standardized types of interface to a DA that a web application may use (which is appropriate depends on where the web application is run):\n\n- **Desktop Agent Preload**: Used where the Desktop Agent is able to inject the the `DesktopAgent` API at `window.fdc3` allowing an app to access it directly, for example in an Electron app or where a browser Browser Extension is in use.\n- **Desktop Agent Proxy**: Used when running in a standard web browser (without a browser extension or similar customization). The Desktop Agent will often be running in a different window or frame to the application and MUST be communicated with via cross-document messaging with `postMessage` and `MessagePorts` (see the [HTML5 Living Standard](https://html.spec.whatwg.org/multipage/web-messaging.html) for more details). A 'proxy' class implementing the Desktop Agent API is used to abstract the details of cross-document messaging, allowing the application to work with the FDC3 API directly.\n\nThe FDC3 Standard defines a [Web Connection Protocol (WCP)](specs/webConnectionProtocol) that allows apps to work with either interface, by detecting which is applicable, and [Desktop Agent Communication Protocol (DACP)](specs/desktopAgentCommunicationProtocol) that standardizes the messaging protocol used for cross-document messaging over `postMessage` and `MessagePorts` in a web browser.\n\nThe FDC3 NPM module implements the `getAgent()` function defined by WCP and can return an injected Desktop Agent, a Desktop Agent Proxy, or other Desktop Agent implementation enabled by a non-standard interface.\n\nHence, FDC3 apps SHOULD obtain access to a `DesktopAgent` object (`fdc3`) by importing or loading the `@finos/fdc3` library and then calling the provided `getAgent()` function, ensuring that they can support any of the standardized interfaces.\n\n:::info\n\nIn prior versions of FDC3 (&lt;= 2.1) Apps were required to use the 'Desktop Agent Preload' interface, i.e. they relied on the existence of the `window.fdc3` object, which meant that apps running in a standard web browser had to import libraries specific to the Desktop Agent implementation in use. From FDC3 2.2 onwards the 'Desktop Agent Proxy' interface is available, which allows apps in a standard web browser to connect to any Desktop Agent that implements that interface.\n\nHence, from FDC3 2.2 onwards apps SHOULD call `getAgent()` to retrieve a `DesktopAgent` API interface.\n\n:::\n\nAs web applications can navigate to or be navigated by users to different URLs and become different applications, validation of apps identity is often necessary. The web application's current URL is passed to web browser-based Desktop Agents to allow them to establish the app's identity - usually connecting it with an App Directory record already known to the Desktop Agent. For more details on identity validation see the Identity Validation section of the [Web Connection Protocol (WCP)](specs/webConnectionProtocol).\n\n### Usage\n\nOnce you've retrieved a `DesktopAgent` interface you may use its functions to communicate with the Desktop Agent and through it, other applications:\n\n```js\nimport { DesktopAgent, getAgent } from \"@finos/fdc3\";\n\nasync function sendData(desktopAgent: DesktopAgent) {\n  await desktopAgent.broadcast({\n    type: \"fdc3.instrument\",\n    id: { ticker: \"AAPL\" }\n  });\n}\n\nconst desktopAgent: DesktopAgent = await getAgent();\nawait sendData(desktopAgent);\n```\n\n## Native\n\nThe FDC3 Standard currently only defines language specific API bindings for JavaScript/TypeScript and .NET, but is intended to be implemented in other languages (which can make use of the [Desktop Agent Communication Protocol (DACP)](specs/desktopAgentCommunicationProtocol) as a wire protocol, but need to define a suitable connection protocol, which includes a defined communication channel to do so).  \n\nHence, for a native application to be FDC3-enabled, it needs to either:\n\n- Make use of a shared library (such as a .NET DLL or JAR file) that provides it with an implementation of the FDC3 API (which ties it to a specific Desktop Agent implementation).\n- Model itself as a Desktop Agent (rather than just an app working with one) and use the Agent Bridging protocol to connect to a Desktop Agent Bridge and work through it to interoperate with apps managed by other Desktop Agents.\n\n### .NET\n\nFor a .NET application to be FDC3-enabled, it needs to run in the context of a platform provider that makes the FDC3 API available.  The manner in which you get a reference to the desktop agent can be highly dependent on the provider chosen.  For those looking to implement your own desktop agent, a recommended and typical design is to register an instance of the Desktop Agent at startup which can be injected into any class constructors that need references through inversion of control.  More details for creating your own DesktopAgent can be found in the [fdc3-dotnet repository](https://github.com/finos/fdc3-dotnet).\n\n#### Usage\n\nFDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can be used by .NET applications to target operations from the [API Specification](./spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations.\n\n## Hybrid\n\nIn a hybrid application, a standalone native application incorporates a web view, within which a web application runs. This may be considered a special case of the web platform where all platform-provider requirements for web applications must be satisfied, but it is the responsibility of the associated native application, rather than a platform provider, to ensure they are fulfilled. This may be achieved via either of the defined web interfaces, i.e. by injecting an implementation of the DesktopAgent API at `window.fdc3` or via the FDC3 Web Connection Protocol (`postMessage`).\n\n## Compliance\n\nSupport for each platform is optional and compliance with the FDC3 standard should be assessed for each platform implemented independently of any other, with the exception of ensuring that where applications running on multiple platforms are used together, communication between them still complies with the standard.\n\nThe Web API binding is expressed using TypeScript syntax that defines the API interface (for both TypeScript and JavaScript). Adherence to the specific binding is required for Web application platforms. No specific API binding for native platforms is currently expressed in the Standard. Hence, native applications may be implemented with any programming language binding that supports the constructs required by the API specification, until such time that the FDC3 Standard introduces an appropriate language-specific binding.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/app-directory/overview.md",
    "content": "---\nid: overview\nsidebar_label: Overview\ntitle: App Directory Overview (2.2)\n---\n\nAn application directory (appD) is a structured repository of information about apps that can be used in an FDC3-enabled desktop. In other words, it’s a convenient way of storing and managing metadata about apps in your ecosystem.\n\nThe application metadata stored in appD records may include: the app name, type, details about how to run the application, its icons, publisher, support contact details and so on. It may also include links to or embed manifest formats defined elsewhere, such as proprietary manifests for launching the app in a container product or a Web Application Manifest (as [defined by the W3C](https://www.w3.org/TR/appmanifest/)).\n\nAll this information is readily available in one place and can be used both to populate a launcher or app catalog UI for your users, and by the Desktop Agent managing the apps on your desktop. In fact, if your desktop platform supports the FDC3 standard, appD is the primary way that the FDC3 Desktop Agent implementation should receive the details about apps available to run on your desktop. Conversely, if an app is not listed in appD, the Desktop Agent can’t ensure its participation in context sharing or use it to resolve intents.\n\n## Advantages\n\nUsing appD offers many advantages both for financial institutions running an FDC3-enabled desktop container and for vendors that provide FDC3-compliant apps:\n\n### For the user\n\n#### Easier to Find App Info\n\nYour appD is the one place to collect all the information about apps. The more apps you have, the more you’ll appreciate the convenience of not having to chase down details about each. This is particularly important for large institutions with multiple desks.\n\n#### Human Readable\n\nAppD has two types of users. One is the Desktop Agent, but the other is humans administrating and using the smart desktop at your organization. Hence, an appD contains information about apps in both machine- and human-readable forms. For example, it includes both unique identifiers for apps that are used to refer to them in code and human-friendly app names, icons, descriptions and tooltips necessary to populate a launcher menu or app catalog user interface for your users.\n\n#### Apps are Discoverable\n\nFor large institutions, it can be difficult to keep track of all the apps (developed both in-house and by vendors), since a typical desktop could have many. Users can search appD to discover the apps they need. An app might already reside on their system or be available to them over the internet, but if they don’t have a way to search the apps available to them, they won’t be able to find it. An appD provides a way for users to discover the apps they need.\n\nAn appD makes it possible to discover info about apps that reside on various domains, not just the one domain the appD itself is hosted on. In addition, you can find details about how to launch the apps in multiple, diverse environments. This is a different use-case to, for example, the [W3C's Web App Manifest](https://www.w3.org/TR/appmanifest/), which is hosted on the same domain as the app, is limited to web apps, and is generally used to 'install' an app that the user has already accessed.\n\n#### Updating Apps\n\nTypically, software evolves over time. The app versions you are running today will not be the same ones you need tomorrow. Therefore, you will need to upgrade apps periodically. Very few people look forward to upgrading, but appD and web deployment can make it easier for you. To roll out a new version of your app, either update the existing entry for it in appD or add a new entry for that version (allowing users to select the version they will use).\n\n#### Agent-agnostic\n\nAs a part of the FDC3 standard, appD isn't tied to any specific vendor. This is important, as it allows you more flexibility in that you are not tied to any specific container or Desktop Agent implementation. If at any point you want to switch to a different Desktop Agent, the process won’t be prohibitively difficult. The existing appD will work without any additional effort from you, as long as your new Desktop Agent is also FDC3-compliant. This is in contrast with proprietary solutions, where you would have to produce a new configuration and integration for every application.\n\nAppD reduces fragmentation in the market and allows end-users more flexibility in what applications can be included in their desktop.\n\n#### Intent Resolution\n\nAppD provides information to the Desktop Agent on which applications can handle particular [intents](../intents/spec) and the context types they support as input to them. This allows the Desktop Agent to implement an [intent resolver](../api/spec#resolvers) that can launch applications and pass the intent and context to them to operate on, supporting workflows between applications that didn't require prior bilateral agreements between the application providers.\n\n### For an Application Provider\n\nUntil now, we've looked at appD from the perspective of a desktop owner and user. But appD also offers advantages to vendors who develop apps for the financial services desktop.\n\n#### Apps Work Well Together Out-of-the-box\n\nWhen your customers add your FDC3-compliant app to their desktop via an appD record accurately describing it, you can be sure that your app will interoperate with other apps that follow the FDC3 standard. You don’t have to do anything special, or arrange a bilateral agreement with anyone else. The benefit of the open standard is that any app that follows it will work well with any other compliant app.\n\n#### Easy Updates\n\nAs a vendor, you prefer for all your customers to run your latest software. However, many customers will postpone upgrades, sometimes for a long time, because upgrading can be a pain. An advantage of a vendor-hosted appD is that the configuration of an app can be updated at any time and, if your customers need to choose when to upgrade, multiple versions of it can be made available, each with their own configuration. By making it easier for customers to update, you can drive better adoption.\n\n### For the Industry\n\nBy hosting our own appD we can easily combine applications from various providers into one cohesive directory. Alternatively, we can connect to directories from multiple providers (in standardized format) and provide a single view over them. This reduces fragmentation in the market, allows end-users more flexibility in what apps to include in their smart desktop, and obviates the need for vendors to provide application details in diverse formats or for their customers to work out these details for themselves.\n\n## Relationship to Other Standards\n\nThe App Directory's application record is similar to application manifests defined in other standards, in particular the W3C's [Web Application Manifest](https://www.w3.org/TR/appmanifest/). However, the App Directory, and by extension the application record, serve a different set of use-cases specific to application interoperability on financial services desktops, which other standards do not fully address.\n\nWherever possible, FDC3 seeks to draw inspiration from, align itself with and reference other standards - ensuring that conventions and best practices developed by those standards are reused, along with the standard itself (e.g. data formats in ISO standard formats, external links to technology-specific manifest file formats etc.). For a list of standards that FDC3 references, see the [References](../references) page.\n\n## Use Cases\n\nAn application directory provides information about an application's identifiers, publisher details, intents that it supports, and metadata necessary to launch and integrate the application in a Desktop Agent.\n\nThe following provides a summary of use cases.\n\n### Launcher\n\nA Desktop Agent will usually include a user interface allowing the user to select from a set of launchable applications and then allow them to manually launch one. It is also responsible for launching applications necessary to resolve a raised intent. However, it must first retrieve the necessary metadata about the available applications. An app directory provides an endpoint to retrieve a list of the available applications along with their metadata, which may include or link to additional information necessary to launch the application in a specific Desktop Agent.\n\nA launcher will usually be configured with the locations of one or more AppD servers (which is necessary to implement intent resolution), however, as described in the [Service Discovery](#service-discovery) section, a fully qualified application identifier (e.g. `app1@host.appd.com`) may also be used to both locate the appD service and to retrieve the specific application data.\n\n![img](/assets/appd_launcher_embedded.png)\n\n### Aggregated View\n\nThere could be many different appD service instances in the world providing application data zoned to the provider or enterprise deployment. The appD specification allows for unique instances of the service with no requirement to aggregate data or define a structured hierarchy. With this said, a launcher might want to construct an aggregated view of applications from one or more appD instances. In this case, the launcher would be required to retrieve multiple application definitions from one or more appD instances providing a consolidated view of all applications required.\n\nToday, there is no intention to create a single registry of known AppD instances, so there is an assumption that the launcher will have prior\nknowledge of the AppD instance location.\n\n![img](/assets/appd_launcher_aggregated.png)\n\n### Authentication and Entitlements\n\nThe AppD API specification defines the optional use of an access token to identify the requesting user/launcher and implement authorizations which may affect appD API responses. For example, different subsets of the full list of applications may be returned for different users depending on their role in an organization.\n\nThe specification does not define or make mandatory any authorizations or roles that a provider or enterprise can define.\n\n## Application Identifiers\n\nApplication Records served by an app directory are each labelled with an identifier, `appId`, which should be unique within the app directory instance and may be used to refer to or retrieve the application's record via the [app directory API](spec). This identifier may be made globally unique through a nested namespace approach and email address construction (`appId@fqdn`) where `@` followed by the app directory instance's host name is appended to it. The resulting globally unique identifier is known as a 'fully qualified application identifier'.\n\nFully qualified appIds may be used to locate the appD instance hosting the application's record. See the [Service Discovery](#service-discovery) section for details.\n\n### Shrinking the URI\n\nAlthough the concept of fully qualified application IDs are useful in resolving the actual host of the application directory, there is no requirement for an application directory to use this fully qualified application ID as the resolver for a record.  An application ID is unique to given application directory, but there is no requirement to use the fully qualified representation when querying an interface.  Taking the prior example, the fully qualified application ID `app1@appd.foo.com` is represented as `app1` within the application directory.  As a result a launcher can use a shortened URI construct `https://appd.foo.com/api/appd/v2/apps/app1` to resolve the application data vs `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`.\n\n## Service Discovery\n\nIn order to support the discovery of applications that can be used with a Desktop Agent, it is necessary to access data stored in one or more app directory instances.\n\n![img](/assets/appd_service_distribution.png)\n\nHowever, in order to do so, you must first discover the location of an app directory service, which you may then use to generate URIs  (e.g. `https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com`) to query a given directory instance for data. In order to construct a URI, the host location and port of a given AppD service instance is required.\n\nThree methods for discovering app directory services are defined in this Standard:\n\n  1. **Static configuration:** Statically defined URI records for use within client applications (typically a Desktop Agent implementation) directly.\n  2. **Fully-qualified appID namespace syntax host resolution:** Discovery of the appD location using a fully qualified application ID (appId) domain name.\n  3. **DNS lookup by domain name:** Discovery of the appD location using a domain name to lookup DNS SRV records identifying the host server location and TCP port. ([RFC2782](https://tools.ietf.org/html/rfc2782))\n\nApp directory service host discovery implementations SHOULD support each of these methods and MUST support at least static configuration.\n\n### Static configuration\n\nAs the name implies, a static configuration for an appD service location is defined within a Desktop Agent or launcher application. This is the simplest and most common approach to app directory and application data discovery.\n\n![img](/assets/appd_static_config.png)\n\n### Fully-qualified appID namespace syntax host resolution\n\nAn app directory URI can be constructed using a [fully qualified application ID](overview#application-identifiers) (email address syntax) by using fqdn part of the ID as the host location and the name part as the application name. Given an application id `app1` with a fully qualified identifier of `app1@appd.foo.com` an application directory host location can be derived by simply extracting the fqdn \"appd.foo.com\" from the email syntax. The extracted fqdn \"app.foo.com\" MUST resolve to the actual host location where the application directory is running.\n\nA launcher can then easily construct a URI by:\n\n1. URI protocol is defaulted to `https`, but can be overridden by the launcher.\n2. URI hostname is the fully qualified domain of the application ID.\n3. URI port is default `https/443`, but can be overridden by the launcher\n4. URI url is by default `/api/appd/(version)/apps` . Calls that are made without version MUST automatically default to latest, i.e. `/api/appd/apps/app1` should return the same result as `/api/appd/v2/apps/app1\".\n\nThe resulting URI to retrieve application data for `app1` would be [https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com](https://appd.foo.com/api/appd/v2/apps/app1@appd.foo.com)\n\n### DNS/SRV Records\n\nAnother approach to support app directory service discovery (resolution) is through use of existing domain name service (DNS) implementations that are broadly used on the Internet today (see: [RFCs](https://www.isc.org/community/rfcs/dns/)). Name service implementations can be considered critical infrastructure and are proven stable with over twenty years of use. Name services can be used both through public Internet or locally deployed intranet, which provides optionality to deployment schemes.\n\nMore specifically, resolution of an appD service instance (host location) can be implemented using DNS \"service records\" (SRV) providing the host instance, protocol and associated port. The following is a well-known description of a SRV record ([RFC2782](https://tools.ietf.org/html/rfc2782)):\n\n```text\nzone name { _service._proto.name. TTL  class  SRV priority weight port target.}\n```\n\n- *`service`*: the symbolic name of the desired service.  For AppD service, this must be identified as **`_appd`**\n- *`proto`*: the transport protocol of the desired service; this is usually either [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) or [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).  For AppD service **_tcp** must be used.\n- *`name`*: the domain name for which this record is valid, ending in a dot.  For AppD service,  the name should directly map to the application identifier domain.\n- *`TTL`*: standard DNS [time to live](https://en.wikipedia.org/wiki/Time_to_live) field.\n- *`class`*: standard DNS class field (this is always *IN*).\n- *`priority`*: the priority of the target host, lower value means more preferred.\n- *`weight`*: A relative weight for records with the same priority, higher value means more preferred.\n- *`port`*: the TCP or UDP port on which the service is to be found. For AppD service, TCP should always be used.\n- *`target`*: the canonical hostname of the machine providing the service, ending in a dot. This would be the host where the AppD service is running.\n\nFor AppD Service the SRV record MUST use the following definitions:\n\n- `service` = **`_appd`**\n- `proto` = **`_tcp`**\n- `name` = must map to the domain of the application identifier . Example:  the `name` for application identifier `app1@appd.foo.com` would be `appd.foo.com`\n\n*AppD service through DNS / SRV records:*\n\n![img](/assets/appd_dns.png)\n\n#### Known domains\n\nAlthough SRV records provide the means of resolving the location of an app directory service for a specific domain, there could be a need to know what domains exist in the universe. This would be a list of domains representing all known directory instances. It is recommended that the FDC3/FINOS organization publish a list of known domains which support AppD services. This publication can be handled in multiple ways, such as structured files or API endpoints. This proposal shall not provide a qualified solution to achieve this, but rather draw attention to a potential requirement.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/app-directory/spec.md",
    "content": "---\nid: spec\nsidebar_label: API\ntitle: App Directory API (2.2)\n---\n\nView the [full specification][1] in [OpenAPI v3.0][2] format (generated with [ReDoc][3]),\nor explore with the [Swagger Editor][4].\n\n[1]: pathname:///schemas/2.2/app-directory.html\n[2]: https://www.openapis.org/\n[3]: https://github.com/Redocly/redoc/\n[4]: https://editor.swagger.io/?url=https://fdc3.finos.org/schemas/2.2/appd.schema.json\n\n## Endpoints\n\n Endpoint           | Method | Description\n ------------------ | ------ | -----------\n `/v2/apps`         | GET    | Retrieve all application definitions\n `/v2/apps/{appId}` | GET    | Retrieve an application definition\n `/v1/apps`         | POST   | (deprecated v1 API version) Create a new application definition\n `/v1/apps/{appId}` | GET    | (deprecated v1 API version) Retrieve an application definition\n `/v1/apps/search`  | GET    | (deprecated v1 API version) Retrieve a list of applications\n\nApp Directory implementations MAY extend the list of endpoints to provide other necessary functionality. However, FDC3 Desktop Agent implementations that connect to app directories MUST support connection to app directories that only provide the minimum endpoints listed here.\n\n## App Directory Standard Compliance\n\nAn FDC3 Standard compliant App Directory implementation **MUST**:\n\n- Implement the specified `/v2` endpoints for retrieving app definitions as defined in the [app directory OpenAPI specification](pathname:///schemas/2.2/app-directory.html#tag/Application):\n  - `/v2/apps` (GET)\n  - `/v2/apps/{appId}` (GET)\n- Ensure that `appId` field values assigned to applications are unique within the directory.\n- Ensure that app directory records served meet the minimum requirements specified in the [app directory OpenAPI specification](pathname:///schemas/2.2/app-directory.html#tag/Application)\n- Support retrieval of app directory records via either the raw `appId` (e.g. `myAppId`) or fully-qualified appId (e.g. `myAppId@host.domain.com`) as defined in the [app directory overview](overview#shrinking-the-uri).\n\nAn FDC3 Standard compliant App Directory implementation **SHOULD**:\n\n- Support authentication (where required) via the HTTP Authorization header and Bearer authentication schema (implemented via JWT tokens)\n- Select any `categories` field values from the recommended list.\n- Encourage the use of the `lang` and `localizedVersions` fields in appD records to support localization and accessibility.\n\nAn FDC3 Standard compliant App Directory implementation **MAY**:\n\n- Support filtering of application records returned by user entitlement, where authentication is enabled.\n- Implement the deprecated `/v1` endpoints provided for backwards compatibility with prior version of the standard:\n  - `/v1/apps` (POST)\n  - `/v1/apps/{appId}` (GET)\n  - `/v1/apps/search` (GET)\n- Extend the implementation with additional endpoints.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Action.md",
    "content": "---\ntitle: Action\nsidebar_label: Action\n\n---\n\n# Action\n\nA representation of an FDC3 Action (specified via a Context or Context & Intent) that can be inserted inside another object, for example a chat message.\n\nThe action may be completed by calling:\n- `fdc3.raiseIntent()` with the specified Intent and Context\n- `fdc3.raiseIntentForContext()` if only a context is specified, (which the Desktop Agent will resolve by presenting the user with a list of available Intents for the Context).\n- `channel.broadcast()` with the specified Context, if the `broadcast` action has been defined.\n\nAccepts an optional `app` parameter in order to specify a specific app.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/action.schema.json](pathname:///schemas/2.2/context/action.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/action.schema.json))\n\n## Type\n\n`fdc3.action`\n\n## Properties\n\n<details>\n  <summary><code>action</code></summary>\n\n**type**: `string` with values:\n- `broadcast`,\n- `raiseIntent`\n\nThe **action** field indicates the type of action:\n- **raiseIntent** :  If no action or `raiseIntent` is specified, then `fdc3.raiseIntent` or `fdc3.raiseIntentForContext` will be called with the specified context (and intent if given).\n- **broadcast** : If `broadcast` and a `channelId` are specified then `fdc3.getOrCreateChannel(channelId)` is called to retrieve the channel and broadcast the context to it with `channel.broadcast(context)`. If no `channelId` has been specified, the context should be broadcast to the current channel (`fdc3.broadcast()`)\n\n</details>\n\n<details>\n  <summary><code>title</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA human readable display name for the action\n\n</details>\n\n<details>\n  <summary><code>intent</code></summary>\n\n**type**: `string`\n\nOptional Intent to raise to perform the actions. Should reference an intent type name, such as those defined in the FDC3 Standard. If intent is not set then `fdc3.raiseIntentForContext` should be used to perform the action as this will usually allow the user to choose the intent to raise.\n\n</details>\n\n<details>\n  <summary><code>context</code> <strong>(required)</strong></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\nA context object with which the action will be performed\n\n</details>\n\n<details>\n  <summary><code>channelId</code></summary>\n\n**type**: `string`\n\nOptional channel on which to broadcast the context. The `channelId` property is ignored unless the `action` is broadcast.\n\n</details>\n\n<details>\n  <summary><code>app</code></summary>\n\n**type**: api/AppIdentifier\n\nAn optional target application identifier that should perform the action. The `app` property is ignored unless the action is raiseIntent.\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.action\",\n  \"action\": \"raiseIntent\",\n  \"title\": \"Click to view Chart\",\n  \"intent\": \"ViewChart\",\n  \"context\": {\n    \"type\": \"fdc3.chart\",\n    \"instruments\": [\n      {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"EURUSD\"\n        }\n      }\n    ],\n    \"range\": {\n      \"type\": \"fdc3.dateRange\",\n      \"starttime\": \"2020-09-01T08:00:00.000Z\",\n      \"endtime\": \"2020-10-31T08:00:00.000Z\"\n    },\n    \"style\": \"candle\"\n  },\n  \"app\": {\n    \"appId\": \"MyChartViewingApp\",\n    \"instanceId\": \"instance1\"\n  }\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.action\",\n  \"action\": \"broadcast\",\n  \"channelId\": \"Channel 1\",\n  \"title\": \"Click to view Chart\",\n  \"context\": {\n    \"type\": \"fdc3.chart\",\n    \"instruments\": [\n      {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"EURUSD\"\n        }\n      }\n    ],\n    \"range\": {\n      \"type\": \"fdc3.dateRange\",\n      \"starttime\": \"2020-09-01T08:00:00.000Z\",\n      \"endtime\": \"2020-10-31T08:00:00.000Z\"\n    },\n    \"style\": \"candle\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/BaseContext.md",
    "content": "---\ntitle: BaseContext\nsidebar_label: BaseContext\n\n---\n\n# BaseContext\n\n## Schema\n\n[https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json](https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json)\n\n## Type\n\n`undefined`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n</details>\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Chart.md",
    "content": "---\ntitle: Chart\nsidebar_label: Chart\n\n---\n\n# Chart\n\nA context type representing details of a Chart, which may be used to request plotting of a particular chart or to otherwise share details of its composition, such as:\n\n- A list of instruments for comparison\n- The time period to plot the chart over\n- The style of chart (line, bar, mountain, candle etc.)\n- Other settings such as indicators to calculate, or data representing drawings and annotations.\n\nIn addition to handling requests to plot charts, a charting application may use this type to output a representation of what it is currently displaying so that it can be recorded by another application.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/chart.schema.json](pathname:///schemas/2.2/context/chart.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chart.schema.json))\n\n## Type\n\n`fdc3.chart`\n\n## Properties\n\n<details>\n  <summary><code>instruments</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Instrument](Instrument)\n\n</details>\n\nAn array of instrument contexts whose data should be plotted.\n\n</details>\n\n<details>\n  <summary><code>range</code></summary>\n\n**type**: [TimeRange](TimeRange)\n\nThe time range that should be plotted\n\n</details>\n\n<details>\n  <summary><code>style</code></summary>\n\n**type**: `string` with values:\n- `line`,\n- `bar`,\n- `stacked-bar`,\n- `mountain`,\n- `candle`,\n- `pie`,\n- `scatter`,\n- `histogram`,\n- `heatmap`,\n- `custom`\n\nThe type of chart that should be plotted\n\n</details>\n\n<details>\n  <summary><code>otherConfig</code></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\n</details>\n\nIt is common for charts to support other configuration, such as indicators, annotations etc., which do not have standardized formats, but may be included in the `otherConfig` array as context objects.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chart\",\n  \"instruments\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"AAPL\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"GOOG\"\n      }\n    }\n  ],\n  \"range\": {\n    \"type\": \"fdc3.timeRange\",\n    \"startTime\": \"2020-09-01T08:00:00.000Z\",\n    \"endTime\": \"2020-10-31T08:00:00.000Z\"\n  },\n  \"style\": \"line\",\n  \"otherConfig\": [\n    {\n      \"type\": \"somevendor.someproduct.indicator\",\n      \"name\": \"stddev\",\n      \"parameters\": {\n        \"period\": 10,\n        \"matype\": \"exponential\"\n      }\n    },\n    {\n      \"type\": \"someothervendor.someotherproduct.formula\",\n      \"formula\": \"standard-deviation\",\n      \"fields\": {\n        \"lookback\": 10,\n        \"type\": \"ema\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/ChatInitSettings.md",
    "content": "---\ntitle: ChatInitSettings\nsidebar_label: ChatInitSettings\n\n---\n\n# ChatInitSettings\n\nA collection of settings to start a new chat conversation\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/chatInitSettings.schema.json](pathname:///schemas/2.2/context/chatInitSettings.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatInitSettings.schema.json))\n\n## Type\n\n`fdc3.chat.initSettings`\n\n## Properties\n\n<details>\n  <summary><code>chatName</code></summary>\n\n**type**: `string`\n\nName to apply to the chat created\n\n</details>\n\n<details>\n  <summary><code>members</code></summary>\n\n**type**: [ContactList](ContactList)\n\nContacts to add to the chat\n\n</details>\n\n<details>\n  <summary><code>message</code></summary>\n\n**One of:**\n\n- **type**: `string`\n- **type**: [Message](Message)\n\nAn initial message to post in the chat when created.\n\n</details>\n\n<details>\n  <summary><code>options</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>groupRecipients</code></summary>\n\n**type**: `boolean`\n\nif false a separate chat will be created for each member\n\n</details>\n\n<details>\n  <summary><code>isPublic</code></summary>\n\n**type**: `boolean`\n\nif true the room will be visible to everyone in the chat application\n\n</details>\n\n<details>\n  <summary><code>allowHistoryBrowsing</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to browse past messages\n\n</details>\n\n<details>\n  <summary><code>allowMessageCopy</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to copy/paste messages\n\n</details>\n\n<details>\n  <summary><code>allowAddUser</code></summary>\n\n**type**: `boolean`\n\nif true members will be allowed to add other members to the chat\n\n</details>\n\nOption settings that affect the creation of the chat\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.initSettings\",\n  \"chatName\": \"Chat ABCD\",\n  \"members\": {\n    \"type\": \"fdc3.contactList\",\n    \"contacts\": [\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane@mail.com\"\n        }\n      },\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"John Doe\",\n        \"id\": {\n          \"email\": \"john@mail.com\"\n        }\n      }\n    ]\n  },\n  \"options\": {\n    \"groupRecipients\": true,\n    \"isPublic\": false,\n    \"allowHistoryBrowsing\": true,\n    \"allowMessageCopy\": true\n  },\n  \"message\": {\n    \"type\": \"fdc3.message\",\n    \"text\": {\n      \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n    },\n    \"entities\": {\n      \"0\": {\n        \"type\": \"fdc3.fileAttachment\",\n        \"data\": {\n          \"name\": \"myImage.png\",\n          \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n        }\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/ChatMessage.md",
    "content": "---\ntitle: ChatMessage\nsidebar_label: ChatMessage\n\n---\n\n# ChatMessage\n\nA context representing a chat message. Typically used to send the message or to pre-populate a message for sending.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/chatMessage.schema.json](pathname:///schemas/2.2/context/chatMessage.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatMessage.schema.json))\n\n## Type\n\n`fdc3.chat.message`\n\n## Properties\n\n<details>\n  <summary><code>chatRoom</code> <strong>(required)</strong></summary>\n\n**type**: [ChatRoom](ChatRoom)\n\n</details>\n\n<details>\n  <summary><code>message</code> <strong>(required)</strong></summary>\n\n**type**: [Message](Message)\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.message\",\n  \"chatRoom\": {\n    \"type\": \"fdc3.chat.room\",\n    \"providerName\": \"Symphony\",\n    \"id\": {\n      \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n    }\n  },\n  \"message\": {\n    \"type\": \"fdc3.message\",\n    \"text\": {\n      \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot\"\n    },\n    \"entities\": {\n      \"0\": {\n        \"type\": \"fdc3.fileAttachment\",\n        \"data\": {\n          \"name\": \"myImage.png\",\n          \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n        }\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/ChatRoom.md",
    "content": "---\ntitle: ChatRoom\nsidebar_label: ChatRoom\n\n---\n\n# ChatRoom\n\nReference to the chat room which could be used to send a message to the room\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/chatRoom.schema.json](pathname:///schemas/2.2/context/chatRoom.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatRoom.schema.json))\n\n## Type\n\n`fdc3.chat.room`\n\n## Properties\n\n<details>\n  <summary><code>providerName</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe name of the service that hosts the chat\n\n</details>\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nIdentifier(s) for the chat - currently unstandardized\n\n</details>\n\n<details>\n  <summary><code>url</code></summary>\n\n**type**: `string`\n\nUniversal url to access to the room. It could be opened from a browser, a mobile app, etc...\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nDisplay name for the chat room\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.room\",\n  \"providerName\": \"Symphony\",\n  \"id\": {\n    \"streamId\": \"j75xqXy25NBOdacUI3FNBH\"\n  },\n  \"url\": \"http://symphony.com/ref/room/j75xqXy25NBOdacUI3FNBH___pqSsuJRdA\",\n  \"name\": \"My new room\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/ChatSearchCriteria.md",
    "content": "---\ntitle: ChatSearchCriteria\nsidebar_label: ChatSearchCriteria\n\n---\n\n# ChatSearchCriteria\n\nA context type that represents a simple search criterion, based on a list of other context objects, that can be used to search or filter messages in a chat application.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/chatSearchCriteria.schema.json](pathname:///schemas/2.2/context/chatSearchCriteria.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/chatSearchCriteria.schema.json))\n\n## Type\n\n`fdc3.chat.searchCriteria`\n\n## Properties\n\n<details>\n  <summary><code>criteria</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n  <summary><code>Search Criteria</code></summary>\n\n**One of:**\n\n- **type**: [Instrument](Instrument)\n- **type**: [Organization](Organization)\n- **type**: [Contact](Contact)\n- **type**: `string`\n\nAn individual criteria against which to match chat messages, based on an FDC3 context or free-text string.\n\n\n\n\n</details>\n\nAn array of criteria that should match chats returned from by a search.\n\n⚠️ Operators (and/or/not) are not defined in `fdc3.chat.searchCriteria`. It is up to the application that processes the FDC3 Intent to choose and apply the operators between the criteria.\n\nEmpty search criteria can be supported to allow resetting of filters.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.chat.searchCriteria\",\n  \"criteria\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"TSLA\"\n      },\n      \"name\": \"Tesla, inc.\"\n    },\n    \"annual return\"\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Contact.md",
    "content": "---\ntitle: Contact\nsidebar_label: Contact\n\n---\n\n# Contact\n\nA person contact that can be engaged with through email, calling, messaging, CMS, etc.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/contact.schema.json](pathname:///schemas/2.2/context/contact.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/contact.schema.json))\n\n## Type\n\n`fdc3.contact`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>email</code></summary>\n\n**type**: `string`\n\nThe email address for the contact\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nFactSet Permanent Identifier representing the contact\n\n</details>\n\nIdentifiers that relate to the Contact represented by this context\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the contact\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.contact\",\n  \"name\": \"Jane Doe\",\n  \"id\": {\n    \"email\": \"jane.doe@mail.com\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/ContactList.md",
    "content": "---\ntitle: ContactList\nsidebar_label: ContactList\n\n---\n\n# ContactList\n\nA collection of contacts, e.g. for chatting to or calling multiple contacts.\n\nThe contact list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/contactList.schema.json](pathname:///schemas/2.2/context/contactList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/contactList.schema.json))\n\n## Type\n\n`fdc3.contactList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the contact list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the contact list\n\n</details>\n\n<details>\n  <summary><code>contacts</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Contact](Contact)\n\n</details>\n\nAn array of contact contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.contactList\",\n  \"contacts\": [\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"Jane Doe\",\n      \"id\": {\n        \"email\": \"jane.doe@mail.com\"\n      }\n    },\n    {\n      \"type\": \"fdc3.contact\",\n      \"name\": \"John Doe\",\n      \"id\": {\n        \"email\": \"john.doe@mail.com\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Context.md",
    "content": "---\nid: Context\nsidebar_label: Context\ntitle: Context\nhide_title: true\n---\n# `Context`\n\nThe `fdc3.context` type defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not\nreally meant to be used on its own, but is imported by more specific type definitions (standardised or custom) to provide\nthe structure and properties shared by all FDC3 context data types.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has.\n\nNotes:\n\n- The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type\ncan be expected to have, but this can always be extended with custom fields as appropriate.\n\n## Type\n\n`fdc3.context`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/context.schema.json](pathname:///schemas/2.2/context/context.schema.json)\n\n## Details\n\n| Property    | Type    | Required | Example Value                    |\n|-------------|---------|----------|----------------------------------|\n| `type`      | string  | Yes      | `'fdc3.context'`                 |\n| `name`      | string  | No       | `'Display name'`                 |\n| `id`        | object  | No       | `{ id: 'value', 'id': 'value' }` |\n\n### `type` (required)\n\nThe type property is the only _required_ part of the FDC3 context data schema.\nThe FDC3 [API](../../api/spec) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../../intents/spec) also register the context data types they support in an FDC3 [App Directory](../../app-directory/overview), used for intent discovery and routing.\n\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`.\nFor non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\nSee the [Context Data Specification](../../context/spec) for more information about context data types.\n\n### `name` (optional)\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id` (optional)\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier.\n\nIdentifier values SHOULD always be of type string.\n\n## See Also\n\nFDC3 Specifications\n\n- [Context Data](../../context/spec)\n- [Intents](../../intents/spec)\n- [API](../../api/spec)\n- [App Directory](../../app-directory/spec)\n\nFDC3 Context Types\n\n- [Contact](Contact)\n- [ContactList](ContactList)\n- [Country](Country)\n- [Instrument](Instrument)\n- [InstrumentList](InstrumentList)\n- [Organization](Organization)\n- [Position](Position)\n- [Portfolio](Portfolio)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Country.md",
    "content": "---\ntitle: Country\nsidebar_label: Country\n\n---\n\n# Country\n\nA country entity.\n\nNotes:\n\n- It is valid to include extra properties and metadata as part of the country payload, but the minimum requirement is for at least one standardized identifier to be provided\n\n  - `COUNTRY_ISOALPHA2` SHOULD be preferred.\n\n- Try to only use country identifiers as intended and specified in the [ISO standard](https://en.wikipedia.org/wiki/ISO_3166-1). E.g. the `COUNTRY_ISOALPHA2` property must be a recognized value and not a proprietary two-letter code. If the identifier you want to share is not a standardized and recognized one, rather define a property that makes it clear what value it is. This makes it easier for target applications.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/country.schema.json](pathname:///schemas/2.2/context/country.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/country.schema.json))\n\n## Type\n\n`fdc3.country`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA2</code></summary>\n\n**type**: `string`\n\nTwo-letter ISO country code\n\n</details>\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA3</code></summary>\n\n**type**: `string`\n\nThree-letter ISO country code\n\n</details>\n\n<details>\n  <summary><code>ISOALPHA2</code></summary>\n\n**type**: `string`\n\nTwo-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\n\n</details>\n\n<details>\n  <summary><code>ISOALPHA3</code></summary>\n\n**type**: `string`\n\nThree-letter ISO country code. Deprecated in FDC3 2.0 in favour of the version prefixed with `COUNTRY_`.\n\n</details>\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the country\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.country\",\n  \"name\": \"Sweden\",\n  \"id\": {\n    \"COUNTRY_ISOALPHA2\": \"SE\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Currency.md",
    "content": "---\ntitle: Currency\nsidebar_label: Currency\n\n---\n\n# Currency\n\nA context representing an individual Currency.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/currency.schema.json](pathname:///schemas/2.2/context/currency.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/currency.schema.json))\n\n## Type\n\n`fdc3.currency`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nThe name of the currency for display purposes\n\n</details>\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>CURRENCY_ISOCODE</code></summary>\n\n**type**: `string`\n\nThe `CURRENCY_ISOCODE` should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\n\n</details>\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.currency\",\n  \"name\": \"US Dollar\",\n  \"id\": {\n    \"CURRENCY_ISOCODE\": \"USD\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/DocumentedContext.md",
    "content": "---\ntitle: DocumentedContext\nsidebar_label: DocumentedContext\n\n---\n\n# DocumentedContext\n\n## Schema\n\n[https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json](https://github.com/finos/FDC3/tree/main/schemas/context/context.schema.json)\n\n## Type\n\n`undefined`\n\n## Properties\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nContext data objects may include a name property that can be used for more information, or display purposes. Some derived types may require the name object as mandatory, depending on use case.\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\nContext data objects may include a set of equivalent key-value pairs that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types may choose to require at least one identifier. Identifier values SHOULD always be of type string.\n\n</details>\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Email.md",
    "content": "---\ntitle: Email\nsidebar_label: Email\n\n---\n\n# Email\n\nA collection of information to be used to initiate an email with a Contact or ContactList.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/email.schema.json](pathname:///schemas/2.2/context/email.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/email.schema.json))\n\n## Type\n\n`fdc3.email`\n\n## Properties\n\n<details>\n  <summary><code>recipients</code> <strong>(required)</strong></summary>\n\n**One of:**\n\n- **type**: [Contact](Contact)\n- **type**: [ContactList](ContactList)\n\nOne or more recipients for the email.\n\n</details>\n\n<details>\n  <summary><code>subject</code></summary>\n\n**type**: `string`\n\nSubject line for the email.\n\n</details>\n\n<details>\n  <summary><code>textBody</code></summary>\n\n**type**: `string`\n\nBody content for the email.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/FileAttachment.md",
    "content": "---\ntitle: File Attachment\nsidebar_label: File Attachment\n\n---\n\n# File Attachment\n\nA File attachment encoded in the form of a data URI. Can be added to a Message.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/fileAttachment.schema.json](pathname:///schemas/2.2/context/fileAttachment.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/fileAttachment.schema.json))\n\n## Type\n\n`fdc3.fileAttachment`\n\n## Properties\n\n<details>\n  <summary><code>data</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>name</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe name of the attached file\n\n</details>\n\n<details>\n  <summary><code>dataUri</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA data URI encoding the content of the file to be attached\n\n</details>\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.fileAttachment\",\n  \"data\": {\n    \"name\": \"myImage.png\",\n    \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Instrument.md",
    "content": "---\ntitle: Instrument\nsidebar_label: Instrument\n\n---\n\n# Instrument\n\nA financial instrument from any asset class.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/instrument.schema.json](pathname:///schemas/2.2/context/instrument.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/instrument.schema.json))\n\n## Type\n\n`fdc3.instrument`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>BBG</code></summary>\n\n**type**: `string`\n\nhttps://www.bloomberg.com/\n\n</details>\n\n<details>\n  <summary><code>CUSIP</code></summary>\n\n**type**: `string`\n\nhttps://www.cusip.com/\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nhttps://www.factset.com/\n\n</details>\n\n<details>\n  <summary><code>FIGI</code></summary>\n\n**type**: `string`\n\nhttps://www.openfigi.com/\n\n</details>\n\n<details>\n  <summary><code>ISIN</code></summary>\n\n**type**: `string`\n\nhttps://www.isin.org/\n\n</details>\n\n<details>\n  <summary><code>PERMID</code></summary>\n\n**type**: `string`\n\nhttps://permid.org/\n\n</details>\n\n<details>\n  <summary><code>RIC</code></summary>\n\n**type**: `string`\n\nhttps://www.refinitiv.com/\n\n</details>\n\n<details>\n  <summary><code>SEDOL</code></summary>\n\n**type**: `string`\n\nhttps://www.lseg.com/sedol\n\n</details>\n\n<details>\n  <summary><code>ticker</code></summary>\n\n**type**: `string`\n\nUnstandardized stock tickers\n\n</details>\n\nAny combination of instrument identifiers can be used together to resolve ambiguity, or for a better match. Not all applications will use the same instrument identifiers, which is why FDC3 allows for multiple to be specified. In general, the more identifiers an application can provide, the easier it will be to achieve interoperability.\n\nIt is valid to include extra properties and metadata as part of the instrument payload, but the minimum requirement is for at least one instrument identifier to be provided.\n\nTry to only use instrument identifiers as intended. E.g. the `ticker` property is meant for tickers as used by an exchange.\nIf the identifier you want to share is not a ticker or one of the other standardized fields, define a property that makes it clear what the value represents. Doing so will make interpretation easier for the developers of target applications.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the instrument\n\n</details>\n\n<details>\n  <summary><code>market</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>MIC</code></summary>\n\n**type**: `string`\n\nhttps://en.wikipedia.org/wiki/Market_Identifier_Code\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nHuman readable market name\n\n</details>\n\n<details>\n  <summary><code>COUNTRY_ISOALPHA2</code></summary>\n\n**type**: `string`\n\nhttps://www.iso.org/iso-3166-country-codes.html\n\n</details>\n\n<details>\n  <summary><code>BBG</code></summary>\n\n**type**: `string`\n\nhttps://www.bloomberg.com/\n\n</details>\n\nThe `market` map can be used to further specify the instrument and help achieve interoperability between disparate data sources. This is especially useful when using an `id` field that is not globally unique.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.instrument\",\n  \"name\": \"Microsoft\",\n  \"id\": {\n    \"ticker\": \"MSFT\",\n    \"RIC\": \"MSFT.OQ\",\n    \"ISIN\": \"US5949181045\"\n  },\n  \"market\": {\n    \"MIC\": \"XNAS\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/InstrumentList.md",
    "content": "---\ntitle: InstrumentList\nsidebar_label: InstrumentList\n\n---\n\n# InstrumentList\n\nA collection of instruments. Use this type for use cases that require not just a single instrument, but multiple (e.g. to populate a watchlist). However, when holding information for each instrument is required, it is recommended to use the [Portfolio](Portfolio) type.\n\nThe instrument list schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/instrumentList.schema.json](pathname:///schemas/2.2/context/instrumentList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/instrumentList.schema.json))\n\n## Type\n\n`fdc3.instrumentList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the instrument list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the instrument list\n\n</details>\n\n<details>\n  <summary><code>instruments</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Instrument](Instrument)\n\n</details>\n\nAn array of instrument contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.instrumentList\",\n  \"instruments\": [\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"AAPL\"\n      },\n      \"market\": {\n        \"MIC\": \"XNAS\"\n      }\n    },\n    {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ISIN\": \"US5949181045\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Interaction.md",
    "content": "---\ntitle: Interaction\nsidebar_label: Interaction\n\n---\n\n# Interaction\n\nAn `Interaction` is a significant direct exchange of ideas or information between a number of participants, e.g. a Sell Side party and one or more Buy Side parties. An `Interaction` might be a call, a meeting (physical or virtual), an IM or the preparation of some specialist data, such as financial data for a given company or sector.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/interaction.schema.json](pathname:///schemas/2.2/context/interaction.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/interaction.schema.json))\n\n## Type\n\n`fdc3.interaction`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>URI</code></summary>\n\n**type**: `string`\n\nCan be used by a target application to pass a record's link back to the originating application. This offers the originating application a way to open the record for a user to view.\n\n</details>\n\n<details>\n  <summary><code>SALESFORCE</code></summary>\n\n**type**: `string`\n\nInteractions ID in Salesforce\n\n</details>\n\n<details>\n  <summary><code>SINGLETRACK</code></summary>\n\n**type**: `string`\n\nInteraction ID in SingleTrack\n\n</details>\n\nCan be used by a target application to pass an identifier back to the originating application after an interaction record has been created, updated or deleted. An interaction ID does not need to be populated by the originating application, however the target application could store it for future reference and SHOULD return it in a `TransactionResult`.\n\n</details>\n\n<details>\n  <summary><code>participants</code> <strong>(required)</strong></summary>\n\n**type**: [ContactList](ContactList)\n\nA list of contacts involved in the interaction\n\n</details>\n\n<details>\n  <summary><code>timeRange</code> <strong>(required)</strong></summary>\n\n**type**: [TimeRange](TimeRange)\n\nThe time range over which the interaction occurred\n\n</details>\n\n<details>\n  <summary><code>interactionType</code> <strong>(required)</strong></summary>\n\n**Any of:**\n\n- **type**: `string` with values:\n- `Instant Message`,\n- `Email`,\n- `Call`,\n- `Meeting`\n- **type**: `string`\n\n`interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or `'Meeting'` although other string values are permitted.\n\n</details>\n\n<details>\n  <summary><code>description</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nA human-readable description of the interaction\n\n</details>\n\n<details>\n  <summary><code>initiator</code></summary>\n\n**type**: [Contact](Contact)\n\nThe contact that initiated the interaction\n\n</details>\n\n<details>\n  <summary><code>origin</code></summary>\n\n**type**: `string`\n\nUsed to represent the application or service that the interaction was created from to aid in tracing the source of an interaction.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.interaction\",\n  \"participants\": {\n    \"type\": \"fdc3.contactList\",\n    \"contacts\": [\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"Jane Doe\",\n        \"id\": {\n          \"email\": \"jane.doe@mail.com\"\n        }\n      },\n      {\n        \"type\": \"fdc3.contact\",\n        \"name\": \"John Doe\",\n        \"id\": {\n          \"email\": \"john.doe@mail.com\"\n        }\n      }\n    ]\n  },\n  \"interactionType\": \"Instant Message\",\n  \"timeRange\": {\n    \"type\": \"fdc3.timeRange\",\n    \"startTime\": \"2022-02-10T15:12:00Z\"\n  },\n  \"description\": \"Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum\",\n  \"initiator\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@mail.com\"\n    }\n  },\n  \"origin\": \"Outlook\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Message.md",
    "content": "---\ntitle: Message\nsidebar_label: Message\n\n---\n\n# Message\n\nA chat message to be sent through an instant messaging application. Can contain one or several text bodies (organized by mime-type, plaintext or markdown), as well as attached entities (either arbitrary file attachments or FDC3 actions to be embedded in the message). To be put inside a ChatInitSettings object.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/message.schema.json](pathname:///schemas/2.2/context/message.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/message.schema.json))\n\n## Type\n\n`fdc3.message`\n\n## Properties\n\n<details>\n  <summary><code>text</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>text/plain</code></summary>\n\n**type**: `string`\n\nPlain text encoded content.\n\n</details>\n\n<details>\n  <summary><code>text/markdown</code></summary>\n\n**type**: `string`\n\nMarkdown encoded content\n\n</details>\n\nA map of string mime-type to string content\n\n</details>\n\n<details>\n  <summary><code>entities</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**One of:**\n\n- **type**: [Action](Action)\n- **type**: [File Attachment](FileAttachment)\n\n</details>\n\nA map of string IDs to entities that should be attached to the message, such as an action to perform, a file attachment, or other FDC3 context object.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.message\",\n  \"text\": {\n    \"text/plain\": \"Hey all, can we discuss the issue together? I attached a screenshot and a link to the current exchange rate\"\n  },\n  \"entities\": {\n    \"picture1\": {\n      \"type\": \"fdc3.fileAttachment\",\n      \"data\": {\n        \"name\": \"myImage.png\",\n        \"dataUri\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\"\n      }\n    },\n    \"eurusd_action\": {\n      \"type\": \"fdc3.action\",\n      \"title\": \"Click to view Chart\",\n      \"intent\": \"ViewChart\",\n      \"context\": {\n        \"type\": \"fdc3.chart\",\n        \"instruments\": [\n          {\n            \"type\": \"fdc3.instrument\",\n            \"id\": {\n              \"ticker\": \"EURUSD\"\n            }\n          }\n        ],\n        \"range\": {\n          \"type\": \"fdc3.dateRange\",\n          \"starttime\": \"2020-09-01T08:00:00.000Z\",\n          \"endtime\": \"2020-10-31T08:00:00.000Z\"\n        },\n        \"style\": \"candle\"\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Nothing.md",
    "content": "---\ntitle: Nothing\nsidebar_label: Nothing\n\n---\n\n# Nothing\n\nA type that explicitly represents a lack of context.\n\nNotes:\n\n- Intended to be used in situations where no context is desired.\n- For example:\n  - Raising an intent without context (e.g. opening a blank order form, or chat interface without a contact selected).\n  - Resetting context on a channel (e.g. when context is used to set a filter in other applications a null context might release the filter).\n- An explicit representation of a Null or empty context allows apps to declare support for a lack of context, for example in their intent metadata in an app directory.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/nothing.schema.json](pathname:///schemas/2.2/context/nothing.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/nothing.schema.json))\n\n## Type\n\n`fdc3.nothing`\n\n## Properties\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.nothing\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Order.md",
    "content": "---\ntitle: Order\nsidebar_label: Order\n\n---\n\n# Order\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing an order. To be used with OMS and EMS systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the order in one or more systems, an optional human readable `name` field to be used to summarize the order and an optional `details` field that may be used to provide additional detail about the order, including a context representing a `product`, which may be extended with arbitrary properties. The `details.product` field is currently typed as a unspecified Context type, but both `details` and `details.product` are expected to be standardized in future.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/order.schema.json](pathname:///schemas/2.2/context/order.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/order.schema.json))\n\n## Type\n\n`fdc3.order`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the order in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the order.\n\n</details>\n\n<details>\n  <summary><code>details</code></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>product</code></summary>\n\n**type**: [Product](Product)\n\n</details>\n\nOptional additional details about the order, which may include a product element that is an, as yet undefined but extensible, Context\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.order\",\n  \"name\": \"...\",\n  \"id\": {\n    \"myOMS\": \"12345\"\n  },\n  \"details\": {\n    \"product\": {\n      \"type\": \"fdc3.product\",\n      \"id\": {\n        \"productId\": \"ABC123\"\n      },\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"MSFT\"\n        }\n      }\n    }\n  }\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.order\",\n  \"id\": {\n    \"myOMS\": \"ABC123\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/OrderList.md",
    "content": "---\ntitle: OrderList\nsidebar_label: OrderList\n\n---\n\n# OrderList\n\n[@experimental](/docs/fdc3-compliance#experimental-features) A list of orders. Use this type for use cases that require not just a single order, but multiple.\n\nThe OrderList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/orderList.schema.json](pathname:///schemas/2.2/context/orderList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/orderList.schema.json))\n\n## Type\n\n`fdc3.orderList`\n\n## Properties\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the order list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable summary of the order list\n\n</details>\n\n<details>\n  <summary><code>orders</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Order](Order)\n\n</details>\n\nAn array of order contexts that forms the list.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.orderList\",\n  \"orders\": [\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"ABC123\"\n      }\n    },\n    {\n      \"type\": \"fdc3.order\",\n      \"id\": {\n        \"myOMS\": \"DEF456\"\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Organization.md",
    "content": "---\ntitle: Organization\nsidebar_label: Organization\n\n---\n\n# Organization\n\nAn entity that can be used when referencing private companies and other organizations where a specific instrument is not available or desired e.g. CRM and News workflows.\n\nIt is valid to include extra properties and metadata as part of the organization payload, but the minimum requirement is for at least one specified identifier to be provided.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/organization.schema.json](pathname:///schemas/2.2/context/organization.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/organization.schema.json))\n\n## Type\n\n`fdc3.organization`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n**Subproperties:**\n\n<details>\n  <summary><code>LEI</code></summary>\n\n**type**: `string`\n\nThe Legal Entity Identifier (LEI) is a 20-character, alpha-numeric code based on the ISO 17442 standard developed by the International Organization for Standardization (ISO). It connects to key reference information that enables clear and unique identification of legal entities participating in financial transactions.\n\n</details>\n\n<details>\n  <summary><code>PERMID</code></summary>\n\n**type**: `string`\n\nRefinitiv Permanent Identifiers, or PermID for the organization\n\n</details>\n\n<details>\n  <summary><code>FDS_ID</code></summary>\n\n**type**: `string`\n\nFactSet Permanent Identifier representing the organization\n\n</details>\n\nIdentifiers for the organization, at least one must be provided.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name of the organization\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.organization\",\n  \"name\": \"Cargill, Incorporated\",\n  \"id\": {\n    \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n    \"FDS_ID\": \"00161G-E\"\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Portfolio.md",
    "content": "---\ntitle: Portfolio\nsidebar_label: Portfolio\n\n---\n\n# Portfolio\n\nA financial portfolio made up of multiple positions (holdings) in several instruments. Contrast this with e.g. the [InstrumentList](InstrumentList) type, which is just a list of instruments.\n\nThis is a good example of how types can be composed and extended with extra properties to define more complex types.\n\nThe Portfolio type consists of an array of [Position](Position) types, each of which refers to a single [Instrument](Instrument) and a holding amount for that instrument.\n\nThe portfolio schema does not explicitly include identifiers in the `id` section, as there bis not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/portfolio.schema.json](pathname:///schemas/2.2/context/portfolio.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/portfolio.schema.json))\n\n## Type\n\n`fdc3.portfolio`\n\n## Properties\n\n<details>\n  <summary><code>positions</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Position](Position)\n\n</details>\n\nThe List of Positions which make up the Portfolio\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the portfolio in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the portfolio\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.portfolio\",\n  \"positions\": [\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"AAPL\"\n        }\n      },\n      \"holding\": 2000000\n    },\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"MSFT\"\n        }\n      },\n      \"holding\": 1500000\n    },\n    {\n      \"type\": \"fdc3.position\",\n      \"instrument\": {\n        \"type\": \"fdc3.instrument\",\n        \"id\": {\n          \"ticker\": \"IBM\"\n        }\n      },\n      \"holding\": 3000000\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Position.md",
    "content": "---\ntitle: Position\nsidebar_label: Position\n\n---\n\n# Position\n\nA financial position made up of an instrument and a holding in that instrument. This type is a good example of how new context types can be composed from existing types.\n\nIn this case, the instrument and the holding amount for that instrument are required values.\n\nThe [Position](Position) type goes hand-in-hand with the [Portfolio](Portfolio) type, which represents multiple holdings in a combination of instruments.\n\nThe position schema does not explicitly include identifiers in the `id` section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/position.schema.json](pathname:///schemas/2.2/context/position.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/position.schema.json))\n\n## Type\n\n`fdc3.position`\n\n## Properties\n\n<details>\n  <summary><code>instrument</code> <strong>(required)</strong></summary>\n\n**type**: [Instrument](Instrument)\n\n\n\n</details>\n\n<details>\n  <summary><code>holding</code> <strong>(required)</strong></summary>\n\n**type**: `number`\n\nThe amount of the holding, e.g. a number of shares\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the position in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the position\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.position\",\n  \"instrument\": {\n    \"type\": \"fdc3.instrument\",\n    \"id\": {\n      \"ticker\": \"AAPL\"\n    }\n  },\n  \"holding\": 2000000\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Product.md",
    "content": "---\ntitle: Product\nsidebar_label: Product\n\n---\n\n# Product\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing a tradable product. To be used with OMS and EMS systems.\n\nThis type is currently only loosely defined as an extensible context object, with an optional instrument field.\n\nThe Product schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/product.schema.json](pathname:///schemas/2.2/context/product.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/product.schema.json))\n\n## Type\n\n`fdc3.product`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the product. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nA human-readable summary of the product.\n\n</details>\n\n<details>\n  <summary><code>instrument</code></summary>\n\n**type**: [Instrument](Instrument)\n\nA financial instrument that relates to the definition of this product\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.product\",\n  \"id\": {\n    \"productId\": \"ABC123\"\n  },\n  \"instrument\": {\n    \"type\": \"fdc3.instrument\",\n    \"id\": {\n      \"ticker\": \"MSFT\"\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/TimeRange.md",
    "content": "---\ntitle: TimeRange\nsidebar_label: TimeRange\n\n---\n\n# TimeRange\n\nA context representing a period of time. Any user interfaces that represent or visualize events or activity over time can be filtered or focused on a particular time period, e.g.:\n\n- A pricing chart\n- A trade blotter\n- A record of client contact/activity in a CRM\n\nExample use cases:\n\n- User may want to view pricing/trades/customer activity for a security over a particular time period, the time range might be specified as the context for the `ViewChart` intent OR it might be embedded in another context (e.g. a context representing a chart to plot).\n- User filters a visualization (e.g. a pricing chart) to show a particular period, the `TimeRange` is broadcast and other visualizations (e.g. a heatmap of activity by instrument, or industry sector etc.) receive it and filter themselves to show data over the same range.\n\nNotes:\n\n- A `TimeRange` may be closed (i.e. `startTime` and `endTime` are both known) or open (i.e. only one of `startTime` or `endTime` is known).\n- Ranges corresponding to dates (e.g. `2022-05-12` to `2022-05-19`) should be specified using times as this prevents issues with timezone conversions and inclusive/exclusive date ranges.\n- String fields representing times are encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n  - A timezone indicator should be specified, e.g. `\"2022-05-12T15:18:03Z\"` or `\"2022-05-12T16:18:03+01:00\"`\n  - Times MAY be specified with millisecond precision, e.g. `\"2022-05-12T15:18:03.349Z\"`\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/timeRange.schema.json](pathname:///schemas/2.2/context/timeRange.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/timeRange.schema.json))\n\n## Type\n\n`fdc3.timeRange`\n\n## Properties\n\n<details>\n  <summary><code>startTime</code></summary>\n\n**type**: `string`\n\nThe start time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n\n</details>\n\n<details>\n  <summary><code>endTime</code></summary>\n\n**type**: `string`\n\nThe end time of the range, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator.\n\n</details>\n\n## Examples\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"startTime\": \"2022-03-30T15:44:44Z\",\n  \"endTime\": \"2022-04-30T23:59:59Z\"\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"startTime\": \"2022-03-30T15:44:44+00:00\"\n}\n```\n\n```json\n{\n  \"type\": \"fdc3.timeRange\",\n  \"endTime\": \"2022-03-30T16:44:44.123Z\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Trade.md",
    "content": "---\ntitle: Trade\nsidebar_label: Trade\n\n---\n\n# Trade\n\n[@experimental](/docs/fdc3-compliance#experimental-features) context type representing a trade. To be used with execution systems.\n\nThis type currently only defines a required `id` field, which should provide a reference to the trade in one or more systems, an optional human readable `name` field to be used to summarize the trade and a required `product` field that may be used to provide additional detail about the trade, which is currently typed as a unspecified Context type, but `product` is expected to be standardized in future.\n\n The Trade schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/trade.schema.json](pathname:///schemas/2.2/context/trade.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/trade.schema.json))\n\n## Type\n\n`fdc3.trade`\n\n## Properties\n\n<details>\n  <summary><code>id</code> <strong>(required)</strong></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the trade in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nA human-readable summary of the trade.\n\n</details>\n\n<details>\n  <summary><code>product</code> <strong>(required)</strong></summary>\n\n**type**: [Product](Product)\n\nA product that is the subject of the trade.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.trade\",\n  \"name\": \"...\",\n  \"id\": {\n    \"myEMS\": \"12345\"\n  },\n  \"product\": {\n    \"type\": \"fdc3.product\",\n    \"id\": {\n      \"productId\": \"ABC123\"\n    },\n    \"instrument\": {\n      \"type\": \"fdc3.instrument\",\n      \"id\": {\n        \"ticker\": \"MSFT\"\n      }\n    }\n  }\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/TradeList.md",
    "content": "---\ntitle: TradeList\nsidebar_label: TradeList\n\n---\n\n# TradeList\n\n[@experimental](/docs/fdc3-compliance#experimental-features) A list of trades. Use this type for use cases that require not just a single trade, but multiple.\n\nThe TradeList schema does not explicitly include identifiers in the id section, as there is not a common standard for such identifiers. Applications can, however, populate this part of the contract with custom identifiers if so desired.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/tradeList.schema.json](pathname:///schemas/2.2/context/tradeList.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/tradeList.schema.json))\n\n## Type\n\n`fdc3.tradeList`\n\n## Properties\n\n<details>\n  <summary><code>trades</code> <strong>(required)</strong></summary>\n\n**type**: `array`\n\n<details>\n  <summary><code>Items</code></summary>\n\n**type**: [Trade](Trade)\n\n</details>\n\nAn array of trade contexts that forms the list.\n\n</details>\n\n<details>\n  <summary><code>id</code></summary>\n\n**type**: `object`\n\n<details>\n  <summary><code>Additional Properties</code></summary>\n\n**type**: `string`\n\n</details>\n\nOne or more identifiers that refer to the trade list in an OMS, EMS or related system. Specific key names for systems are expected to be standardized in future.\n\n</details>\n\n<details>\n  <summary><code>name</code></summary>\n\n**type**: `string`\n\nAn optional human-readable name for the trade list\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.tradeList\",\n  \"trades\": [\n    {\n      \"type\": \"fdc3.trade\",\n      \"name\": \"...\",\n      \"id\": {\n        \"myEMS\": \"12345\"\n      },\n      \"product\": {\n        \"type\": \"fdc3.product\",\n        \"id\": {\n          \"productId\": \"ABC123\"\n        },\n        \"instrument\": {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"MSFT\"\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"fdc3.trade\",\n      \"id\": {\n        \"myEMS\": \"67890\"\n      },\n      \"product\": {\n        \"type\": \"fdc3.product\",\n        \"id\": {\n          \"productId\": \"DEF456\"\n        },\n        \"instrument\": {\n          \"type\": \"fdc3.instrument\",\n          \"id\": {\n            \"ticker\": \"TSLA\"\n          }\n        }\n      }\n    }\n  ]\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/TransactionResult.md",
    "content": "---\ntitle: TransactionResult\nsidebar_label: TransactionResult\n\n---\n\n# TransactionResult\n\nA context type representing the result of a transaction initiated via FDC3, which SHOULD be returned as an `IntentResult` by intents that create, retrieve, update or delete content or records in another application. Its purpose is to provide a status and message (where needed) for the transaction and MAY wrap a returned context object.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/transactionresult.schema.json](pathname:///schemas/2.2/context/transactionresult.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/transactionresult.schema.json))\n\n## Type\n\n`fdc3.transactionResult`\n\n## Properties\n\n<details>\n  <summary><code>status</code> <strong>(required)</strong></summary>\n\n**type**: `string` with values:\n- `Created`,\n- `Deleted`,\n- `Updated`,\n- `Failed`\n\nThe status of the transaction being reported.\n\n</details>\n\n<details>\n  <summary><code>context</code></summary>\n\n**type**: [Context](/docs/next/context/spec#the-context-interface)\n\n\nA context object returned by the transaction, possibly with updated data.\n\n</details>\n\n<details>\n  <summary><code>message</code></summary>\n\n**type**: `string`\n\nA human readable message describing the outcome of the transaction.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.transactionResult\",\n  \"status\": \"Updated\",\n  \"context\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@mail.com\"\n    }\n  },\n  \"message\": \"record with id 'jane.doe@mail.com' was updated\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/ref/Valuation.md",
    "content": "---\ntitle: Valuation\nsidebar_label: Valuation\n\n---\n\n# Valuation\n\nA context type representing the price and value of a holding.\n\n## Schema\n\n[https://fdc3.finos.org/schemas/2.2/context/valuation.schema.json](pathname:///schemas/2.2/context/valuation.schema.json) ([github](https://github.com/finos/FDC3/tree/main/packages/fdc3-context/schemas/context/valuation.schema.json))\n\n## Type\n\n`fdc3.valuation`\n\n## Properties\n\n<details>\n  <summary><code>value</code> <strong>(required)</strong></summary>\n\n**type**: `number`\n\nThe value of the holding, expresses in the nominated currency.\n\n</details>\n\n<details>\n  <summary><code>price</code></summary>\n\n**type**: `number`\n\nThe price per unit the the valuation is based on.\n\n</details>\n\n<details>\n  <summary><code>CURRENCY_ISOCODE</code> <strong>(required)</strong></summary>\n\n**type**: `string`\n\nThe valuation currency, which should conform to 3 character alphabetic codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html)\n\n</details>\n\n<details>\n  <summary><code>valuationTime</code></summary>\n\n**type**: `string`\n\nThe time at which the valuation was performed, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n</details>\n\n<details>\n  <summary><code>expiryTime</code></summary>\n\n**type**: `string`\n\nThe time at which this valuation expires, encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included.\n\n</details>\n\n## Example\n\n```json\n{\n  \"type\": \"fdc3.valuation\",\n  \"value\": 500,\n  \"price\": 5,\n  \"CURRENCY_ISOCODE\": \"USD\",\n  \"expiryTime\": \"2022-05-13T16:16:24+01:00\"\n}\n```\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/context/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Context Data (2.2)\n---\n\nTo interoperate, apps need to exchange commonly recognized context structures that can indicate topic with any number of identifiers or mappings to different systems. FDC3 Context Data defines a standard for passing common identifiers and data, encoded in JSON, between apps to create a seamless workflow. FDC3 Context Data is not a symbology solution and is not specifically focused on modeling financial objects. The focus is on providing a standard JSON payload structure that can be used to establish a lowest common denominator for interoperability.\n\nContext objects are used when raising [intents](../intents/spec) and when broadcasting context to other applications.\n\nThere are two main use cases for exchanging context data:\n\n- **Transmitting reference data between applications.**\n  The source application will send as many known identifiers as possible, and the target application will try to match the entity based on the identifiers. It may then choose to map to its own internal domain representation for rendering purposes.\n\n  An example of this is sending an instrument or contact, when only an ISIN or email is required to reference the same data in another application.\n\n- **Transferring information between applications.**\n  The source application may have data required to compose a workflow with another application, e.g. a list of contacts that have been selected, or a complex object representing an RFQ request.\n\n  In many such cases there aren't any sensible reference identifiers that can be shared, it is instead the data itself being transferred.\n\n## Assumptions\n\n1. Context data objects are identified and routed according to their type, which is unique.\n2. Any names, identifiers or extra properties are optional.\n3. More complex objects can be composed from simpler objects by defining a new type, e.g a position from an instrument and a holding amount.\n4. If multiple pieces of data need to be sent, an embedded array can be used, identified as a collection type, e.g. \"contactList\" or \"portfolio\". This allows for additional metadata and data relationships to be expressed.\n5. There needs to be a way to reference or look up the structure of well-known context types, e.g. from a directory.\n\n## Other Standards\n\nFDC3 recognizes that there are other object definitions for providing context between applications. Most, if not all of these definitions though are platform-specific. FDC3, as a rule, sets out to be platform-agnostic and focused on creating bridges between the various walled gardens on the financial desktop.\n\n### Context Schemas\n\nFDC3 Context data is primarily encoded in JSON, but may also be encoded in language specific formats for use with FDC3 API implementations in those languages, although it is advisable to ensure that they can be converted to and from JSON.\n\nEach Standardized context type defined by the FDC3 Standard has an associated [JSON Schema](https://json-schema.org/) definition that should be considered the 'source of truth' for the context definition, although examples in documentation may also be given in TypeScript or JavaScript. The TypeScript definitions distributed in the FDC3 NPM module are generated from the JSON Schema files using [quicktype](https://quicktype.io/). Both documentation for fields defined (in the form of a `title` and `description` entry for each field defined) and examples SHOULD be included in JSON Schema definitions for Context types to ensure that the schema file can serve as a single source of truth, and that code generated from the schema files can also include that documentation.\n\n## The Context Interface\n\nThe Context interface defines the basic contract or \"shape\" for all data exchanged by FDC3 operations. As such, it is not meant to be used on its own, but is imported by more specific type definitions (standardized or custom) to provide the structure and properties shared by all FDC3 context data types.\n\nThe Context interface can be summarized as:\n\n- Having a unique _type_ identifier, used for routing.\n- Optionally providing a name.\n- Optionally providing a map of equivalent identifiers.\n- Any other properties or metadata.\n\nThe key element of FDC3 context types is their mandatory `type` property, which is used to identify what type of data the\nobject represents, and what shape it has. The FDC3 context type, and all derived types, define the minimum set of fields a context data object of a particular type can be expected to have, but this can always be extended with custom fields as appropriate.\n\nHence, the Context interface can be represented in TypeScript as:\n\n```typescript\ninterface Context {\n    type: string;\n    name?: string;\n    id?: {\n        [x:string]: string;\n    },\n    [x: string]: any;\n}\n```\n\nor in JSON Schema as:\n\n```json\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"https://fdc3.finos.org/schemas/2.2/context/context.schema.json\",\n    \"type\": \"object\",\n    \"title\": \"Context\",\n    \"description\": \"The `fdc3.context` type defines the basic contract for all data exchanged by FDC3 operations.\",\n    \"properties\": {\n        \"type\": {\n            \"type\": \"string\"\n        },\n        \"name\": {\n            \"type\": \"string\"\n        },\n        \"id\": {\n            \"type\": \"object\",\n            \"unevaluatedProperties\": {\n                \"type\": \"string\"\n            }\n        }\n    },\n    \"additionalProperties\": true,\n    \"required\": [\n        \"type\"\n    ]\n}\n```\n\n:::note\n\nThis is a simplified version of the schema for illustrative purposes, the fully documented Context schema, which is composed with other FDC3 Standard context schemas, can be found at: [https://fdc3.finos.org/schemas/2.2/context/context.schema.json](pathname:///schemas/2.2/context/context.schema.json).\n\n:::\n\n### `type`\n\nThe type property is the only _required_ part of the FDC3 context data schema. The FDC3 [API](../api/spec) relies on the `type` property being present to route shared context data appropriately.\n\nFDC3 [Intents](../intents/spec) also register the context data types they support in an FDC3 [App Directory](../app-directory/overview), used for intent discovery and routing.\n\nStandardized FDC3 context types have well-known `type` properties prefixed with the `fdc3` namespace, e.g. `fdc3.instrument`.\nFor non-standard types, e.g. those defined and used by a particular organization, the convention is to prefix them with an\norganization-specific namespace, e.g. `blackrock.fund`.\n\n#### Namespacing\n\nAll well-known types at FDC3 level are prefixed with `fdc3`. For private type definitions, or type definitions issued by other organizations, different namespaces MUST be used, e.g. `blackrock.fund`, etc.\n\n### `name`\n\nContext data objects may include an optional name property that can be used for more information, or display purposes. Some\nderived types may require the name object as mandatory, depending on use case.\n\n### `id`\n\nContext data objects may include a set of equivalent key-value pairs in the `id` property that can be used to help applications identify and look up the context type they receive in their own domain. The idea behind this design is that applications can provide as many equivalent identifiers to a target application as possible, e.g. an instrument may be represented by an ISIN, CUSIP or Bloomberg identifier.\n\nIdentifiers do not make sense for all types of data, so the `id` property is therefore optional, but some derived types choose to require at least one identifier.\n\nWhere an identifier is the name of an existing standard, external to FDC3, it is represented in all caps. For example: FIGI, PERMID, CUSIP, ISO-2. When an identifier is a more general concept, it is represented in all lower case.  For example: ticker, name, geocode, email.\n\nIdentifier values SHOULD always be of type string.\n\nAll standard identifier names are reserved names. Applications may use their own identifiers ad hoc. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"foo\":\"bar\"\n}\n```\n\nThe identifier \"foo\" is proprietary, an application that can use it is free to do so. However, since multiple applications may want to use the \"foo\" name and may use it to mean different things, there is a need for applications to ensure that their identifiers use naming conventions that will avoid collision. The recommended approach here is to prefix the identifier name with a namespace. For example:\n\n```json\n\"id\": {\n    \"CUSIP\":\"037833100\",\n    \"com.company.foo\": \"000C7F-E\"\n}\n```\n\n### Avoid union types / composition of primitive types\n\nBoth Typescript and JSON Schema allow for a type of polymorphism in types and interfaces that is hard to represent in other languages: allowing the type of a variable to be a ['union'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of other, unrelated types. E.g.: in TypeScript\n\n```ts\ntype Example = SomeOtherType | YetAnotherType;\n```\n\nSimilar constructs are allowed in JSON Schema by [combining or composing schemas](https://json-schema.org/understanding-json-schema/reference/combining) using the `anyOf` or `oneOf` keywords to specify that a value can take the form defined in one-or-more or one-of-several sub-schemas.\n\n```json\n\"recipients\": {\n    \"title\": \"Email Recipients\",\n    \"description\": \"One or more recipients for the email.\",\n    \"oneOf\": [\n        {\n            \"$ref\": \"contact.schema.json#\"\n        },\n        {\n            \"$ref\": \"contactList.schema.json#\"\n        }\n    ]\n}\n```\n\nHowever, other languages can be less flexible. In most languages, polymorphism of object types is possible via the implementation and/or extension of an interface (for example all context types are derived from the [Context](ref/Context) schema, which can be modelled as an interface). However, this approach is not possible if one of the types in the union is a primitive, meaning it's not a class and can't be modified to implement an interface, e.g.:\n\n```ts\ntype Example2 = SomeOtherType | number;\n```\n\nHence, to ensure that FDC3 context objects are implementable in other languages context schemas MUST NOT use `anyOf`/`oneOf` compositions of primitive types in JSON schema (and, hence, unions of primitive types in TypeScript) and SHOULD avoid compositions of Object types unless a concept that can be defined as an interface (such as [Context](ref/Context)) is available.\n\n### Other Field Type Conventions\n\nThis Standard defines a number of conventions for the fields of context types that all context objects SHOULD adhere to in order to reduce or prevent competing conventions from being established in both standardized types and proprietary types created by app developers.\n\n#### Times\n\nFields representing a point in time SHOULD be string encoded according to [ISO 8601-1:2019](https://www.iso.org/standard/70907.html) with a timezone indicator included, e.g.:\n\n- Time in UTC: `\"2022-03-30T15:44:44Z\"`\n- Also time in UTC: `\"2022-03-30T15:44:44+00:00\"`\n- Same time in EDT: `\"2022-03-30T11:44:44-04:00\"`\n\nTimes MAY be expressed with millisecond precision, e.g.:\n\n- `\"2022-03-30T11:44:44.123-04:00\"`\n- `\"2022-03-30T11:44:44.123Z\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30T11:44:44.123-04:00\")\n```\n\n#### Dates\n\nFields representing a point in time SHOULD be string encoded using the `YYYY-MM-DD` date format from [ISO 8601-1:2019](https://www.iso.org/standard/70907.html).\n\nE.g. `\"2022-03-30\"`\n\nParsing in JavaScript:\n\n```javascript\nlet aDate = new Date(\"2022-03-30\")\n```\n\n#### Country codes\n\nFields representing a country SHOULD be string encoded using the Alpha-2-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) and field name `COUNTRY_ISOALPHA2`. The Alpha-3-codes from [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) MAY be used in addition to the Alpha-2-code with the field name `COUNTRY_ISOALPHA3`.\n\nE.g. `\"COUNTRY_ISOALPHA2\": \"GB\"`\n\n#### Currency codes\n\nFields representing a currency SHOULD be string encoded using the Alphabetic code from [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) with the field name `CURRENCY_ISOCODE`.\n\nE.g. `\"CURRENCY_ISOCODE\": \"GBP\"`\n\n:::note\nISO 4217 only includes major currency codes, conversions to minor currencies is the responsibility of the consuming system (where required).\n:::\n\n## Context Data Standard Compliance\n\nAn FDC3 Standard compliant application that supports the use of context data **MUST**:\n\n- Ensure that any FDC3-defined standard context types used meet the interface defined for that type of context data.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers.\n- Where App or Private channels are supported, use the [`Channel.addContextListener`](../api/ref/Channel#addcontextlistener) API call to set up appropriate handlers.\n\nAn FDC3 Standard compliant application that supports the use of context data **SHOULD**:\n\n- Prefer FDC3-defined standard context types over proprietary contexts, where a suitable FDC3-defined standard context type is available.\n- Ensure that any proprietary context data types defined follow any the recommended [namespacing](#namespacing) and [field type conventions](spec#other-field-type-conventions) in the specification.\n- Where an app is intended to receive context from [`fdc3.open`](../api/ref/DesktopAgent#open) calls, use the [`fdc3.addContextListener`](../api/ref/DesktopAgent#addcontextlistener) API call to set up appropriate handlers within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n\nAn FDC3 Standard compliant application that supports the use of context data **MAY**:\n\n- Define proprietary context data types to support use cases not currently supported via FDC3-defined standard context types.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Context Types\n\nThe following are standard FDC3 context types:\n\n- [`fdc3.action`](ref/Action) ([schema](pathname:///schemas/2.2/context/action.schema.json))\n- [`fdc3.chart`](ref/Chart) ([schema](pathname:///schemas/2.2/context/chart.schema.json))\n- [`fdc3.chat.initSettings`](ref/ChatInitSettings) ([schema](pathname:///schemas/2.2/context/chatInitSettings.schema.json))\n- [`fdc3.chat.message`](ref/ChatMessage) ([schema](pathname:///schemas/2.2/context/chatMessage.schema.json))\n- [`fdc3.chat.room`](ref/ChatRoom) ([schema](pathname:///schemas/2.2/context/chatRoom.schema.json))\n- [`fdc3.chat.searchCriteria`](ref/ChatSearchCriteria) ([schema](pathname:///schemas/2.2/context/chatSearchCriteria.schema.json))\n- [`fdc3.contact`](ref/Contact) ([schema](pathname:///schemas/2.2/context/contact.schema.json))\n- [`fdc3.contactList`](ref/ContactList) ([schema](pathname:///schemas/2.2/context/contactList.schema.json))\n- [`fdc3.country`](ref/Country) ([schema](pathname:///schemas/2.2/context/country.schema.json))\n- [`fdc3.currency`](ref/Currency) ([schema](pathname:///schemas/2.2/context/currency.schema.json))\n- [`fdc3.email`](ref/Email) ([schema](pathname:///schemas/2.2/context/email.schema.json))\n- [`fdc3.instrument`](ref/Instrument) ([schema](pathname:///schemas/2.2/context/instrument.schema.json))\n- [`fdc3.instrumentList`](ref/InstrumentList) ([schema](pathname:///schemas/2.2/context/instrumentList.schema.json))\n- [`fdc3.interaction`](ref/Interaction) ([schema](pathname:///schemas/2.2/context/interaction.schema.json))\n- [`fdc3.message`](ref/Message) ([schema](pathname:///schemas/2.2/context/message.schema.json))\n- [`fdc3.organization`](ref/Organization) ([schema](pathname:///schemas/2.2/context/organization.schema.json))\n- [`fdc3.portfolio`](ref/Portfolio) ([schema](pathname:///schemas/2.2/context/portfolio.schema.json))\n- [`fdc3.position`](ref/Position) ([schema](pathname:///schemas/2.2/context/position.schema.json))\n- [`fdc3.nothing`](ref/Nothing) ([schema](pathname:///schemas/2.2/context/nothing.schema.json))\n- [`fdc3.timeRange`](ref/TimeRange) ([schema](pathname:///schemas/2.2/context/timeRange.schema.json))\n- [`fdc3.transactionResult`](ref/TransactionResult) ([schema](pathname:///schemas/2.2/context/transactionresult.schema.json))\n- [`fdc3.valuation`](ref/Valuation) ([schema](pathname:///schemas/2.2/context/valuation.schema.json))\n\nThe following are [`@experimental`](/docs/fdc3-compliance#experimental-features) types, which are in the process of being defined:\n\n- [`fdc3.order`](ref/Order) ([schema](pathname:///schemas/2.2/context/order.schema.json))\n- [`fdc3.orderList`](ref/OrderList) ([schema](pathname:///schemas/2.2/context/orderList.schema.json))\n- [`fdc3.product`](ref/Product) ([schema](pathname:///schemas/2.2/context/product.schema.json))\n- [`fdc3.trade`](ref/Trade) ([schema](pathname:///schemas/2.2/context/trade.schema.json))\n- [`fdc3.tradeList`](ref/TradeList) ([schema](pathname:///schemas/2.2/context/tradeList.schema.json))\n\n### Examples\n\nThe below examples show how the base context data interface can be used to define specific context data objects.\n\n#### Contact\n\n```json\n{\n    \"type\": \"fdc3.contact\",\n    \"name\": \"John Smith\",\n    \"id\":{\n        \"email\": \"john.smith@company.com\",\n    }\n}\n```\n\n#### Email\n\n```json\n{\n  \"type\": \"fdc3.email\",\n  \"recipients\": {\n    \"type\": \"fdc3.contact\",\n    \"name\": \"Jane Doe\",\n    \"id\": {\n      \"email\": \"jane.doe@example.com\"\n    }\n  },\n  \"subject\": \"The information you requested\",\n  \"textBody\": \"Blah, blah, blah ...\"\n}\n```\n\n#### Instrument\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\",\n        \"FIGI\" : \"BBG000B9XRY4\",\n    }\n}\n```\n\n#### TypeScript definition\n\nThe `Instrument` type is derived from the `Context` type (note that the name becomes a required field, the type is fixed and optional `id` subfields are defined):\n\n```typescript\ninterface Instrument extends Context {\n    type: 'fdc3.instrument',\n    name: string;\n    id: {\n        ticker?: string;\n        ISIN?: string;\n        CUSIP?: string;\n    }\n}\n```\n\ne.g. as a JSON payload:\n\n```json\n{\n    \"type\" : \"fdc3.instrument\",\n    \"name\" : \"Apple\",\n    \"id\" :\n    {\n        \"ticker\" : \"aapl\",\n        \"ISIN\" : \"US0378331005\",\n        \"CUSIP\" : \"037833100\"\n    },\n}\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/fdc3-charter.md",
    "content": "---\nid: fdc3-charter\ntitle: FDC3 Charter\n---\n\n## Scope\n\nThe FDC3 Standard specifies protocols and taxonomies to enable applications in financial services workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements between app developers.\n\nFinancial applications include any type of application used in common financial workflows, including:\n\n- Containerized Web applications - Interoperability platforms extending Chromium (e.g. Electron, OpenFin, interop.io's io.Connect)\n- PWAs & Web applications running in a commercial browser\n- Traditional native applications implemented in C++, .NET, Java, Python, etc.\n- Hybrid web/native applications - stand alone native apps embedding a WebView (e.g. Electron, CEF, WebView2, NW.js etc.)\n- Common desktop applications not specific to finance, but critical to workflows - such as Excel, Outlook, Slack, etc.\n\nThis standards group is focused specifically on establishing and promoting standards for the interoperability of front-end applications, hence, its activities are focused on:\n\n- The discovery, configuration, identity and use of financial services applications (e.g. the FDC3 [App Directory](https://fdc3.finos.org/docs/app-directory/overview)),\n- APIs for communication and interaction between applications (e.g. the [Desktop Agent API](https://fdc3.finos.org/docs/api/spec) and [Agent Bridging API](https://fdc3.finos.org/docs/agent-bridging/spec)),\n- Message formats used for communication (e.g. [Context Data](https://fdc3.finos.org/docs/context/spec))\n- Names for requested functionality and workflow steps (e.g. [Intents](https://fdc3.finos.org/docs/intents/spec))\n- Creating and promoting tests for conformance to these standards (e.g. the FDC3 Conformance Framework) and training & certification programs that relate to them (e.g. [Introduction to FDC3](https://training.linuxfoundation.org/express-learning/introduction-to-fdc3-lfel1000/))\n\nThe group's activities do not include:\n\n- Interoperability or communication between back-end platforms.\n- Defining financial objects - where existing standards are well established and can be reused.\n\n## Licensing\n\n- Version 1.0 of the FDC3 specification is licensed under the [FDC3 1.0 Final Specification License](https://github.com/finos/FDC3/blob/17892008c26a73ff1fd9f6e40ceb8c8bfd58c610/PATENTS-FDC3-1.0.md).\n\n- Versions 1.1 - 2.1 of the FDC3 specification are subject to the [FINOS IP Policy](https://github.com/finos/community/blob/fdd059c93b6ceefadd8cf60c4bef995366695337/website/static/governance-docs/IP-Policy.pdf), which authorizes implementation of FDC3 specifications without charge, on a RAND basis, subject to the terms of the policy. For details of the IP commitments made by contributors to FDC3, please refer to the policy.\n\n- Versions of the FDC3 specification following 2.1 and subsequent draft specifications are licensed under the [Community Specification License 1.0](https://github.com/finos/FDC3/blob/4ce90d45ca8e0c4f8f2c5bd73f51304278783d87/LICENSE.md)\n\n- All code in the FDC3 specification (including JSON Schema) are licensed under [Apache 2.0](https://github.com/finos/FDC3/blob/main/LICENSE)\n\n### Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/fdc3-compliance.md",
    "content": "---\nid: fdc3-compliance\ntitle: Compliance\n---\n\nFDC3 standards follow the IETF best practices for keywords to Indicate Requirement levels: [RFC 2119](https://tools.ietf.org/html/rfc2119).  Documentation should be updated as needed to reflect this.\n\nIn general, the ratified FDC3 specs represent a lowest common denominator interface for interoperability. So, unless a particular item in a spec is marked with keywords such as OPTIONAL, MAY, SHOULD, or SHOULD NOT, it should be treated as REQUIRED.  Since FDC3 itself is primarily concerned with establishing the baseline requirements for interoperation, this is consistent with the IETF Guidance:\n\n>6. **Guidance in the use of these Imperatives**\n>\n>    Imperatives of the type defined in this memo must be used with care\n>    and sparingly.  In particular, they MUST only be used where it is\n>    actually required for interoperation or to limit behavior which has\n>    potential for causing harm (e.g., limiting retransmissions)  For\n>    example, they must not be used to try to impose a particular method\n>    on implementors where the method is not required for\n>    interoperability.\n\nThese rules would apply only to standards work within FDC3. Today, this covers the API, App Directory, Context Data, and Intents specifications.\n\n## Personas\n\nFDC3 implementors generally fall into 2 categories: platform providers, and application providers. A platform provider supplies an implementation(s) of the FDC3 APIs (The Desktop Agent API and Application Directory) for applications to use.\n\nAn application provider is largely a downstream consumer of FDC3 standards. It MAY use the API, it MAY use Context Data, it MAY use Intents. Application providers are only required to comply with the standards they make use of.\n\nDepending on persona, implementation compliance with FDC3 will mean different things.\n\n### Platform Provider\n\nFor platform providers FDC3 compliance requires that they meet the requirements of the APIs that they implement:\n\n- [Desktop Agent API compliance requirements](api/spec#desktop-agent-api-standard-compliance).\n- [App Directory compliance requirements](app-directory/spec#app-directory-standard-compliance).\n\n### Application Provider\n\nFor application providers FDC3 compliance requires that they interact with the FDC3 APIs as intended and meet the requirements of the Intents and Context Data Standards. Specifically:\n\n- [Intents Standard compliance requirements](intents/spec#intents-standard-compliance)\n- [Context Data Standard compliance requirements](context/spec#context-data-standard-compliance)\n\n## Versioning\n\nTypically, a Standard that has marketplace relevance is revised from time to time, to correct errors and/or to add functionality to support new use cases. Hence, there exist multiple versions of the standard. As FDC3 is a standards project, we don't follow semver, which is meant for libraries. We use the versioning scheme `<major>.<minor>`, e.g. `1.1` or `2.3`.\n\n## Deprecation Policy\n\nOver time, it is not uncommon for certain things in a standard to be marked for removal in a future version, possibly being replaced by an alternative. That is, they are deprecated. Often, they are retained in the standard because of their widespread use, but their use in new projects is discouraged.\n\nFDC3 adopts the following deprecation policy:\n\n1. A feature can be deprecated by any major or minor version. Newly deprecated features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n2. A feature shall only be removed by a major version. Newly removed features will be described in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n3. Deprecated features are clearly marked with an `@deprecated` tag and comment in both the documentation and jsDocs applied to the TypeScript sources.\n4. Where possible, changes to the behavior of an existing feature should be avoided; consider deprecating it and replacing it with something with a different name/syntax.\n5. Breaking change should only be made in a major version of the Standard.\n\n## Experimental Features\n\nOccasionally, a change to FDC3 may be proposed where the design is tentative, and because of this, we need feedback from the community to finalize its inclusion in the Standard. In such cases, a feature may be designated as _experimental_ to indicate that its design may change in future and that it is exempted from the normal versioning and deprecation polices in order to facilitate that change.  However, designating a feature as experimental is likely to reduce its uptake by the community, hence, this designation should be used sparingly.\n\nFDC3 adopts the following experimental features policy:\n\n1. A feature may be designated as experimental where feedback is needed to confirm the final design of that feature, with the goal of including it as a full part of the Standard without the experimental label.\n2. A feature should only be designated as experimental where there is a reasonable chance that breaking changes to its design may be applied, based on feedback received; non-breaking changes (refinements) may already be applied to features defined in the Standard without the experimental designation.\n3. Experimental features are clearly marked with an `@experimental` tag and comment in both the documentation and docs applied to the TypeScript sources.\n4. Unless otherwise stated, experimental features should be considered optional for compliance purposes, but recommended for implementation (i.e. the SHOULD keyword is implied).\n5. Experimental features are exempted from the normal versioning and deprecation policies that govern changes to FDC3. I.e. breaking changes may be made to experimental features between versions of the Standard without a major version release.\n6. The experimental designation may be removed from a feature in a minor version release (as this will be considered an additive change).\n\n## Conformance testing\n\nThe FDC3 Standards include a set of [definitions for conformance tests](api/conformance/Conformance-Overview) that may be used to determine if a Desktop Agent API implementation conforms to a particular Standard version, to help disambiguate complex parts of the FDC3 Standard and to enable test-driven development of a Desktop Agent implementation.\n\nThe current set of tests focus on the Desktop Agent API and the interface to it. Tests are not yet defined for the App Directory API or Bridging API Parts of the FDC3 Standard, hence, conformance to those parts of the Standard must be determined manually.\n\nThe FDC3 Conformance tests are implemented for JavaScript/TypeScript web applications by the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework). Desktop Agent implementors working with web interfaces (Desktop Agent Preload or Desktop Agent Proxy) can clone the conformance framework and run the tests locally to determine if their agent is compliant with the Standard.\n\nOnce a Desktop Agent has passed the conformance tests locally, its authors can [apply for a formal certification of compliance with the Standard from FINOS](https://github.com/finos/FDC3-conformance-framework/blob/main/instructions.md). Please note the [Terms and Conditions](https://github.com/finos/FDC3-conformance-framework/blob/main/terms-conditions/FDC3-Certified-Terms.md) of the Conformance Program.\n\nimport badge_12 from '/img/community/certified-1.2.png';\nimport badge_20 from '/img/community/certified-2.0.png';\n\n<img src={badge_12} alt=\"Certified conformant with FDC3 1.2 badge\" style={{width: 200}} />\n<img src={badge_20} alt=\"Certified conformant with FDC3 2.0 badge\" style={{width: 200}} />\n\n## Intellectual Property Claims\n\nRecipients of this document are requested to submit, with their comments, notification of\nany relevant patent claims or other intellectual property rights of which they may be aware that\nmight be infringed by any implementation of the standard set forth in this document, and to provide\nsupporting documentation.\n\nTHIS STANDARD IS BEING OFFERED WITHOUT ANY WARRANTY\nWHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NON-INFRINGEMENT IS\nEXPRESSLY DISCLAIMED. ANY USE OF THIS STANDARD SHALL BE MADE\nENTIRELY AT THE IMPLEMENTER'S OWN RISK, AND NEITHER THE FOUNDATION,\nNOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY\nWHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF\nANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE\nOF THIS STANDARD.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/fdc3-glossary.md",
    "content": "---\nid: fdc3-glossary\ntitle: Glossary of Terms\nsidebar_label: Glossary\n---\n\nFor the purposes of this Standard, the following definitions apply. Other terms are defined when first used, at which place they appear in bold and italic type. Terms explicitly defined in this Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined are assumed to be well-known in the financial services or software industries.\n\n- **Agent Bridge**: Shorthand for Desktop Agent Bridge.\n- **app**: Shorthand for application.\n- **app directory**: A repository of application metadata supporting discovery, for example via name or intent, and retrieval of metadata necessary to launch an application.\n- **app directory record**: Metadata relating to a single application, encoded in JSON.\n- **appD**: Shorthand for app directory.\n- **appD record**: Shorthand for app directory record.\n- **application**: Any endpoint on the desktop that is registered with/known by a Desktop Agent, launchable by a Desktop Agent, addressable by a Desktop Agent or otherwise able to interact with the Desktop Agent.\n- **application, hybrid**: Any web application running within the context of a standalone native application that embeds a web view, typically based on Chromium.\n- **application, native**: A non-web-based application; i.e., one that runs outside the context of web browser, web view or web container. A user-written program, typically implemented in a language such as C++, C#, Java, or Python, rather than JavaScript or TypeScript.\n- **application, web**: An application written in TypeScript or JavaScript, HTML and CSS, which runs within the context of a web browser or a web container.\n- **Application Provider**: A downstream consumer of FDC3 Standards that can understand and use the FDC3 API (supplied by a Platform Provider), context data, and/or intents.\n- **application-specific intent**: A custom intent defined by an application or applications, independent of the Standard.\n- **Bridge**: Shorthand for Desktop Agent Bridge.\n- **bridging**: Shorthand for the exchange of messages across a Desktop Agent Bridge for the purposes of extending interop between apps managed by different Desktop Agents.\n- **Bridge Connection Protocol (BCP)**: A defined set of steps for a Desktop Agent to connect to a Desktop Agent Bridge.\n- **Bridge Messaging Protocol (BMP)**: Protocol for Desktop Agents to communicate with each other over a Desktop Agent Bridge.\n- **Browser Resident Desktop Agent**: A Desktop Agent loaded in a window or frame within a web browser (in contrast to a Desktop Agent that \"injects\" a global fdc3 object) that is communicated with via a Desktop Agent Proxy.\n- **Channel**: A grouping of apps for the purposes of sharing stateful pieces of data. A secondary interface of the FDC3 API.\n- **context channels**: A mechanism to allow sets of apps to share stateful pieces of data among themselves, and to be alerted when that data changes.\n- **context**: Shorthand for context data.\n- **context data**: Objects encoding common identifiers and data in a standardized format that can be passed between apps via context channels or used in conjunction with intents to invoke actions creating a seamless cross-application workflow. Diverse context data types are created to encode different types of data, each having their own _type_ field and unique set of data fields.\n- **Desktop Agent**: A desktop component (or aggregate of components) that serves as a launcher and message router (broker) for applications in its domain. The primary interface of the FDC3 API.\n- **Desktop Agent Bridge (DAB)**: An independent service that Desktop Agents connect to which allows them to relay requests to other Desktop Agents also connected to the bridge, allowing FDC3-based interop to extend across multiple Desktop Agents and machines.\n- **Desktop Agent Communication Protocol (DACP)**: JSON communication protocol for the Desktop Agent API. Used by a Desktop Agent Proxy interface over the Channel Messaging API (as specified by the Web Connection Protocol) to communicate with a Desktop Agent running in another window/frame.\n- **Desktop Agent Preload**: An 'injected' or 'preloaded' Desktop Agent API implementation, typically provided by an electron (or similar) container or browser extension, which is made available to web applications at `window.fdc3` and may be returned by the `getAgent()` function defined in the FDC3 Web Connection Protocol.\n- **Desktop Agent Proxy**: An interface to a web-based Desktop Agent (implementation of the Desktop Agent API) that uses the Web Connection Protocol and Desktop Agent Communication protocol to communicate with a Desktop Agent implementation running in another frame or window. Returned by the `getAgent()` function provided by the FDC3 NPM module where a browser-based Desktop Agent is detected.\n- **FDC3 API**: A baseline, consistent developer interface for interoperability between applications.\n- **GUID**: Globally Unique IDentifier, synonymous with UUID. Defined by [IETF RFC4122](references).\n- **interop**: Shorthand for interoperability.\n- **interoperability**: the ability of software applications to exchange and make use of information and invoke specified actions.\n- **intent**: A verb, with a pre-agreed meaning (expected behavior), used to invoke an action between applications. A set of such verbs can, in conjunction with Context Data acting as nouns, be used to put together common cross-application workflows on the financial desktop.\n- **Listener**: API interface which allows unsubscribing from Intents or Context Channels.\n- **MessageChannel**: An interface defined by the [HTML Standard's Channel Messaging API](https://html.spec.whatwg.org/multipage/web-messaging.html#channel-messaging) for a two-way pipe with a `MessagePort` at each end, used to implement communication between code running in different browsing contexts. Used by the Web Connection Protocol.\n- **MessagePort**: An interface defined by the [HTML Standard's Channel Messaging API](https://html.spec.whatwg.org/multipage/web-messaging.html#channel-messaging) used to transmit and receive messages over a `MessageChannel`. Each channel has two message ports. Data sent through one port is received by the other port, and vice versa. Used by the Web Connection Protocol.\n- **Originating App**: The application that sent a particular context message or raised an intent.\n- **Parent frame**: A browser window or frame that creates the window or iframe in which an application runs. (The parent provides a `WindowProxy` object which is used by Web Connection Protocol).\n- **Platform Provider**: An environment that provides an implementation of the FDC3 API that applications can use.\n- **raising an intent**: The act of requesting, via the FDC3 API/Desktop Agent that a specified action be performed by another application, using specified context data as input.\n- **resolver**: A facility of a Desktop Agent used to map a raised intent and associated context object to an application that will perform the action represented by the intent, using the context object as input. Where multiple applications can resolve the intent, a resolver will often display a user-interface allowing a user to pick from the available applications that support the intent and type of context supplied.\n- **resolving an intent**: The act of mapping a specified intent and context object to an application.\n- **SessionStorage**: A JavaScript storage API defined by the [HTML Standard's Web Storage API](https://html.spec.whatwg.org/multipage/webstorage.html#webstorage) that persists data for web apps within the scope of a specific window or tab. SessionStorage is identical to the LocalStorage API but is scoped to a particular window/tab, as defined by the [HTML Standard](https://html.spec.whatwg.org/multipage/webstorage.html#dom-sessionstorage)\n- **standard intent**: An intent defined by this Standard.\n- **UUID**: Universally Unique IDentifier, synonymous with GUID. Defined by [IETF RFC4122](references).\n- **Web Connection Protocol (WCP)**: A defined set of steps for a web application to connect to Desktop Agents that implement any of the interfaces defined for web applications in the FDC3 Standard, including both preloaded Desktop Agent interfaces and Browser-based Desktop Agents that work with a Desktop Agent Proxy.\n- **WindowProxy**: An interface defined by the HTML standard that proxies a remote Window object: [https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object). WindowProxy objects are used for communication via `postMessage` as part of the Web Connection Protocol.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/fdc3-intro.md",
    "content": "---\nid: fdc3-intro\ntitle: Welcome to FDC3 2.2\nsidebar_label: Introduction\n---\n\nThe mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion, without prior bi-lateral agreements.\n\nFDC3 provides an **open standard for interoperability** between applications on the financial desktop.\n\nThis includes standardized verbs to invoke actions between applications (**intents**), a standardized **context data** format, a REST-based **App Directory** standard, and standardized API operations for a **Desktop Agent**.\n\n## Motivation\n\nFDC3 codifies standard patterns that application developers have been using for cross-application workflows between web and native applications in the financial industry.\n\nFor more information, see [Why FDC3?](why-fdc3)\n\n## Parts of the Standard\n\nThe [Standard](fdc3-standard) currently consists of five complementary parts:\n\n- [API](api/spec)\n- [Intents](intents/spec)\n- [Context Data](context/spec)\n- [App Directory](app-directory/spec)\n- [Agent Bridging](agent-bridging/spec)\n\n## Use Cases\n\nFrom its inception, the standards have been informed by real-world [business use cases](use-cases/overview), which you can view on this website, and form an important part of FDC3.\n\n## Who is using FDC3?\n\nThe Financial Desktop Connectivity and Collaboration Consortium (FDC3) standards are created and used by [leading organizations across the financial industry](/users). For more detail on who's using FDC3, developer tools, training and examples, see the [community page](/community).\n\n## How is FDC3 governed?\n\nFDC3 is hosted within, and governed by the policies of, the [Fintech Open Source Foundation](http://finos.org/) (FINOS). FINOS is an independent nonprofit organization focused on promoting open innovation within financial services.\n\n- See the [FDC3 Governance document](https://github.com/finos/FDC3/blob/main/GOVERNANCE.md) for details of how FDC3 is governed.\n- See the [FDC3 Contribution Guide](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md) for details of how to contribute to FDC3.\n- See the [FDC3 Charter](fdc3-charter#licensing) for details of how deliverables are licensed.\n\n## Where should I go next?\n\n- Have a look at the [API's supported platforms](api/supported-platforms) or [common use cases](use-cases/overview).\n- Visit FDC3 [on GitHub](https://github.com/finos/FDC3).\n- Download and install our [npm package](https://www.npmjs.com/package/@finos/fdc3).\n- Try out an FDC3-compliant implementation, e.g. this [browser extension](https://github.com/finos/fdc3-desktop-agent).\n- Join us in the [mailing list](mailto:fdc3+subscribe@finos.org) or on [Slack](https://app.slack.com/client/T01E7QRQH97/C01R0P7H5LH).\n- [Participate](https://github.com/finos/FDC3#getting-involved) in the evolution of the standard.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/fdc3-standard.md",
    "content": "---\nid: fdc3-standard\ntitle: FDC3 2.2\nsidebar_label: Abstract\n---\n\n**Status:** Current  \n_**adopted:** 1st April 2025_  \n_**released:** 8th April 2025_  \n\n## Abstract\n\nFDC3 aims to provide an open standard for interoperability on the financial desktop. This includes standardized verbs to invoke actions between applications (called \"intents\"), a standardized data format, an OpenAPI app directory standard, and standardized API operations.\n\nThe specifications are informed by agreed business [use cases](use-cases/overview), and implemented and used by leading [financial industry participants](../../users).\n\nThe standard currently consists of five complementary parts:\n\n- **[Desktop Agent API](api/spec)**: An API interface for working with a Desktop agent, which acts as launcher and message router (broker) for applications in its domain.\n- **[Intents](intents/spec)**: A set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n- **[Context Data](context/spec)**: A message format for passing common identifiers and data between apps to create a seamless workflow.\n- **[App Directory](app-directory/spec)**: A structured repository of information about apps that can be used in an FDC3-enabled desktop.\n- **[Agent Bridging](agent-bridging/spec)**: An [@experimental](fdc3-compliance#experimental-features) API interface for the interconnection of Desktop Agents (DAs) such that apps running under different Desktop Agents can interoperate.\n\n## Versioning\n\nThis Standard defines FDC3 Version 2.2. The differences between this version and earlier ones can be found in the [Changelog](https://github.com/finos/FDC3/blob/main/CHANGELOG.md).\n\nFor more details on FDC3's versioning, deprecation and experimental features policies see the [Compliance page](./fdc3-compliance#versioning).\n\n## Table of Contents\n\n- [Compliance information](fdc3-compliance)\n- [Glossary](fdc3-glossary)\n- [References](references)\n- [API Part](api/spec)\n- [Intents Part](intents/spec)\n- [Context Data Part](context/spec)\n- [App Directory Part](app-directory/spec)\n- [Agent Bridging Part](agent-bridging/spec)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/guides/submit-new-intent.md",
    "content": "---\nid: SubmitNewIntent\nsidebar_label: How To Submit New Intent\ntitle: How to Submit a New Intent PR\n---\n\n## Getting Started\n\nPrepare to submit a patch as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch) in CONTRIBUTING.md. Use the issue number and issue title as the branch name, e.g.\n\n```git checkout -b 587-intent-proposal-view-research```\n\nTo install all the necessary packages to run the website locally, change to the website directory and run yarn\n\n```bash\ncd website\nyarn\n```\n\nTo run the website locally\n\n```yarn start```\n\nThis will open the home page or browse to [https://localhost:3000](https://localhost:3000)\n\nNote that the page opens on the current release version of the docs and you will be changing the latest version. Click the version selector in the top left hand corner\n\n![Version Selector](/assets/version_selector.png)\n\nand then select 'Documentation' under 'Latest Version'\n\n![Latest Version Selector](/assets/latest_version_selector.png)\n\nThe 'next' version will be indicated in the header:\n\n![Next Version](/assets/next_version.png)\n\n## Create Intent File\n\nAdd the new intent markdown file to docs/intents/ref. Use one of the existing intent markdown files as a template. E.g. the [ViewResearch](../intents/ref/ViewResearch) intent was created using [ViewProfile](../intents/ref/ViewProfile) as an example:\n\n![View Research](/assets/view_research.png)\n\n## Link to Intent File\n\nAdd links to your Intent File to the following:\n\n- [src/intents/Intents.ts](https://github.com/finos/FDC3/blob/main/src/intents/Intents.ts)\n- [src/intents/standard intents.json](https://github.com/finos/FDC3/blob/main/src/intents/standard%20intents.json)\n- [website/sidebars.json](https://github.com/finos/FDC3/blob/main/website/sidebars.json) (look for the 'Intents' property and the 'ids' property within it)\n\nAt this point your new Intent should appear on the sidebar (you may need to restart yarn to get this).\n\nAlso add to:\n\n- [docs/intents/spec.md](https://github.com/finos/FDC3/blob/main/docs/intents/spec.md) in the 'Standard Intents' section (also add the summary from your Intent page)\n- Any of the Context documents in [docs/context/ref](https://github.com/finos/FDC3/blob/main/docs/context/ref) that are utilized by the Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent, each of the [Contact](../context/ref/Contact), [Instrument](../context/ref/Instrument) and [Organization](../context/ref/Organization) Contexts are valid and so links were added to their Context pages)\n- Any of the Intents documents in [docs/intents/ref](https://github.com/finos/FDC3/blob/main/docs/intents/ref) that are related or relevant to the new Intent (e.g. for the [ViewResearch](../intents/ref/ViewResearch) intent a link was added to the [ViewAnalysis](../intents/ref/ViewAnalysis) document)\n\n## Finishing Off\n\nCommit your changes and push as described in [How to Contribute a Patch](https://github.com/finos/FDC3/blob/main/CONTRIBUTING.md#3how-to-contribute-a-patch). Then submit the branch as a Pull Request (in github, go to the Branches tab and click 'New Pull Request')\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/CreateInteraction.md",
    "content": "---\nid: CreateInteraction\nsidebar_label: CreateInteraction\ntitle: CreateInteraction\nhide_title: true\n---\n# `CreateInteraction`\n\nCreate a record documenting an interaction (calls, meetings, etc.) between a list of contacts.\n\n## Intent Name\n\n`CreateInteraction`\n\n## Display Name\n\n`Create Interaction`\n\n## Possible Contexts\n\n- [ContactList](../../context/ref/ContactList)\n- [Interaction](../../context/ref/Interaction)\n\nSHOULD return context as a result:\n\n- [TransactionResult](../../context/ref/TransactionResult)\n\n## Example\n\n```js\nconst interaction = {\n    type: 'fdc3.interaction',\n    participants: {\n        type: 'fdc3.contactList',\n        contacts: [\n            {\n                type: 'fdc3.contact',\n                name: 'Jane Doe',\n                id: {\n                    email: 'jane.doe@mail.com'\n                }\n             },\n            {\n                type: 'fdc3.contact',\n                name: 'John Doe',\n                id: {\n                    email: 'john.doe@mail.com'\n                }\n            },\n        ]\n    },\n    interactionType: 'Instant Message',\n    timeRange: {\n        type: 'fdc3.timeRange',\n        startTime: '2022-02-10T15:12:00Z'\n    },\n    description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n    initiator:  {\n        type: 'fdc3.contact',\n        name: 'Jane Doe',\n        id: {\n            email: 'jane.doe@mail.com'\n        }\n    },\n    origin: 'Outlook'\n}\n\nconst intentResolution = await fdc3.raiseIntent('CreateInteraction', interaction);\nconst result = await intentResolution.getResult();\nconsole.log(result);\n```\n\nConsole log will display:\n\n```js\n{\n    type: 'fdc3.transactionResult',\n    status: 'Created',\n    context: {\n        type: 'fdc3.interaction',\n        participants: {\n            type: 'fdc3.contactList',\n            contacts: [\n                {\n                    type: 'fdc3.contact',\n                    name: 'Jane Doe',\n                    id: {\n                        email: 'jane.doe@mail.com'\n                    }\n                 },\n                {\n                    type: 'fdc3.contact',\n                    name: 'John Doe',\n                    id: {\n                        email: 'john.doe@mail.com'\n                    }\n                },\n            ]\n        },\n        interactionType: 'Instant Message',\n        timeRange: {\n            type: 'fdc3.timeRange',\n            startTime: '2022-02-10T15:12:00Z'\n        },\n        description: 'Laboris libero dapibus fames elit adipisicing eu, fermentum, dignissimos laboriosam, erat, risus qui deserunt. Praesentium! Reiciendis. Hic harum nostrud, harum potenti amet? Mauris. Pretium aliquid animi, eget eiusmod integer proident. Architecto ipsum blandit ducimus, possimus illum sunt illum necessitatibus ab litora sed, nonummy integer minus corrupti ducimus iste senectus accumsan, fugiat nostrud? Pede vero dictumst excepturi, iure earum consequuntur voluptatum',\n        initiator:  {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        origin: 'Outlook'\n        id:  {\n            Singletrack: 'a0S8d000000uO05EAE'\n        }\n    },\n    message: 'record with id \"a0S8d000000uO05EAE\" was created'\n}\n```\n\n## See Also\n\nContext\n- [Interaction](../../context/ref/Interaction)\n- [TransactionResult](../../context/ref/TransactionResult)"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/CreateOrUpdateProfile.md",
    "content": "---\nid: CreateOrUpdateProfile\nsidebar_label: CreateOrUpdateProfile\ntitle: CreateOrUpdateProfile\nhide_title: true\n---\n# `CreateOrUpdateProfile`\n\nCreate a record or update an existing profile record with information for the individual or organization provided as context.\n\n## Intent Name\n\n`CreateOrUpdateProfile`\n\n## Display Name\n\n`Create or Update Profile`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\nSHOULD return context as a result:\n\n- [TransactionResult](../../context/ref/TransactionResult)\n\n## Example\n\n```js\nconst organization = {\n  \"type\": \"fdc3.organization\",\n  \"name\": \"Cargill, Incorporated\",\n  \"id\": {\n    \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n    \"FDS_ID\": \"00161G-E\"\n  }\n};\n\nconst intentResolution = await fdc3.raiseIntent('CreateOrUpdateProfile', organization);\nconst result = await intentResolution.getResult();\nconsole.log(result);\n```\n\nConsole log might display:\n\n```js\n{\n    type: 'fdc3.transactionResult',\n    status: 'Created',\n    context: {\n        \"type\": \"fdc3.organization\",\n        \"name\": \"Cargill, Incorporated\",\n        \"id\": {\n            \"LEI\": \"QXZYQNMR4JZ5RIRN4T31\",\n            \"FDS_ID\": \"00161G-E\",\n            \"internalId\": \"al983020303a_23\"\n        }\n    },\n    message: 'record with id \"al983020303a_23\" was created'\n}\n```\n\n## See Also\n\n- [ViewProfile](../../intents/ref/ViewProfile)\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n- [TransactionResult](../../context/ref/TransactionResult)"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/SendChatMessage.md",
    "content": "---\nid: SendChatMessage\nsidebar_label: SendChatMessage\ntitle: SendChatMessage\nhide_title: true\n---\n# `SendChatMessage`\n\nSend a message to an existing chat room.\n\n## Intent Name\n\n`SendChatMessage`\n\n## Display Name\n\n`Send Chat Message`\n\n## Possible Contexts\n\n- [ChatMessage](../../context/ref/ChatMessage)\n\n## Example\n\n```js\n// Start a chat and retrieve a reference to the chat room created\nconst intentResolution = await fdc3.raiseIntent(\"StartChat\", context);\nconst chatRoom = intentResolution.getResult();\n\n//Some time later\n\nlet chatMessage: ChatMessage = {\n    type: \"fdc3.chat.message\",\n    chatRoom,\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nawait fdc3.raiseIntent(\"SendChatMessage\", context, intentResolution.source);\n```\n\n## See Also\n\nContext\n- [ChatMessage](../../context/ref/ChatMessage)\n- [ChatRoom](../../context/ref/ChatRoom)\n\nIntents\n- [StartChat](StartChat)\n- [StartCall](StartCall)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/StartCall.md",
    "content": "---\nid: StartCall\nsidebar_label: StartCall\ntitle: StartCall\nhide_title: true\n---\n# `StartCall`\n\nInitiate a call with a contact or list of contacts.\n\n## Intent Name\n\n`StartCall`\n\n## Display Name\n\n`Start a Call`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartCall', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n\n- [StartChat](StartChat)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/StartChat.md",
    "content": "---\nid: StartChat\nsidebar_label: StartChat\ntitle: StartChat\nhide_title: true\n---\n# `StartChat`\n\nInitiate a chat with a contact, a list of contacts or detailed initialization settings.  This could be launched from within another application. For example initiating a chat from a research or OMS application.\n\n## Intent Name\n\n`StartChat`\n\n## Display Name\n\n`Start a Chat`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('StartChat', contact)\n\n// chat with initialization settings\nconst initSettings = {\n    type: 'fdc3.chat.initSettings',\n    chatName: 'Chat ABCD',\n    members: {\n        type: 'fdc3.contactList',\n        contacts: [{\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane@mail.com'\n            }\n        },{\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john@mail.com'\n            },\n        }]\n    },\n    options: {\n        groupRecipients: true, // one chat with both contacts\n        isPublic: false, // private chat room\n        allowHistoryBrowsing: true,\n        allowMessageCopy: true\n    }\n    message: {\n      type: 'fdc3.message',\n      text: {\n        'text/plain': 'Hey all, can we discuss the issue together? I attached a screenshot'\n      },\n      entities: {\n         '0': {\n             type: 'fdc3.fileAttachment',\n              data: {\n              name: 'myImage.png',\n                    dataUri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'\n              }\n          }\n      }\n    }\n}\n\nconst resolution = fdc3.raiseIntent('StartChat', initSettings);\n\n// Return a reference to the room\nconst chatRoom = await resolution.getResult();\n```\n\n## See Also\n\nContext\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n- [ChatInitSettings](../../context/ref/ChatInitSettings)\n\nIntents\n\n- [SendChatMessage](SendChatMessage)\n- [StartCall](StartCall)\n- [StartEmail](StartEmail)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/StartEmail.md",
    "content": "---\nid: StartEmail\nsidebar_label: StartEmail\ntitle: StartEmail\nhide_title: true\n---\n# `StartEmail`\n\nInitiate an email with a contact or list of contacts provided as part of an Email context.\n\n## Intent Name\n\n`StartEmail`\n\n## Display Name\n\n`Start Email`\n\n## Possible Contexts\n\n- [Email](../../context/ref/Email)\n\n## Example\n\n```js\nwindow.fdc3.raiseIntent('fdc3.StartEmail', {\n  type: 'fdc3.email',\n  recipients: {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n      email: 'jane.doe@example.com'\n    }\n  },\n  subject: 'The information you requested',\n  textBody: 'Blah, blah, blah ...'\n})\n```\n\n## See Also\n\nContext\n\n- [Email](../../context/ref/Email)\n\nIntents\n\n- [StartCall](StartCall)\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewAnalysis.md",
    "content": "---\nid: ViewAnalysis\nsidebar_label: ViewAnalysis\ntitle: ViewAnalysis\nhide_title: true\n---\n# `ViewAnalysis`\n\nDisplay analysis on the provided context.\n\n## Intent Name\n\n`ViewAnalysis`\n\n## Display Name\n\n`View Analysis`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewAnalysis', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewChart.md",
    "content": "---\nid: ViewChart\nsidebar_label: ViewChart\ntitle: ViewChart\nhide_title: true\n---\n# `ViewChart`\n\nDisplay a chart for the provided context.\n\n## Intent Name\n\n`ViewChart`\n\n## Display Name\n\n`View Chart`\n\n## Possible Contexts\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\n## Example\n\nRequest a chart for an instrument:\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewChart', instrument)\n```\n\nRequest a specific chart:\n\n```js\nconst chart = {\n    type: \"fdc3.chart\",\n    instruments: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        },\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"GOOG\"\n            }\n        }\n    ],\n    range: {\n        type: \"fdc3.timeRange\",\n        startTime: \"2020-09-01T08:00:00.000Z\",\n        endTime: \"2020-10-31T08:00:00.000Z\"\n    },\n    style: \"line\",\n    otherConfig: {\n        indicators: [\n            {\n                name: \"ma\",\n                parameters: {\n                    period: 14,\n                    type: \"ema\"\n                }\n            },\n            {\n                name: \"volume\"\n            }\n        ]\n    }\n};\n\nfdc3.raiseIntent(\"ViewChart\", chart);\n```\n\n## See Also\n\nContext\n\n- [Chart](../../context/ref/Chart)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewQuote](ViewQuote)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewChat.md",
    "content": "---\nid: ViewChat\nsidebar_label: ViewChat\ntitle: ViewChat\nhide_title: true\n---\n# `ViewChat`\n\nOpen an existing chat room.\n\n## Intent Name\n\n`ViewChat`\n\n## Display Name\n\n`View Chat`\n\n## Possible Contexts\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact): It will open the **direct** chat where there is the current user and the contact\n- [ContactList](../../context/ref/ContactList): It will open the **room** where there is the current user and the listed contacts. Contact List may need to display search results if there are multiple matches.\n\n## Output\n\nThis intent returns as output:\n- If the chat doesn't exist, will display a modal to create a chat\n- if the chat gets created, return its ChatRoom context\n- if none is created return void\n\n## Example: ChatRoom\n\n```js\nconst chatRoom = {\n    type: 'fdc3.chat.room',\n    providerName: \"Symphony\",\n    id: {\n        streamId: \"j75xqXy25NBOdacUI3FNBH\"\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', chatRoom);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## Example: Contact\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contact);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the direct chat was found\n```\n\n## Example: ContactList\n\n```js\nconst contacts = {\n    type: 'fdc3.contactList',\n    contacts: [\n        {\n            type: 'fdc3.contact',\n            name: 'Jane Doe',\n            id: {\n                email: 'jane.doe@mail.com'\n            }\n        },\n        {\n            type: 'fdc3.contact',\n            name: 'John Doe',\n            id: {\n                email: 'john.doe@mail.com'\n            }\n        },\n    ]\n}\n\n\nconst intentResolution = await fdc3.raiseIntent('ViewChat', contacts);\n\nconst chatRoom = intentResolution.getResult(): // A chatRoom will be returned as context if the room was found\n```\n\n## See Also\n\nContext\n\n- [ChatRoom](../../context/ref/ChatRoom)\n- [Contact](../../context/ref/Contact)\n- [ContactList](../../context/ref/ContactList)\n\nIntents\n\n- [StartChat](StartChat)"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewContact.md",
    "content": "---\nid: ViewContact\nsidebar_label: ViewContact (deprecated)\ntitle: ViewContact\nhide_title: true\n---\n# `ViewContact`\n\n:::caution\nViewContact has been deprecated in FDC3 2.0 in favour of the more general [ViewProfile](ViewProfile) intent.\n:::\n\nView details for a contact.\n\n## Intent Name\n\n`ViewContact`\n\n## Display Name\n\n`View Contact Details`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n\n## Example\n\n```js\nconst contact = {\n    type: 'fdc3.contact',\n    name: 'Jane Doe',\n    id: {\n        email: 'jane@mail.com'\n    }\n}\n\nfdc3.raiseIntent('ViewContact', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n\nIntents\n\n- [StartChat](StartChat)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewHoldings.md",
    "content": "---\nid: ViewHoldings\nsidebar_label: ViewHoldings\ntitle: ViewHoldings\nhide_title: true\n---\n# `ViewHoldings`\n\nDisplay any holdings for the provided instrument, list of instruments, or organization.\n\n## Intent Name\n\n`ViewHoldings`\n\n## Display Name\n\n`View Holdings`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewHoldings', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewInstrument](ViewInstrument)\n- [ViewAnalysis](ViewAnalysis)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewInstrument.md",
    "content": "---\nid: ViewInstrument\nsidebar_label: ViewInstrument\ntitle: ViewInstrument\nhide_title: true\n---\n# `ViewInstrument`\n\nDisplay details for the provided instrument.\n\n## Intent Name\n\n`ViewInstrument`\n\n## Display Name\n\n`View Instrument Details`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewInstrument', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)\n- [ViewOrders](ViewOrders)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewInteractions.md",
    "content": "---\nid: ViewInteractions\nsidebar_label: ViewInteractions\ntitle: ViewInteractions\nhide_title: true\n---\n# `ViewInteractions`\n\nDisplay interactions (calls, meetings, etc.) related to an individual, an instrument or organization provided as context.\n\n## Intent Name\n\n`ViewInteractions`\n\n## Display Name\n\n`View Interactions`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewInteractions', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewProfile](ViewProfile)\n- [ViewResearch](ViewResearch)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewMessages.md",
    "content": "---\nid: ViewMessages\nsidebar_label: ViewMessages\ntitle: ViewMessages\nhide_title: true\n---\n# `ViewMessages`\n\nSearch and display a list of messages (for example in a chat application or CRM) to the user. \n\n## Intent Name\n\n`ViewMessages`\n\n## Display Name\n\n`View Messages`\n\n## Possible Contexts\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n\n## Example\n\nRequest display of messages relating to a specific `fdc3.instrument` (representing a ticker):\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.instrument\",\n            id: {\n                ticker: \"AAPL\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.contact`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific `fdc3.organization`:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        }\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages relating to a specific **phrase**:\n\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\nRequest display of messages matching _multiple_ criteria:\n```js\nconst searchCriteria = {\n    type: \"fdc3.chat.searchCriteria\",\n    criteria: [\n        {\n            type: \"fdc3.contact\",\n            name: \"Jane Doe\",\n            id: {\n                email: \"jane.doe@mail.com\"\n            }\n        },\n        {\n            type: \"fdc3.organization\",\n            name: \"Symphony\"\n        },\n        \"#OrderID45788422\"\n    ]\n}\n\nfdc3.raiseIntent('ViewMessages', searchCriteria);\n```\n\n## See Also\n\nContext\n\n* [ChatSearchCriteria](../../context/ref/ChatSearchCriteria)\n* [Instrument](../../context/ref/Instrument)\n* [Contact](../../context/ref/Contact)\n* [Organization](../../context/ref/Organization)\n\nIntents\n\n* [ViewChat](ViewChat)"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewNews.md",
    "content": "---\nid: ViewNews\nsidebar_label: ViewNews\ntitle: ViewNews\nhide_title: true\n---\n# `ViewNews`\n\nDisplay news stories for the provided context.\n\n## Intent Name\n\n`ViewNews`\n\n## Display Name\n\n`View News`\n\n## Possible Contexts\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'IBM'\n    },\n    market: {\n        MIC: \"XNYS\"\n    }\n}\n\nfdc3.raiseIntent('ViewNews', instrument)\n```\n\n## See Also\n\nContext\n\n- [Country](../../context/ref/Country)\n- [Instrument](../../context/ref/Instrument)\n- [InstrumentList](../../context/ref/InstrumentList)\n- [Organization](../../context/ref/Organization)\n- [Portfolio](../../context/ref/Portfolio)\n- [Position](../../context/ref/Position)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewOrders.md",
    "content": "---\nid: ViewOrders\nsidebar_label: ViewOrders\ntitle: ViewOrders\nhide_title: true\n---\n# `ViewOrders`\n\nDisplay any orders related to the provided contact, instrument, or organization.\n\n## Intent Name\n\n`ViewOrders`\n\n## Display Name\n\n`View Orders`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'Tesla, Inc.',\n    id: {\n        ticker: 'TSLA'\n    }\n}\n\nfdc3.raiseIntent('ViewOrders', instrument)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInstrument](ViewInstrument)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewProfile.md",
    "content": "---\nid: ViewProfile\nsidebar_label: ViewProfile\ntitle: ViewProfile\nhide_title: true\n---\n# `ViewProfile`\n\nDisplay basic profile information for the individual or organization provided as context.\n\n## Intent Name\n\n`ViewProfile`\n\n## Display Name\n\n`View Profile`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewProfile', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewHoldings](ViewHoldings)\n- [ViewInteractions](ViewInteractions)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewQuote.md",
    "content": "---\nid: ViewQuote\nsidebar_label: ViewQuote\ntitle: ViewQuote\nhide_title: true\n---\n# `ViewQuote`\n\nDisplay pricing for an [Instrument](../../context/ref/Instrument).\n\n## Intent Name\n\n`ViewQuote`\n\n## Display Name\n\n`View Quote`\n\n## Possible Contexts\n\n- [Instrument](../../context/ref/Instrument)\n\n## Example\n\n```js\nconst instrument = {\n    type: 'fdc3.instrument',\n    name: 'International Business Machines',\n    id: {\n        ticker: 'ibm'\n    }\n}\n\nfdc3.raiseIntent('ViewQuote', instrument)\n```\n\n## See Also\n\nContext\n\n- [Instrument](../../context/ref/Instrument)\n\nIntents\n\n- [ViewChart](ViewChart)"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/ref/ViewResearch.md",
    "content": "---\nid: ViewResearch\nsidebar_label: ViewResearch\ntitle: ViewResearch\nhide_title: true\n---\n# `ViewResearch`\n\nShow research related to an instrument, an individual or organization provided as context.\n\n## Intent Name\n\n`ViewResearch`\n\n## Display Name\n\n`View Research`\n\n## Possible Contexts\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\n## Example\n\n```js\nconst contact = {\n  type: 'fdc3.contact',\n  name: 'Jane Doe',\n  id: {\n    email: 'jane@mail.com'\n  }\n}\n\nfdc3.raiseIntent('ViewResearch', contact)\n```\n\n## See Also\n\nContext\n\n- [Contact](../../context/ref/Contact)\n- [Instrument](../../context/ref/Instrument)\n- [Organization](../../context/ref/Organization)\n\nIntents\n\n- [ViewAnalysis](ViewAnalysis)\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/intents/spec.md",
    "content": "---\nid: spec\nsidebar_label: Overview\ntitle: Intents Overview (2.2)\n---\n\nFDC3 Intents define a standard set of verbs that, in conjunction with context data acting as nouns, can be used to put together common cross-application workflows on the financial desktop.\n\n- Applications register the intents and [context data](../context/spec) combinations they support in the [App Directory](../app-directory/spec).\n- The App Directory supports application discovery by intents and/or context data.\n- Intents are not full RPC, apps don’t need to enumerate every function with an intent.\n- FDC3 standard intents are a limited set, organizations can create their own intents.\n\n## Naming Conventions\n\nNaming of Intents SHOULD follow the below guidelines:\n\n- Intent names should be free of non-alphanumeric characters.\n- ‘.’ will be used to namespace the intent (see below).\n- Intent names should be in UpperCamelCase.\n\n:::note\nThe naming guidelines should be adhered to when creating future Intents.  This is to ensure they meet the criteria for addition to the FDC3 standard and to provide a consistent user experience.\n:::\n\n### Characteristics\n\nWhen creating Intents they should be:\n\n- Recognizable\n  - Generally self-evident what the thing is\n- Repeatable\n  - Many instances across the industry\n- Stateless\n  - Workflows should not require callbacks or endpoints to maintain references to each other.  Once an Intent is passed to an endpoint - it controls the rest of that workflow.\n- Specific\n  - Terms should not be so open-ended that one endpoint could fulfill the Intent in a completely different way than another\n- Distinct\n  - Granular enough that Intent handlers can communicate key functional differences\n\n### Namespaces\n\nAll standard intent names are reserved. Applications may use their own intents ad hoc.\nHowever, there is occasionally a need for applications to ensure that their intents avoid collision, for example, where a workflow is highly specific to or internal to an application. The recommended approach is to namespace the intent with the application name. For example, the ‘myChart’ App may expose the ‘ViewChart’ intent and the ‘myChart.Foo’ proprietary intent.\n\n### Intent Name Prefixes\n\nEarly versions of the FDC3 standard included 8 intents, which used one of two different prefixes ( `View___` and `Start___`) that are focused on UI interactions.  The prefixes are used to help define the expected behavior of an app when resolving an intent with that prefix. The list of intent name prefixes was expanded in FDC3 2.0 to include prefixes that indicate that CRUD operations should be performed on data.\n\n#### `View___`\n\n- Expected behavior: Content should be displayed to the user.\n\n#### `Start___`\n  \n- Expected behavior: An interaction, such as a chat room or email thread, should be initiated.\n\nAs more use cases were identified it was clear further Intents were required.  FDC3 2.0 expanded this set to include the following:\n\n#### `Create___`\n\n- Expected behavior: A new record or entity should be created. The operation should fail if it already exists.\n\n#### `Update___`\n\n- Expected behavior: An existing record or entity should be updated. The operation should fail if it does not exist.\n\n#### `CreateOrUpdate___`\n\n- Expected behavior: A new record or entity should be created, or an existing one updated if it exists.\n\n#### `Delete___`\n\n- Expected behavior: An existing record or entity should be deleted. The operation should fail if it does not exist.\n\n#### `Get___`\n\n- Expected behavior: A record or entity should be retrieved and returned as an intent result. The operation should fail if the record does not exist.\n\n#### `Share___`\n\n- Expected behavior: A record or entity should shared. The operation should fail if it does not exist\n\n## Using Intents\n\nCombined with [context data](../context/spec) and [App Directory](../app-directory/overview) standards, intents enable rich service discovery on the desktop. For example:\n\n### Ask for a chart to be displayed\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n});\n```\n\n### Ask a specific application to display a chart\n\n```javascript\nconst result = await fdc3.raiseIntent(\"ViewChart\", {\n  type: \"fdc3.instrument\",\n  name: \"IBM\",\n  id: {\n    ticker:\"ibm\"\n  }\n}, \"market-data-app\");\n```\n\n### Find applications that can start a chat\n\n```javascript\nconst intentApps = await fdc3.findIntent(\"StartChat\");\n```\n\n### Find available intents for a contact\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.contact\",\n  name: \"Jane Doe\",\n  id: {\n    email:\"jane@doe.com\"\n  }\n});\n```\n\n## Intents that return data\n\nFrom FDC3 2.0, intents raised through the Desktop Agent API may return results in the form of a `Context` object or a `Channel`. Where an intent implements a transaction with another application, for example for a CRUD operation, the [`fdc3.transactionResult` context type](../context/ref/TransactionResult) SHOULD be used to provide a result status for the transaction and may wrap a context object that would otherwise be returned.\n\nFor more details on retrieving a result from a raised intent, see the [documentation for `raiseIntent`](../api/ref/DesktopAgent#raiseintent).\n\n## Intents Standard Compliance\n\nAn FDC3 Standard compliant application that supports intents **MUST**:\n\n- Meet the expected context and behavior defined for any FDC3-defined standard intents used.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) after it is launched. This facilitates delivery of raised intents to the application.\n\nAn FDC3 Standard compliant application that supports intents **SHOULD**:\n\n- Prefer FDC3-defined standard intents over proprietary intents, where a suitable standardized intent is available.\n- Ensure that proprietary intents follow the recommended naming conventions in the specification.\n- Apply [namespacing](#namespaces) to proprietary intent names, where it is necessary to avoid collision with those created by other applications.\n- Where an app is intended to be launched in order to resolve a raised intent, use the [`fdc3.addIntentListener`](../api/ref/DesktopAgent#addintentlistener) API call to set up the necessary handler function(s) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations.\n- Use the `fdc3.transactionResult` context type to return a status for any transactions relating to CRUD operations.\n\nAn FDC3 Standard compliant application that supports intents **MAY**:\n\n- Define proprietary intents to support use cases not currently supported via FDC3-defined standard intents.\n\nFor more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).\n\n## Standard Intents\n\nA list of standardized intents are defined in the following pages:\n\n- [`CreateInteraction`](ref/CreateInteraction)\n- [`CreateOrUpdateProfile`](ref/CreateOrUpdateProfile)\n- [`StartCall`](ref/StartCall)\n- [`StartChat`](ref/StartChat)\n- [`StartEmail`](ref/StartEmail)\n- [`ViewAnalysis`](ref/ViewAnalysis)\n- [`ViewChat`](ref/ViewChat)\n- [`ViewChart`](ref/ViewChart)\n- [`ViewHoldings`](ref/ViewHoldings)\n- [`ViewInstrument`](ref/ViewInstrument)\n- [`ViewInteractions`](ref/ViewInteractions)\n- [`ViewMessages`](ref/ViewMessages)\n- [`ViewNews`](ref/ViewNews)\n- [`ViewOrders`](ref/ViewOrders)\n- [`ViewProfile`](ref/ViewProfile)\n- [`ViewQuote`](ref/ViewQuote)\n- [`ViewResearch`](ref/ViewResearch)\n\n### Deprecated Intents\n\n- [`ViewContact`](ref/ViewContact)\n\n## Using Intents without a context\n\nAs the [Desktop Agent API](../api/ref/DesktopAgent) and [App Directory](../app-directory/overview) both require a context to be specified wherever intents are used, using an intent without a context is achieved through the use of the explicit `null` context type [`fdc3.nothing`](../context/ref/Nothing). By using an explicit type to represent an absence of context we allow applications to declare their support for an absence of context.\n\n```javascript\nconst intentsAndApps = await fdc3.findIntentsByContext({\n  type: \"fdc3.nothing\",\n});\n\nconst result = await fdc3.raiseIntent(\"StartChat\", {\n  type: \"fdc3.nothing\"\n});\n```\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/references.md",
    "content": "---\nid: references\ntitle: References & Bibliography\nsidebar_label: References\n---\n\n\nThe following normative documents contain provisions, which, through reference in this text, constitute provisions of this Standard. For dated references, subsequent amendments to, or revisions of, any of these publications do not apply. However, parties to agreements based on this Standard are encouraged to investigate the possibility of applying the most recent editions of the normative documents indicated below. For undated references, the latest edition of the normative document referred to applies:\n\n- **Apache 2.0 open-source license**, [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0).\n- **Community Specification license**, [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0)\n- **ISO 3166-1**, _Codes for the representation of names of countries and their subdivisions – Part 1: Country codes_, [https://www.iso.org/iso-3166-country-codes.html](https://www.iso.org/iso-3166-country-codes.html).\n- **ISO 8601-1:2019**, _Date and time — Representations for information interchange — Part 1: Basic rules_, [https://www.iso.org/standard/70907.html](https://www.iso.org/standard/70907.html)\n- **JSON Schema**, [https://json-schema.org/](https://json-schema.org/).\n- **OpenAPI Standard v3.0**, [https://www.openapis.org/](https://www.openapis.org/).\n- **quicktype**, [https://quicktype.io/](https://quicktype.io/).\n- **RFC 2119**, _Keywords for use in RFCs to Indicate Requirement Levels, March 1997_, [https://datatracker.ietf.org/doc/html/rfc2119](https://datatracker.ietf.org/doc/html/rfc2119).\n- **RFC 2782**, _A DNS RR for specifying the location of services (DNS SRV), February 2000_, [https://datatracker.ietf.org/doc/html/rfc2782](https://datatracker.ietf.org/doc/html/rfc2782).\n- **RFC 4122**, _A Universally Unique IDentifier (UUID) URN Namespace, July 2005_, [https://datatracker.ietf.org/doc/html/rfc4122](https://datatracker.ietf.org/doc/html/rfc4122).\n- **RFC 5646**, _Tags for Identifying Languages, September 2009_, [https://datatracker.ietf.org/doc/html/rfc5646](https://datatracker.ietf.org/doc/html/rfc5646).\n- **TypeScript Programming Language**, [https://www.typescriptlang.org/](https://www.typescriptlang.org/).\n- **Web Application Manifest**, _W3C Working Draft_, February 2022 [https://www.w3.org/TR/appmanifest/](https://www.w3.org/TR/appmanifest/)\n\nThe following documents may be useful in understanding certain aspects of this Standard; however, knowledge of them is not essential to the creation of a compliant implementation of this Standard:\n\n- **CUSIP**, _Committee on Uniform Security Identification Procedures_, [https://www.cusip.com/identifiers.html#/CUSIP](https://www.cusip.com/identifiers.html#/CUSIP).\n- **FIGI**, _Financial Instrument Global Identifier_, [https://www.openfigi.com/about/figi](https://www.openfigi.com/about/figi).\n- **ISIN**, _International Securities Identification Number_, [https://www.isin.org/isin/](https://www.isin.org/isin/)\n- **LEI**, _Legal Entity Identifier based on the ISO 17442 standard_, [https://www.legalentityidentifier.co.uk/what-is-lei-code/](https://www.legalentityidentifier.co.uk/what-is-lei-code/).\n- **npm**,  [https://docs.npmjs.com/about-npm](https://docs.npmjs.com/about-npm).\n- **PermID**, _Permanent Identifiers_, [https://permid.org/](https://permid.org/).\n- **pnpm**, [https://pnpm.io/motivation](https://pnpm.io/motivation).\n- **REST**, [https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm), [https://restfulapi.net/](https://restfulapi.net/).\n- **SEDOL**, _Stock Exchange Daily Official List_, [https://www.lseg.com/sedol](https://www.lseg.com/sedol).\n- **yarn**, [https://yarnpkg.com/getting-started](https://yarnpkg.com/getting-started).\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/trademarks.md",
    "content": "---\nid: trademarks\ntitle: Trademarks\n---\n\nThe trademarks, logos, and service marks not owned on behalf of FDC3 and FINOS and that are displayed on the Site are the registered and unregistered marks of their respective owners. No rights are granted by the FDC3 or FINOS to use such marks, whether by implication, estoppel, or otherwise.\n\nTrademarks used within this site and the FDC3 Standard include, but are not limited to:\n\n- Autobahn is a registered trademark of DEUTSCHE BANK AG, LONDON\n- Chromium is a trademark of Google LLC\n- Eikon is a registered trademark of Refinitiv\n- FDC3 is a registered trademark and brand of The Linux Foundation\n- Excel is a Microsoft Corporation product name\n- Finsemble is a registered trademark and product name of interop.io, Inc.\n- Glue42 is a trademark and product name of interop.io, Inc.\n- io.Connect is a trademark and product name of interop.io, Inc.\n- Java is a registered trademark of Oracle America, Inc.\n- JavaScript  is a registered trademark of Oracle America, Inc.\n- .NET is a trademark of Microsoft Corporation\n- npm is a trademark of npm, Inc.\n- OpenFin is a registered trademark of OpenFin Inc.\n- Outlook is a registered trademark of Microsoft Corporation\n- Python is a registered trademark of the Python Software Foundation\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/001-equity-sell-side-trader.md",
    "content": "---\nid: uc-1\ntitle: \"Use Case 1: Equity sell side trader\"\nsidebar_label: 1. Equity sell side trader\nlayout: use_case\n---\n\n![A diagrammatic representation of the applications available to the trader](/img/use-cases/1.png)\n\nOn their desktop, this user has:\n\n- Their firm's internal research & analytics platform, providing liquidity tools and internal research. The product is running and the **liquidity tool** is open.\n- An installed **chat application** is running.\nA **Watchlist** of stocks the trader is interested in\nA third-party **Charting Application** is available that the user accesses via a browser window. This is not open. \nAn **Overview** which gives pricing and fundamental data for stocks\n\n## Workflow 1\nThe user receives a message in the chat application containing an instrument identifier for Tesla. They want to do some analysis on Tesla and so see what applications are available through right clicking on the identifier for Tesla. A menu will appear within the chat application showing applications that can be launched from the Messenger tool. The menu shows two apps, both for analysis; one in the internal platform, the other in the market data terminal. \n\n## Workflow 2\nThe user wants to see his firm's internal research on Tesla and so decides to open the analysis app from his internal platform. The application is launched showing all internal research available for Tesla. \n\n## Workflow 3\nThe user wants to do further analysis on Tesla and so they open (themselves) a new app in the market data terminal that has Tesla's financial statement and other calculated financial data (such as market capitalization, P/E ratio, growth rate, earnings margins, etc). The user sees the third party charting app listed in a menu in the market data terminal and decides to do some technical analysis using that app. They select the chart app, which opens in a browser window. \n\n## Workflow 4\nHaving done technical analysis in the Chart app, the user wants to do the same analysis on BMW, and also use the open pricing and fundamental app. The user creates a link between the financial statement app, the pricing data app (both in the market data terminal) and the charting app. The user changes the instrument in the financial statement app and the other applications update to show information on BMW. \n\n## Workflow 5\nThe user adds BMW and Tesla to a shared group of companies (aka a Watchlist) named \"Automotive comparables\" to a list within the open Watchlist. All linked applications update with the new companies.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/002-buy-side-portfolio-manager.md",
    "content": "---\nid: uc-2\ntitle: \"Use Case 2: Buy side Portfolio Manager\"\nsidebar_label: 2. Buy side Portfolio Manager\nlayout: use_case\n---\n\n## Preconditions\nOn their desktop, this user has:\n- An installed full-service market data terminal with news, quotes, research management, etc. The application is open and FDC3 compatible.\n- A third-party portfolio management system. The application is closed and not FDC3 compatible.\n- An installed application for the chat tool used by the firm. The application is open and FDC3 compatible. It also has a proprietary integration to the portfolio management system.\n- The default web browser for the OS.\n- The default mail application for the OS.\n\nOn their mobile device, this user has:\n- The default mail application for the device.\n- The default web browser for the device.\n- The installed application from the market data provider.\n- The installed application for the chat tool used at the firm.\n\n## Workflow 1 (non-desktop)\nWhile using the mobile device (out of office), the user receives an email alert from his market data provider that a new research report has been posted which mentions a company that user is interested in. The user wants to read the report and clicks on the link in the email report. The market data application is launched and shows the research report.\n\n## Workflow 2\nBack in the office, the user wants to follow up on the report so he goes to his email client, finds the email and clicks the link. The market data application on the desktop displays the research report.\n\n## Workflow 3\nWhile reading the report the user wants to look up what the firm’s internal analysts have written about the company. The user hovers over the company identifier in the report and launches a tool within the terminal that shows the firm's internal research. A note from one analyst is intriguing so the user wants to know more. The user hovers over the name and launches the chat tool with a conversation with the analyst in focus and some details regarding the note is already posted to the chat.\n\n## Workflow 4\nDuring the chat, the analyst sends a link to a web site containing some further details regarding the company and the reason for the note posted. The user clicks on the link and the web browser opens. The user reads the article and continues to chat with the analyst.\n\n## Workflow 5\nDuring the chat, the analyst shares a chart with some important observations highlighted. The user clicks on the chart image in the chat and the terminal opens a live version of the chart with the observations highlighted.\n\n## Workflow 6\nDuring the chat, the user realizes that some changes should be done to their holdings in the company so hovers over the company identifier and launches the portfolio management system. While looking over the holdings the user also wants to contact the firm’s trader who is listed within the system. The user hovers over the name and launches the chat tool with a conversation with the trader in focus.\n\n## Interoperability Points\n- API\n- Intents\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/003-inhouse-cross-platform-launcher.md",
    "content": "---\nid: uc-3\ntitle: \"Use Case 3: Inhouse Cross Platform Launcher\"\nsidebar_label: 3. Inhouse Cross Platform Launcher\nlayout: use_case\n---\n\n## Preconditions\nThe user wants a single launch pad / toolbar to access my applications and which can also provide the primary UI access point for notifications and alerts.\nOn the desktop this user will typically have:\n- In house, container hosted, applications.\n- 3rd party container hosted applications.\n- In house applications written in .Net which are installed onto the user' desktops using inhouse installers.\n- Applications from a 3rd parties including e-mail applications and Desktop terminal applications\n\n\n## Workflow 1\nThe launcher is started by the user, or automatically run after login, in order to provide access to Applications.\n\nThe launcher may prompts the user to logon using the Enterprise's SSO system, which may be different to the Desktop login.\n\nThe launcher has a list of Application Directory URLs  it is configured to connect to, and passes the logged on user name and SSO identity/cookie of the logged in user to each App Directory as part of its sign on.\nNB It is possible that some of the systems used may ignore the SSO login and may prompt for their own login identity, however by having a first login in the launcher and sharing those details the user may avoid multiple logins to the same Identity system.\n\n\nThe In-House app directory holding details of the in-house applications uses this identity and internal entitlement information to define what applications this user is permissioned to run. This is reflected in the list of applications the App Directory presents to the user.\n\n## Workflow 2\nWhen the Launcher runs an in-house application, the Launcher should provide details of the logged on user including the SSO identity/cookie to the apps as they are launched to avoid forcing the user to repeatedly sign on.\n\nNB The use case is not saying that SSO is part of the FDC3 interfaces but that mechanisms should be defined to allow any SSO information to be passed to App Directories and App Launchers who are free to use this information if appropriate.\n\n## Workflow 3\nThe launcher starts a container based application using the container selected by the Enterprise. The selection of the container has been built into the Launcher design.\n\n## Workflow 4\nThe Launcher starts a desktop exe. The exe has been defined by the one of the App Directories and includes the path to the installed application.\n\nThere is no attempt to install desktop applications for which the user is permissioned but which have not been installed, instead the launcher may show a 'failed to start' error message of some kind.\n\n## Workflow 5\nThe Launcher runs an application from a 3rd party vendor such as a Desktop terminal application.\nNB These 'Desktop terminal applications' typically support tens or even hundreds of different window types which are referred to here as FDC3 Applications even when they are hosted in a single Desktop Application.\n\n## Workflow 6\nOne or more FDC3 Platforms offer save and restore layout functions. The Layout save and restore functionality is available from the The Launcher.  The Enterprise may also make  'standard' pre-built layouts available to users. The layouts made available depend on the user's role.\n\n## Workflow 7\nAs a User with a sales focus, many of the applications I run are related to a client (aka a customer or prospect of my organisation) and I want to launch applications with a customer pre-selected, rather than being forced to select the customer (aka Client) in the application. Therefore the Launcher provides a Client search capability that allows selection of a customer or prospect from an in-house client databases and/or CRM system.\n\n## Workflow 8\nAs a User with a trading focus, I have a similar requirement to Workflow 7, but instead I want to Select an Instrument.\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/004-client-side-fx-trader.md",
    "content": "---\nid: uc-4\ntitle: \"Use Case 4: Client-side FX Trader Credit Check\"\nsidebar_label: 4. Client-side FX Trader Credit Check\nlayout: use_case\n---\n\n## Preconditions\n\n- Running a client in-house proprietary application capable of conducting a user credit check\n- Running third-party trading app (e.g. Autobahn FX)\n\n## Workflow 1\n\n1. The FX Trader clicks button to book a trade in the third-party trading app (e.g. Autobahn FX)\n1. The trading app executes an interop action to the client in-house proprietary credit check application to check the trader's credit limit. If this check indicates the limit has been reached, the trading app presents a rejection dialog as a standard error dialog box with an informational message which may be a standard message (e.g. \"Credit Limit Reached\") or may include an interop link/action (provided by the credit check application) to resolve the limit breach.\n\n![Use Case 4 Workflow](/assets/uc4.png)\n\n## Required Features\n\n- Point-to-point RPC invocation.  Current FDC3 API proposal doesn't define response message for \"open\" and \"send\" methods as they both returns `Promise<void>`:\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L66\n\nhttps://github.com/finos/FDC3/blob/main/src/api/interface.ts#L34\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/005-buy-side-treasurer.md",
    "content": "---\nid: uc-5\ntitle: \"Use Case 5: Buy side Treasurer - client rates across providers\"\nsidebar_label: 5. Buy side Treasurer - client rates across providers\nlayout: use_case\n---\n\n## Preconditions\n\n- Several trading applications from different providers - all running\n- UI which aggregates rates from different providers by entered parameters and allows to quickly execute trade with the most appropriate one\n\n## Workflow 1\n\n1. A Corporate Treasurer enters or chooses the required trade parameters in an aggregator app which then sends requests to different providers to subscribe to rates updates\n1. The aggregator app shows screen with all the rates received from the running provider apps and updates them in real-time as soon as provider sends new rate.\n\n![Use Case 5 Workflow](/assets/uc5.png)\n\n\n## Workflow 2\n\n1. The Treasurer chooses one option to execute from the list of rates shown in the aggregator app\n1. The chosen provider app shows booking UI with pre-populated trade parameters\n\n## Workflow 3\n\n1. The Treasurer closes the screen with aggregated rates\n1. All the providers receive notification that listener has unsubscribed and they can stop providing updates\n\n## Required Features\n\n- Discovery\n- Ability to get invocation response as stream. Current FDC3 API proposal doesn't define API to get stream of responses\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/006-call-transcription-to-crm.md",
    "content": "---\nid: uc-6\ntitle: \"Use Case 6: Call Transcription to CRM\"\nsidebar_label: 6. Call Transcription to CRM\nlayout: use_case\n---\n\n## Overview\n\nVoice calls contain important financial information which is trapped in the audio.  These data are not easily searchable; human notetakers are prone to error; and post hoc call notes may miss crucial elements.\n\nReal-time transcribed audio data, saved to a CRM or other record keeping system, increases data accuracy and saves users valuable time.\n\n## Persona(s)\n\nAnyone who uses the phone to conduct business and needs to record contents.  Examples include:\n\n1. an analyst calling into an earnings call\n1. salesperson on a call with a customer\n1. a meeting attendee capturing their notes\n\n## Workflows\n\nThis transcription workflow consists of multiple workflows for gathering an audio stream.  Each of these Alternate Inputs below could use traditional telephony, or a software client.  The output of the finished transcription is sent to a CRM.\n\n### During live call\n\n1. During a live call, which might be a group call with multiple users, one user conferences in transcription service.\n1. Parties converse as normal, while transcription service turns audio to text.\n1. At conclusion of call, transcription service sends completed transcript and metadata to CRM\n\n### Post-call dictation\n\n1. After an event is concluded, the user initiates a dictation client (possibly a softphone)\n1. User speaks their notes into a microphone.\n1. Transcription service transcribes audio into text.\n1. Transcription service sends completed transcript and metadata to CRM.\n\n## Interoperability Points\n\nEach of these 2 handoffs:  client → transcription service → CRM , represent interoperability points for FDC3.  All 3 may be from separate providers.\n\nThe transcription service → CRM handoff may have an intermediary step where the user selects the 2nd party in their CRM as target for saving (this may potentially be automated with sufficiently rich metadata), or even which CRM or destination to save the data.\n\n## FDC3 Working groups affected\n\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/007-realtime-trade-ticket-population.md",
    "content": "---\nid: uc-7\ntitle: \"Use Case 7: Real-Time voice trades -> trade ticket population\"\nsidebar_label: \"7. Real-Time voice trades -> trade ticket population\"\nlayout: use_case\n---\n\n## Persona\n- Salesperson / Trader / Broker negotiating a trade via voice (over the phone).\n\n## Workflow\n1. User is on a call with a customer.\n1. User conferences in Quote / Trade service.\n1. DURING the call, user dictates trade/quote prefaced by key phrase (e.g. “Confirm…”) to distinguish final quote from negotiation.\n1. Real-time quote/trade transcription service turns audio into structured data breakdown of trade.\n1. Structured quote/trade data delivered to quote trade capture platform, displayed to user.\n1. User may edit details, or correct errors.\n1. User submits ticket to quote capture service.\n\n## Interoperability Points\nThe service which turns voice into structured text and metadata will need to send this data to a separate trade ticket service via FDC3 intents/contexts.\n\n## FDC3 Working groups affected\n- Intents Working Group\n- Contexts Working Group\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/008-user-launches-multiple-apps-from-a-single-container.md",
    "content": "---\nid: uc-8\ntitle: \"Use Case 8: User launches multiple apps from a single container\"\nsidebar_label: 8. User launches multiple apps from a single container\nlayout: use_case\n---\n\n## Preconditions\nOn the desktop the user is running:\n- Third party research & analytics platform\n- Portfolio Management System\n\n## Workflow 1\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\n\n## Workflow 2\nFrom a button next to a holding in the portfolio management system a user launches four applications from the research and analytics platform into the open workspace\nThe applications open within a single container and all show information on the holding\nSelecting a different holding in the portfolio management system updates the launched layout automatically (it is linked when it is launched)\n\n## Workflow 3\nThe user wants to open 4 apps from the research and analytics platform to find more information on a particular holding\nA menu shows all the available apps that accept the holding in context that can be launched into the workspace\nThe user selects four and has the option to open as floating apps or within a single container\nThe user decides to launch them in a single container\nAn Eikon layout opens with the four apps that the user has selected showing information on the current holding\n\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/009-sales-floor-base-workflow.md",
    "content": "---\nid: uc-9\ntitle: \"Use Case 9: Sales Floor Base Workflow\"\nsidebar_label: 9. Sales Floor Base Workflow\nlayout: use_case\n---\n\n## Overview\nThis use case focus on workflow efficiency and heavy reliant on better tools integration with central focus on a CRM. A CRM application with good analytics is central part in any sales business, enabling its integration with the traditional financial  applications is key to make users life as easy as possible.\n\n## Workflow 1\n1. A phone contact happens, the user is in the office using a physical line (e.g. Turret);\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends a CRM call report popup form is shown prefilled with a NLP prepossessed call summary, call statistics (when, how much time, phone number, etc..) and deals registered; \n>* While aware of the technical challenges for NLP in this scenario, that shouldn't make a huge difference for the FDC3 api layer if other path is chosen for this step.\n1. The user edits if required and saves the call report.\n\n## Workflow 2\n1. A chat contact happens;\n1. The CRM automatically is setup in the page relevant to the customer (lets consider that the CRM is FDC3 compliant);\n1. Relevant Analytical tools are automatically set based on the customer profile (this can include any type of analytics - products, customer history, etc.);\n1. While on the chat it triggers a request for analytics on a specific item delivered by another FDC3 compliant app (e.g. Bond, FX... );\n1. Relevant dealing tools, credit check tools, pricing tools are automatically set based on the customer profile;\n1. A deal is agreed and the user uses the relevant tools to register the deal;\n1. When the call ends, the user can trigger from the chat a CRM call report, a popup is shown prefilled with a NLP prepossessed chat summary and deals registered; \n1. The user edits if required and saves the call report.\n\n## Interoperability Points\n- API\n- Context data\n- App Directory\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/010-quantifying-fdc3-interactions.md",
    "content": "---\nid: uc-10\ntitle: \"Use Case 10: Quantifying FDC3 Interactions\"\nsidebar_label: 10. Quantifying FDC3 Interactions\nlayout: use_case\n---\n\n## Persona\nA technologist enabling users to participate in FDC3 workflows, via a desktop, web, or mobile launcher. This persona could be business or technology focused. \n\n## User Goal\nI would like to quantify the FDC3 interactions applications participate in, so that I can understand cross-application workflows and attribute these interactions to business outcomes.\n\n## Preconditions\nThe end-user's app ecosystem is typically comprised of:\n- an app launcher\n- multiple FDC3 compliant in-house applications, owned by different application development teams\n- multiple FDC3-compliant vendor applications\n\n## Workflow 1\nFor a given application, I can review all FDC3 events it has triggered and resolved, with their associated contexts. For example, intents fired, resolved, and contexts put on channels.\n\n## Workflow 2\nSubject to permissions, I can review the source applications for all FDC3 events my application is resolving, and I can review the resolving applications for all FDC3 events my application is triggering. This lets me attribute incoming and outgoing \"traffic\" to and from my application.\n\n## Workflow 3\nI can correlate FDC3 interactions across multiple applications, in order to understand how apps participate in a user workflow that led to an outcome. This includes all interactions from in-house and vendor apps.\n\n## Interoperability Points\n- App Directory\n- API\n\nNOTES\n- Importance of uniquely identifying applications, across in-house and vendor apps, at scale (what do we think is the expected # of unique apps and interactions we will want to track?).\n- Possibility of a hierarchy of apps where an intent can cascade to apps that are part of a group:\n   - Do we foresee this distinction being necessary?  If so, would it suffice to know the app resolved the intent, and then 'lose' any cascading?  Or would you expect the 'cascading' to itself be an intent with resolution?\n   - Ideally, we would be able to structure the reporting in such a way that consumers of the data could easily select the right level of granularity - ie grouping at different levels of hierarchy (ex: using namespacing?)\n- In workflow 3 (but also consequently in 1, 2), we would we want to correlate interactions between applications or instances of applications? If we have more than one chart app open, for example, and context is passed to both or only one of them, would it be required to differentiate between the two cases?\n   - Same as above - ideally, we would be able to structure the reporting in such a way the consumer of the data could easily process select the right level of granularity\n\n## Adoption into the FDC3 Standard\n\n| Workflow  #   |   Status Against 1.0 Standard | App Directory   | Context & Intents | API |\n| :---------: |   -----  | ----- | ---------| --------- | \n| 1  |  New | -  | -  | -  |\n| 2  |  New | -  | -  | -  |\n| 3  |  New |  - |  - | -  |\n\n## Adoption Metrics & Case Studies\n*To be added: quantitative adoption metrics and qualitative measures of impact (case studies)*\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/011-fine-tuning-interop-with-channels.md",
    "content": "---\nid: uc-11\ntitle: \"Use Case 11: Fine-tuning InterOp with Channels\"\nsidebar_label: 11. Fine-tuning InterOp with Channels\nlayout: use_case\n---\n\n## Persona\nA user in a multi-monitor desktop environment with a fairly hectic, time-sensitive and unpredictable working day based on market movement and interactions with clients and colleagues.\n\n## User Goal\nI want to be able to create \"siloed\" workflows on my desktop so that I can quickly switch context to serve a client or execute a trade while still keep an eye on the general market.\n\n## Preconditions\nThe end-user's app desktop environment consists of:\n- an FDC3 compliant in-house application\n- several FDC3-compliant vendor applications\n\n## Workflow 1\nThe user's organisation maintains a coverage list in the in-house application. When selecting a company in there, the user wants a chart and a news component to update in vendor application 1, an options montage to update in vendor application 2.\n\n## Workflow 2\nIn vendor application 1, the user maintains a personal watchlist. When selecting a company in there, the user wants a research portal in vendor application 3 to update as well as a trading screen in vendor application 4.\n\n## Workflow 3\nIn vendor application 2, the user have a tool for ad-hoc company look ups. When selecting a company there, the user wants a chart and a news component in vendor application 1 to update (not the ones from WF 1), a detailed company report in vendor application 2 and a separate trading screen in vendor application 4 (not the one in WF2).\n\n![Use Case 17 Workflow](/assets/uc17.png)\n\n## Interoperability Points\n- API\n- Context\n- Financial Objects Program\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/meeting-minutes/2020-01-16 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n\n\n## Agenda\n### 1. 2020 Move to GitHub - JT (15 min)\n- Goal: manage all new UCWG content in GitHub in 2020\n\n**Proposal:** how to manage the UCWG content \n- Meeting Minutes \n  - legacy [keep them on confluence and link to them] AGREED - link to be added\n  - new [in github, [this folder](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases/meeting-minutes), we also could create a GitHub Issue template] AGREED - link to be updated\n- Governance Docs [to be refreshed and moved to the [use cases intro](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/use-cases-intro.md) page]  - AGREED to move to intro doc, but need to be reviewed and cleaned up. \n  - Ratifying use cases via GitHub PRs - voting done via GitHub (👍 / 👎 on an issue - see [UC 17](https://github.com/finos/FDC3/pull/153)) rather than Google Groups - AGREED \n- Use Cases \n  - 1. In Review [will be managed via submitted pull requests - see [this](https://github.com/finos/FDC3/pulls?q=is%3Aopen+is%3Apr+label%3Ause-cases)]\n  - 2. Accepted [DONE - listed [here](https://github.com/jonathanteperJPMC/FDC3/tree/master/docs/use-cases)]\n  - 3. Rejected \n  - 4. Deleted \n  - 5. Backlog \n  - Use Case XX: Template [we can create this as a github issue type] - JT to try and prove this works\n- Action Items \n  - to be reviewed and closed out. Relevant ones will be migrated. \n- Process: \n  - One of the participants edits meeting minutes live on a screenshare during the call. All participants on the call review and approve the minutes at the end of the call. Once approved verbally on the call, the meeting minutes PR can be merged. \n\n### 2. UC 17 Vote - Johan (5 min)\n- Voting directly on the PR: https://github.com/finos/FDC3/pull/153\n- APPROVED AND MERGED!\n\n### 3. UCWG Goals and Roadmap - JT (15 min)\n- see proposal [here](https://github.com/jonathanteperJPMC/FDC3/blob/master/docs/fdc3-okrs.md#use-case-working-group)\n- UCWG to review offline and comment\n\n### 4. AOB \n- lean UCWG + new recruits\n- clean up open action items in confluence\n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/meeting-minutes/2020-02-20 uc-wg meeting notes.md",
    "content": "---\n\n---\n\n**Date**: 16 January 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n| Jonathan Teper  | JP Morgan  | jonathanteperJPMC  |\n| Johan Sandersson | Factset | donbasuno |\n| Leslie Spiro | Tick42 |  |\n\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n- [ ] review and clean up governance docs \n- [ ] action items on confluence to be closed or migrated to github\n- [ ] goals and roadmaps to be reviewed offline\n- [ ] JT to try creating a use case issue template \n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/meeting-minutes/2020-03-19 uc-wg meeting notes.md",
    "content": "---\n\n---\n**Meeting not held due to low attendance**\n\n**Date**: 19 March 2020\n\n**Attendees**\n\n| Name  | Organization | GitHub ID  |\n| ------------- | ------------- | ------------- |\n\n## Agenda\n### 1. \n\n\n### 4. AOB \n- \n\n## Decisions Made\n- (see inline)\n\n## Action Items\n\n"
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/overview.md",
    "content": "---\nid: overview\ntitle: Use Cases Overview\nhide_title: true\nsidebar_label: Overview\nlayout: default\n---\n\n# Use Cases Overview\n\n## Goal\n\nDocument and ratify business use cases that drive the standards created under the other FDC3 working groups: Intents Working Group, App Directory Working Group, Context Data Working Group, and API Working Group.\n\n## Charter\n\nThe goal of FDC3 is to create standards for desktop application interoperability in the financial industry. For these standards to be successful we need ensure they satisfy a set of foundational use cases and requirements defined and validated by the program participants. These use cases must represent the interop needs of the 40+ members of FDC3 as a sample of the financial industry as a whole. The remaining working groups Context Data, App Directory, Intents and APIs should use the use cases as the basis for each set of standards.\n\nUntil this point the existing working groups have focused on the functional requirements for interop standards with specifications based on assumptions of what is required. To ensure that the standards will enable the scalable interop interactions that we want, we need to validate these assumptions. This should not delay the work of the existing working groups, but happen in parallel with the requirements maintained as the program matures.\n\nUnlike the other working groups, 'Use Cases' should provide requirements only not solutions. The requirements and use cases defined should not be specific to a handful of products that are represented within the working group, but apply to the workflows present across the financial industry.\n\n![Use Cases diagram](/assets/use-cases.png)\n\n\n## Join us\nJoin our mailing-lists and bi-weekly meetings on WebEx. Check the [Wiki documentation page](https://finosfoundation.atlassian.net/wiki/spaces/FDC3/pages/169738241/Use+Case+Working+Group) for details."
  },
  {
    "path": "website/versioned_docs/version-2.2/use-cases/readme.md",
    "content": "---\n\n---\n# Overview \nHere are business use cases that have been documented and ratified by the Use Cases Working Group\n\n# Adoption of Use Cases into the FDC3 Standard\n\n**Use Cases Accepted onto Roadmap of Standards or Implemented**\n\n| Use Cases                                                           | Count         | %       |\n| -------------                                                       |:-------------:| :----:  |\n| 001-equity-sell-side-trader                                         | \t2 / 5       |   40%   | \n| 002-buy-side-portfolio-manager                                      | \t0 / 3\t      |   33%   | \n| 003-inhouse-cross-platform-launcher                                 | \t0 / 8       |    0%   | \n| 004-client-side-fx-trader                                           | \t0 / 1\t      |    0%   | \n| 005-buy-side-treasurer                                              | \t0 / 3\t      |    0%   | \n| 009-call-transcription-to-crm                                       | \t0 / 2\t      |    0%   | \n| 010-realtime-trade-ticket-population                                | \t0 / 1\t      |    0%   | \n| 013-user-launches-multiple-apps-from-a-single-container             | \t0 / 3\t      |    0%   | \n| 015-sales-floor-base-workflow                                       | \t0 / 2\t      |    0%   | \n| 016-quantifying-fdc3-interactions                                   | \t0 / 3\t      |    0%   | \n| total                                                               | \t2 / 31      |  6.5%   | \n\n\n\n**Summary**\n\n| Status                                | Count         | %       |\n| -------------                         |:-------------:| :----:  |\n| New                                   | \t24\t        |   77.5%   | \n| Proposed                              | \t5           | \t16%   | \n| **Accepted onto Roadmap of Standard** | \t0           | \t**0%**  | \n| **Implemented**                       | \t2         \t|  **6.5%** | \n| Rejected                              | \t0           | \t0%    | \n| N/R                                   | \t3           |         | \t\n| Total (excl. N/R)                     | \t31          | \t100%  | \n"
  },
  {
    "path": "website/versioned_docs/version-2.2/why-fdc3.md",
    "content": "---\nid: why-fdc3\nsidebar_label: Why FDC3?\ntitle: Why FDC3?\n---\n\n## Why look for FDC3-enabled applications?\n\nYou want your business to move fast and use best of breed applications. Application integration has traditionally been a time consuming and costly exercise, meaning that once a set of applications supporting a workflow was established, changing parts of the workflow without very good reason was a no-go.\n\nThe main goal of FDC3 is to standardize how applications communicate, without having defined inter-application workflows prior to being deployed. Applications that are FDC3-enabled can take part in a workflow on the desktop without any coding or manual integration, allowing you to replace one application with another application serving the same functions to the desktop (in FDC3 terms - supporting the same Intents and Context).\n\n## Why should I FDC3-enable my applications?\n\nThere is a trend towards breaking up monolithic desktop applications, replacing them with adaptable workflows which involve the collaboration of multiple best-of-breed applications. Still, much of the integration on the desktop is done by the actual end-user; copy/paste between applications, exporting/importing CSV files etc..\n\nEvery application that has manual user input is a candidate for being FDC3-enabled, being able to demonstrate that your application can effectively take part in a workflow (without manual dual-entry or other tedious operations) is a easy route to happier users. Allowing your application to reach out to others is another way of extending the power of your offering; your app might not offer charting, but can let the end-user chart in an FDC3-enabled companion application based on context passed from your own app.\n\n## Why should my development team look at adopting FDC3?\n\nDeploying effective end-user workflows with as little development effort as possible, should be the goal for all internal/platform integration development teams. Implementing or developing on a platform that is FDC3-enabled, if done right, results in more bang for the buck. FDC3 is all about (re)usability and low-touch integration. With an [App directory](app-directory/overview) in place and a platform to develop on, each new enabled app broadens the value of the workflow offering.\n"
  },
  {
    "path": "website/versioned_sidebars/version-1.0-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"fdc3-charter\",\n      \"why-fdc3\",\n      \"fdc3-compliance\",\n      \"fdc3-standard\"\n    ],\n    \"API\": [\n      \"api/api-intro\",\n      \"api/api-spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"API Reference\",\n        \"items\": [\n          \"api/DesktopAgent\",\n          \"api/Context\",\n          \"api/Errors\"\n        ]\n      }\n    ],\n    \"Intents\": [\n      \"intents-intro\",\n      \"intents-spec\"\n    ],\n    \"Context Data\": [\n      \"context-intro\",\n      \"context-spec\"\n    ],\n    \"App Directory\": [\n      \"appd-intro\",\n      \"appd-discovery\",\n      \"appd-use\",\n      \"appd-spec\"\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-13\",\n      \"use-cases/uc-15\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versioned_sidebars/version-1.1-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"fdc3-charter\",\n      \"why-fdc3\",\n      \"fdc3-compliance\",\n      \"fdc3-standard\"\n    ],\n    \"API\": [\n      \"api/overview\",\n      \"api/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Interfaces\",\n        \"items\": [\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/Listener\",\n          \"api/ref/AppIntent\",\n          \"api/ref/IntentResolution\",\n          \"api/ref/AppMetadata\",\n          \"api/ref/IntentMetadata\",\n          \"api/ref/DisplayMetadata\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Types\",\n        \"items\": [\n          \"api/ref/Context\",\n          \"api/ref/ContextHandler\",\n          \"api/ref/OpenError\",\n          \"api/ref/ResolveError\",\n          \"api/ref/ChannelError\"\n        ]\n      }\n    ],\n    \"Intents\": [\n      \"intents/overview\",\n      \"intents/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Reference\",\n        \"items\": [\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewContact\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewInstrument\"\n        ]\n      }\n    ],\n    \"Context Data\": [\n      \"context/overview\",\n      \"context/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Reference\",\n        \"items\": [\n          \"context/ref/Context\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Organization\",\n          \"context/ref/Country\",\n          \"context/ref/Position\",\n          \"context/ref/Portfolio\"\n        ]\n      }\n    ],\n    \"App Directory\": [\n      \"app-directory/overview\",\n      \"app-directory/discovery\",\n      \"app-directory/usage\",\n      \"app-directory/spec\"\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-13\",\n      \"use-cases/uc-15\",\n      \"use-cases/uc-16\",\n      \"use-cases/uc-17\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versioned_sidebars/version-1.2-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"supported-platforms\",\n      \"why-fdc3\",\n      \"fdc3-charter\",\n      \"fdc3-compliance\",\n      \"fdc3-standard\"\n    ],\n    \"API\": [\n      \"api/overview\",\n      \"api/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Reference\",\n        \"items\": [\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/Globals\",\n          \"api/ref/Types\",\n          \"api/ref/Metadata\",\n          \"api/ref/Errors\"\n        ]\n      }\n    ],\n    \"Intents\": [\n      \"intents/overview\",\n      \"intents/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Reference\",\n        \"items\": [\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewContact\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewInstrument\"\n        ]\n      }\n    ],\n    \"Context Data\": [\n      \"context/overview\",\n      \"context/spec\",\n      {\n        \"type\": \"category\",\n        \"label\": \"Reference\",\n        \"items\": [\n          \"context/ref/Context\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Organization\",\n          \"context/ref/Country\",\n          \"context/ref/Position\",\n          \"context/ref/Portfolio\"\n        ]\n      }\n    ],\n    \"App Directory\": [\n      \"app-directory/overview\",\n      \"app-directory/discovery\",\n      \"app-directory/usage\",\n      \"app-directory/spec\"\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-13\",\n      \"use-cases/uc-15\",\n      \"use-cases/uc-16\",\n      \"use-cases/uc-17\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versioned_sidebars/version-2.0-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"why-fdc3\",\n      \"fdc3-charter\"\n    ],\n    \"FDC3 Standard\": [\n      \"fdc3-standard\",\n      \"fdc3-compliance\",\n      \"fdc3-glossary\",\n      \"references\",\n      \"supported-platforms\",\n      {\n        \"type\": \"category\",\n        \"label\": \"API Part\",\n        \"items\": [\n          \"api/spec\",\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/PrivateChannel\",\n          \"api/ref/Globals\",\n          \"api/ref/Types\",\n          \"api/ref/Metadata\",\n          \"api/ref/Errors\",\n          {\n            \"type\": \"category\",\n            \"label\": \"Conformance Tests\",\n            \"items\": [\n              \"api/conformance/Conformance-Overview\",\n              \"api/conformance/Basic-Tests\",\n              \"api/conformance/App-Channel-Tests\",\n              \"api/conformance/User-Channel-Tests\",\n              \"api/conformance/Open-Tests\",\n              \"api/conformance/Intents-Tests\",\n              \"api/conformance/Metadata-Tests\"\n            ]\n          }\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"App Directory Part\",\n        \"items\": [\n          \"app-directory/overview\",\n          \"app-directory/spec\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Intents Part\",\n        \"items\": [\n          \"intents/spec\",\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/StartEmail\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewHoldings\",\n          \"intents/ref/ViewInstrument\",\n          \"intents/ref/ViewInteractions\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewOrders\",\n          \"intents/ref/ViewProfile\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewResearch\",\n          \"intents/ref/ViewContact\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Context Data Part\",\n        \"items\": [\n          \"context/spec\",\n          \"context/ref/Context\",\n          \"context/ref/Chart\",\n          \"context/ref/ChatInitSettings\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Country\",\n          \"context/ref/Currency\",\n          \"context/ref/Email\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Nothing\",\n          \"context/ref/Organization\",\n          \"context/ref/Portfolio\",\n          \"context/ref/Position\",\n          \"context/ref/TimeRange\",\n          \"context/ref/Valuation\"\n        ]\n      }\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-13\",\n      \"use-cases/uc-15\",\n      \"use-cases/uc-16\",\n      \"use-cases/uc-17\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versioned_sidebars/version-2.1-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"why-fdc3\",\n      \"fdc3-charter\"\n    ],\n    \"FDC3 Standard\": [\n      \"fdc3-standard\",\n      \"fdc3-compliance\",\n      \"fdc3-glossary\",\n      \"references\",\n      \"supported-platforms\",\n      {\n        \"type\": \"category\",\n        \"label\": \"API Part\",\n        \"items\": [\n          \"api/spec\",\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/PrivateChannel\",\n          \"api/ref/Globals\",\n          \"api/ref/Types\",\n          \"api/ref/Metadata\",\n          \"api/ref/Errors\",\n          {\n            \"type\": \"category\",\n            \"label\": \"Conformance Tests\",\n            \"items\": [\n              \"api/conformance/Conformance-Overview\",\n              \"api/conformance/Basic-Tests\",\n              \"api/conformance/App-Channel-Tests\",\n              \"api/conformance/User-Channel-Tests\",\n              \"api/conformance/Open-Tests\",\n              \"api/conformance/Intents-Tests\",\n              \"api/conformance/Metadata-Tests\"\n            ]\n          }\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"App Directory Part\",\n        \"items\": [\n          \"app-directory/overview\",\n          \"app-directory/spec\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Intents Part\",\n        \"items\": [\n          \"intents/spec\",\n          \"intents/ref/CreateInteraction\",\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/StartEmail\",\n          \"intents/ref/SendChatMessage\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewChat\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewHoldings\",\n          \"intents/ref/ViewInstrument\",\n          \"intents/ref/ViewInteractions\",\n          \"intents/ref/ViewMessages\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewOrders\",\n          \"intents/ref/ViewProfile\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewResearch\",\n          \"intents/ref/ViewContact\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Context Data Part\",\n        \"items\": [\n          \"context/spec\",\n          \"context/ref/Context\",\n          \"context/ref/Action\",\n          \"context/ref/Chart\",\n          \"context/ref/ChatInitSettings\",\n          \"context/ref/ChatMessage\",\n          \"context/ref/ChatRoom\",\n          \"context/ref/ChatSearchCriteria\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Country\",\n          \"context/ref/Currency\",\n          \"context/ref/Email\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Interaction\",\n          \"context/ref/Message\",\n          \"context/ref/Nothing\",\n          \"context/ref/Order\",\n          \"context/ref/OrderList\",\n          \"context/ref/Organization\",\n          \"context/ref/Portfolio\",\n          \"context/ref/Position\",\n          \"context/ref/Product\",\n          \"context/ref/TimeRange\",\n          \"context/ref/Trade\",\n          \"context/ref/TradeList\",\n          \"context/ref/TransactionResult\",\n          \"context/ref/Valuation\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Agent Bridging Part\",\n        \"items\": [\n          \"agent-bridging/spec\",\n          \"agent-bridging/ref/broadcast\",\n          \"agent-bridging/ref/findInstances\",\n          \"agent-bridging/ref/findIntent\",\n          \"agent-bridging/ref/findIntentsByContext\",\n          \"agent-bridging/ref/getAppMetadata\",\n          \"agent-bridging/ref/open\",\n          \"agent-bridging/ref/PrivateChannel.broadcast\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerAdded\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerRemoved\",\n          \"agent-bridging/ref/PrivateChannel.onAddContextListener\",\n          \"agent-bridging/ref/PrivateChannel.onDisconnect\",\n          \"agent-bridging/ref/PrivateChannel.onUnsubscribe\",\n          \"agent-bridging/ref/raiseIntent\"\n        ]\n      }\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-13\",\n      \"use-cases/uc-15\",\n      \"use-cases/uc-16\",\n      \"use-cases/uc-17\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versioned_sidebars/version-2.2-sidebars.json",
    "content": "{\n  \"docs\": {\n    \"Getting Started\": [\n      \"fdc3-intro\",\n      \"why-fdc3\",\n      \"fdc3-charter\"\n    ],\n    \"FDC3 Standard\": [\n      \"fdc3-standard\",\n      \"fdc3-compliance\",\n      \"fdc3-glossary\",\n      \"references\",\n      {\n        \"type\": \"category\",\n        \"label\": \"API Part\",\n        \"items\": [\n          \"api/spec\",\n          \"api/supported-platforms\",\n          \"api/ref/GetAgent\",\n          \"api/ref/DesktopAgent\",\n          \"api/ref/Channel\",\n          \"api/ref/PrivateChannel\",\n          \"api/ref/Types\",\n          \"api/ref/Metadata\",\n          \"api/ref/Errors\",\n          \"api/ref/Events\",\n          {\n            \"type\": \"category\",\n            \"label\": \"Desktop Agent Specs\",\n            \"items\": [\n              \"api/specs/preloadDesktopAgents\",\n              \"api/specs/browserResidentDesktopAgents\",\n              \"api/specs/webConnectionProtocol\",\n              \"api/specs/desktopAgentCommunicationProtocol\"\n            ]\n          },\n          {\n            \"type\": \"category\",\n            \"label\": \"Conformance Tests\",\n            \"items\": [\n              \"api/conformance/Conformance-Overview\",\n              \"api/conformance/Basic-Tests\",\n              \"api/conformance/App-Channel-Tests\",\n              \"api/conformance/User-Channel-Tests\",\n              \"api/conformance/Open-Tests\",\n              \"api/conformance/Intents-Tests\",\n              \"api/conformance/Metadata-Tests\"\n            ]\n          }\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"App Directory Part\",\n        \"items\": [\n          \"app-directory/overview\",\n          \"app-directory/spec\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Intents Part\",\n        \"items\": [\n          \"intents/spec\",\n          \"intents/ref/CreateInteraction\",\n          \"intents/ref/CreateOrUpdateProfile\",\n          \"intents/ref/SendChatMessage\",\n          \"intents/ref/StartCall\",\n          \"intents/ref/StartChat\",\n          \"intents/ref/StartEmail\",\n          \"intents/ref/ViewAnalysis\",\n          \"intents/ref/ViewChart\",\n          \"intents/ref/ViewChat\",\n          \"intents/ref/ViewContact\",\n          \"intents/ref/ViewHoldings\",\n          \"intents/ref/ViewInstrument\",\n          \"intents/ref/ViewInteractions\",\n          \"intents/ref/ViewMessages\",\n          \"intents/ref/ViewNews\",\n          \"intents/ref/ViewOrders\",\n          \"intents/ref/ViewProfile\",\n          \"intents/ref/ViewQuote\",\n          \"intents/ref/ViewResearch\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Context Data Part\",\n        \"items\": [\n          \"context/spec\",\n          \"context/ref/Action\",\n          \"context/ref/Chart\",\n          \"context/ref/ChatInitSettings\",\n          \"context/ref/ChatMessage\",\n          \"context/ref/ChatRoom\",\n          \"context/ref/ChatSearchCriteria\",\n          \"context/ref/Contact\",\n          \"context/ref/ContactList\",\n          \"context/ref/Country\",\n          \"context/ref/Currency\",\n          \"context/ref/Email\",\n          \"context/ref/FileAttachment\",\n          \"context/ref/Instrument\",\n          \"context/ref/InstrumentList\",\n          \"context/ref/Interaction\",\n          \"context/ref/Message\",\n          \"context/ref/Nothing\",\n          \"context/ref/Order\",\n          \"context/ref/OrderList\",\n          \"context/ref/Organization\",\n          \"context/ref/Portfolio\",\n          \"context/ref/Position\",\n          \"context/ref/Product\",\n          \"context/ref/TimeRange\",\n          \"context/ref/Trade\",\n          \"context/ref/TradeList\",\n          \"context/ref/TransactionResult\",\n          \"context/ref/Valuation\"\n        ]\n      },\n      {\n        \"type\": \"category\",\n        \"label\": \"Agent Bridging Part\",\n        \"items\": [\n          \"agent-bridging/spec\",\n          \"agent-bridging/ref/broadcast\",\n          \"agent-bridging/ref/findInstances\",\n          \"agent-bridging/ref/findIntent\",\n          \"agent-bridging/ref/findIntentsByContext\",\n          \"agent-bridging/ref/getAppMetadata\",\n          \"agent-bridging/ref/open\",\n          \"agent-bridging/ref/PrivateChannel.broadcast\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerAdded\",\n          \"agent-bridging/ref/PrivateChannel.eventListenerRemoved\",\n          \"agent-bridging/ref/PrivateChannel.onAddContextListener\",\n          \"agent-bridging/ref/PrivateChannel.onDisconnect\",\n          \"agent-bridging/ref/PrivateChannel.onUnsubscribe\",\n          \"agent-bridging/ref/raiseIntent\"\n        ]\n      }\n    ]\n  },\n  \"use-cases\": {\n    \"Use Cases\": [\n      \"use-cases/overview\",\n      \"use-cases/uc-1\",\n      \"use-cases/uc-2\",\n      \"use-cases/uc-3\",\n      \"use-cases/uc-4\",\n      \"use-cases/uc-5\",\n      \"use-cases/uc-6\",\n      \"use-cases/uc-7\",\n      \"use-cases/uc-8\",\n      \"use-cases/uc-9\",\n      \"use-cases/uc-10\",\n      \"use-cases/uc-11\"\n    ]\n  }\n}\n"
  },
  {
    "path": "website/versions.json",
    "content": "[\n  \"2.2\",\n  \"2.1\",\n  \"2.0\",\n  \"1.2\",\n  \"1.1\",\n  \"1.0\"\n]\n"
  }
]